diff options
Diffstat (limited to '')
234 files changed, 67096 insertions, 0 deletions
diff --git a/web/Makefile.am b/web/Makefile.am new file mode 100644 index 0000000..c4e5fd5 --- /dev/null +++ b/web/Makefile.am @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + api \ + gui \ + server \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + gui/confluence/README.md \ + gui/custom/README.md \ + $(NULL) diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..c110ef6 --- /dev/null +++ b/web/README.md @@ -0,0 +1,28 @@ +# Web dashboards overview + +The default port is 19999; for example, to access the dashboard on localhost, use: http://localhost:19999 + +To view Netdata collected data you access its **[REST API v1](api/)**. + +For our convenience, Netdata provides 2 more layers: + +1. The `dashboard.js` javascript library that allows us to design custom dashboards using plain HTML. For information on creating custom dashboards, see **[Custom Dashboards](gui/custom/)** and **[Atlassian Confluence Dashboards](gui/confluence/)** + +2. Ready to be used web dashboards that render all the charts a Netdata server maintains. + +## Customizing the standard dashboards + +Charts information is stored at /usr/share/netdata/web/[dashboard_info.js](gui/dashboard_info.js). This file includes information that is rendered on the dashboard, controls chart colors, section and subsection heading, titles, etc. + +If you change that file, your changes will be overwritten when Netdata is updated. You can preserve your settings by creating a new such file (there is /usr/share/netdata/web/[dashboard_info_custom.example.js](gui/dashboard_info_custom_example.js) you can use to start with). + +You have to copy the example file under a new name, so that it will not be overwritten with Netdata updates. + +To configure your info file set in netdata.conf: + +``` +[web] + custom dashboard_info.js = your_file_name.js +``` + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/Makefile.am b/web/api/Makefile.am new file mode 100644 index 0000000..0f54817 --- /dev/null +++ b/web/api/Makefile.am @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + badges \ + queries \ + exporters \ + formatters \ + health \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) + +dist_web_DATA = \ + netdata-swagger.yaml \ + netdata-swagger.json \ + $(NULL) diff --git a/web/api/README.md b/web/api/README.md new file mode 100644 index 0000000..44afbc9 --- /dev/null +++ b/web/api/README.md @@ -0,0 +1,21 @@ +# API + +## Netdata REST API + +The complete documentation of the netdata API is available at the **[Swagger Editor](https://editor.swagger.io/?url=https://raw.githubusercontent.com/netdata/netdata/master/web/api/netdata-swagger.yaml)**. + +If your prefer it over the Swagger Editor, you can also use **[Swagger UI](https://registry.my-netdata.io/swagger/#!/default/get_data)**. This however does not provide all the information available. + +## Google charts API + +netdata is a [Google Visualization API datatable and datasource provider](https://developers.google.com/chart/interactive/docs/reference), so it can directly be used with [Google Charts](https://developers.google.com/chart/interactive/docs/). + +Check this [single chart, jsfiddle example](https://jsfiddle.net/ktsaou/ensu4uws/9/): + +![image](https://cloud.githubusercontent.com/assets/2662304/23824762/1e236b84-0685-11e7-89f4-06fdf67d873a.png) + +and this [multi chart, jsfiddle example](https://jsfiddle.net/ktsaou/L5y2eqp2/): + +![image](https://cloud.githubusercontent.com/assets/2662304/23824766/31a4a68c-0685-11e7-8429-8327cab64be2.png) + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/badges/Makefile.am b/web/api/badges/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/badges/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/badges/README.md b/web/api/badges/README.md new file mode 100644 index 0000000..6884cc1 --- /dev/null +++ b/web/api/badges/README.md @@ -0,0 +1,308 @@ +# Netdata badges + +**Badges are cool!** + +Netdata can generate badges for any chart and any dimension at any time-frame. Badges come in `SVG` and can be added to any web page using an `<IMG>` HTML tag. + +**Netdata badges are powerful**! + +Given that netdata collects from **1.000** to **5.000** metrics per server (depending on the number of network interfaces, disks, cpu cores, applications running, users logged in, containers running, etc) and that netdata already has data reduction/aggregation functions embedded, the badges can be quite powerful. + +For each metric/dimension and for arbitrary time-frames badges can show **min**, **max** or **average** value, but also **sum** or **incremental-sum** to have their **volume**. + +For example, there is [a chart in netdata that shows the current requests/s of nginx](http://london.my-netdata.io/#nginx_local_nginx). Using this chart alone we can show the following badges (we could add more time-frames, like **today**, **yesterday**, etc): + +<a href="https://registry.my-netdata.io/#nginx_local_nginx"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=nginx_local.connections&dimensions=active&value_color=grey:null%7Cblue&label=nginx%20active%20connections%20now&units=null&precision=0"/></a> <a href="https://registry.my-netdata.io/#nginx_local_nginx"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=nginx_local.connections&dimensions=active&after=-3600&value_color=orange&label=last%20hour%20average&units=null&options=unaligned&precision=0"/></a> <a href="https://registry.my-netdata.io/#nginx_local_nginx"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=nginx_local.connections&dimensions=active&group=max&after=-3600&value_color=red&label=last%20hour%20max&units=null&options=unaligned&precision=0"/></a> + +Similarly, there is [a chart that shows outbound bandwidth per class](http://london.my-netdata.io/#tc_eth0), using QoS data. So it shows `kilobits/s` per class. Using this chart we can show: + +<a href="https://registry.my-netdata.io/#tc_eth0"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=tc.world_out&dimensions=web_server&value_color=green&label=web%20server%20sends%20now&units=kbps"/></a> <a href="https://registry.my-netdata.io/#tc_eth0"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=tc.world_out&dimensions=web_server&after=-86400&options=unaligned&group=sum÷=8388608&value_color=blue&label=web%20server%20sent%20today&units=GB"/></a> + +The right one is a **volume** calculation. Netdata calculated the total of the last 86.400 seconds (a day) which gives `kilobits`, then divided it by 8 to make it KB, then by 1024 to make it MB and then by 1024 to make it GB. Calculations like this are quite accurate, since for every value collected, every second, netdata interpolates it to second boundary using microsecond calculations. + +Let's see a few more badge examples (they come from the [netdata registry](../../../registry/)): + +- **cpu usage of user `root`** (you can pick any user; 100% = 1 core). This will be `green <10%`, `yellow <20%`, `orange <50%`, `blue <100%` (1 core), `red` otherwise (you define thresholds and colors on the URL). + + <a href="https://registry.my-netdata.io/#apps_cpu"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=users.cpu&dimensions=root&value_color=grey:null%7Cgreen%3C10%7Cyellow%3C20%7Corange%3C50%7Cblue%3C100%7Cred&label=root%20user%20cpu%20now&units=%25"></img></a> <a href="https://registry.my-netdata.io/#apps_cpu"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=users.cpu&dimensions=root&after=-3600&value_color=grey:null%7Cgreen%3C10%7Cyellow%3C20%7Corange%3C50%7Cblue%3C100%7Cred&label=root%20user%20average%20cpu%20last%20hour&units=%25"></img></a> + +- **mysql queries per second** + + <a href="https://registry.my-netdata.io/#mysql_local"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=mysql_local.queries&dimensions=questions&label=mysql%20queries%20now&value_color=red&units=%5Cs"></img></a> <a href="https://registry.my-netdata.io/#mysql_local"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=mysql_local.queries&dimensions=questions&after=-3600&options=unaligned&group=sum&label=mysql%20queries%20this%20hour&value_color=green&units=null"></img></a> <a href="https://registry.my-netdata.io/#mysql_local"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=mysql_local.queries&dimensions=questions&after=-86400&options=unaligned&group=sum&label=mysql%20queries%20today&value_color=blue&units=null"></img></a> + + niche ones: **mysql SELECT statements with JOIN, which did full table scans**: + + <a href="https://registry.my-netdata.io/#mysql_local_issues"><img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=mysql_local.join_issues&dimensions=scan&after=-3600&label=full%20table%20scans%20the%20last%20hour&value_color=orange&group=sum&units=null"></img></a> + +--- + +> So, every single line on the charts of a [netdata dashboard](http://london.my-netdata.io/), can become a badge and this badge can calculate **average**, **min**, **max**, or **volume** for any time-frame! And you can also vary the badge color using conditions on the calculated value. + +--- + +## How to create badges + +The basic URL is `http://your.netdata:19999/api/v1/badge.svg?option1&option2&option3&...`. + +Here is what you can put for `options` (these are standard netdata API options): + +- `chart=CHART.NAME` + + The chart to get the values from. + + **This is the only parameter required** and with just this parameter, netdata will return the sum of the latest values of all chart dimensions. + + Example: + +```html + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu"></img> + </a> +``` + + Which produces this: + + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu"></img> + </a> + +- `alarm=NAME` + + Render the current value and status of an alarm linked to the chart. This option can be ignored if the badge to be generated is not related to an alarm. + + The current value of the alarm will be rendered. The color of the badge will indicate the status of the alarm. + + For alarm badges, **both `chart` and `alarm` parameters are required**. + +- `dimensions=DIMENSION1|DIMENSION2|...` + + The dimensions of the chart to use. If you don't set any dimension, all will be used. When multiple dimensions are used, netdata will sum their values. You can append `options=absolute` if you want this sum to convert all values to positive before adding them. + + Pipes in HTML have to escaped with `%7C`. + + Example: + +```html + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&dimensions=system%7Cnice"></img> + </a> +``` + + Which produces this: + + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&dimensions=system%7Cnice"></img> + </a> + +- `before=SECONDS` and `after=SECONDS` + + The timeframe. These can be absolute unix timestamps, or relative to now, number of seconds. By default `before=0` and `after=-1` (1 second in the past). + + To get the last minute set `after=-60`. This will give the average of the last complete minute (XX:XX:00 - XX:XX:59). + + To get the max of the last hour set `after=-3600&group=max`. This will give the maximum value of the last complete hour (XX:00:00 - XX:59:59) + + Example: + +```html + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60"></img> + </a> +``` + + Which produces the average of last complete minute (XX:XX:00 - XX:XX:59): + + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60"></img> + </a> + + While this is the previous minute (one minute before the last one, again aligned XX:XX:00 - XX:XX:59): + +```html + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&before=-60&after=-60"></img> + </a> +``` + + It produces this: + + <a href="#"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&before=-60&after=-60"></img> + </a> + +- `group=min` or `group=max` or `group=average` (the default) or `group=sum` or `group=incremental-sum` + + If netdata will have to reduce (aggregate) the data to calculate the value, which aggregation method to use. + + - `max` will find the max value for the timeframe. This works on both positive and negative dimensions. It will find the most extreme value. + + - `min` will find the min value for the timeframe. This works on both positive and negative dimensions. It will find the number closest to zero. + + - `average` will calculate the average value for the timeframe. + + - `sum` will sum all the values for the timeframe. This is nice for finding the volume of dimensions for a timeframe. So if you have a dimension that reports `X per second`, you can find the volume of the dimension in a timeframe, by adding its values in that timeframe. + + - `incremental-sum` will sum the difference of each value to its next. Let's assume you have a dimension that does not measure the rate of something, but the absolute value of it. So it has values like this "1, 5, 3, 7, 4". `incremental-sum` will calculate the difference of adjacent values. In this example, they will be `(5 - 1) + (3 - 5) + (7 - 3) + (4 - 7) = 3` (which is equal to the last value minus the first = 4 - 1). + +- `options=opt1|opt2|opt3|...` + + These fine tune various options of the API. Here is what you can use for badges (the API has more option, but only these are useful for badges): + + - `percentage`, instead of returning the value, calculate the percentage of the sum of the selected dimensions, versus the sum of all the dimensions of the chart. This also sets the units to `%`. + + - `absolute` or `abs`, turn all values positive and then sum them. + + - `display_absolute` or `display-absolute`, to use the signed value during color calculation, but display the absolute value on the badge. + + - `min2max`, when multiple dimensions are given, do not sum them, but take their `max - min`. + + - `unaligned`, when data are reduced / aggregated (e.g. the request is about the average of the last minute, or hour), netdata by default aligns them so that the charts will have a constant shape (so average per minute returns always XX:XX:00 - XX:XX:59). Setting the `unaligned` option, netdata will aggregate data without any alignment, so if the request is for 60 seconds, it will aggregate the latest 60 seconds of collected data. + +These are options dedicated to badges: + +- `label=TEXT` + + The label of the badge. + +- `units=TEXT` + + The units of the badge. If you want to put a `/`, please put a `\`. This is because netdata allows badges parameters to be given as path in URL, instead of query string. You can also use `null` or `empty` to show it without any units. + + The units `seconds`, `minutes` and `hours` trigger special formatting. The value has to be in this unit, and netdata will automatically change it to show a more pretty duration. + +- `multiply=NUMBER` + + Multiply the value with this number. The default is `1`. + +- `divide=NUMBER` + + Divide the value with this number. The default is `1`. + +- `label_color=COLOR` + + The color of the label (the left part). You can use any HTML color, include `#NNN` and `#NNNNNN`. The following colors are defined in netdata (and you can use them by name): `green`, `brightgreen`, `yellow`, `yellowgreen`, `orange`, `red`, `blue`, `grey`, `gray`, `lightgrey`, `lightgray`. These are taken from https://github.com/badges/shields so they are compatible with standard badges. + +- `value_color=COLOR:null|COLOR<VALUE|COLOR>VALUE|COLOR>=VALUE|COLOR<=VALUE|...` + + You can add a pipe delimited list of conditions to pick the color. The first matching (left to right) will be used. + + Example: `value_color=grey:null|green<10|yellow<100|orange<1000|blue<10000|red` + + The above will set `grey` if no value exists (not collected within the `gap when lost iterations above` in netdata.conf for the chart), `green` if the value is less than 10, `yellow` if the value is less than 100, etc up to `red` which will be used if no other conditions match. + + The supported operators are `<`, `>`, `<=`, `>=`, `=` (or `:`) and `!=` (or `<>`). + +- `precision=NUMBER` + + The number of decimal digits of the value. By default netdata will add: + + - no decimal digits for values > 1000 + - 1 decimal digit for values > 100 + - 2 decimal digits for values > 1 + - 3 decimal digits for values > 0.1 + - 4 decimal digits for values <= 0.1 + + Using the `precision=NUMBER` you can set your preference per badge. + +- `scale=XXX` + + This option scales the svg image. It accepts values above or equal to 100 (100% is the default scale). For example, lets get a few different sizes: + + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=100"></img> original<br/> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=125"></img> `scale=125`<br/> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=150"></img> `scale=150`<br/> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=175"></img> `scale=175`<br/> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=system.cpu&after=-60&scale=200"></img> `scale=200` + + +- `refresh=auto` or `refresh=SECONDS` + + This option enables auto-refreshing of images. netdata will send the HTTP header `Refresh: SECONDS` to the web browser, thus requesting automatic refresh of the images at regular intervals. + + `auto` will calculate the proper `SECONDS` to avoid unnecessary refreshes. If `SECONDS` is zero, this feature is disabled (it is also disabled by default). + + Auto-refreshing like this, works only if you access the badge directly. So, you may have to put it an `embed` or `iframe` for it to be auto-refreshed. Use something like this: + +```html +<embed src="BADGE_URL" type="image/svg+xml" height="20" /> +``` + + Another way is to use javascript to auto-refresh them. You can auto-refresh all the netdata badges on a page using javascript. You have to add a class to all the netdata badges, like this `<img class="netdata-badge" src="..."/>`. Then add this javascript code to your page (it requires jquery): + +```html +<script> + var NETDATA_BADGES_AUTOREFRESH_SECONDS = 5; + function refreshNetdataBadges() { + var now = new Date().getTime().toString(); + $('.netdata-badge').each(function() { + this.src = this.src.replace(/\&_=\d*/, '') + '&_=' + now; + }); + setTimeout(refreshNetdataBadges, NETDATA_BADGES_AUTOREFRESH_SECONDS * 1000); + } + setTimeout(refreshNetdataBadges, NETDATA_BADGES_AUTOREFRESH_SECONDS * 1000); +</script> +``` + +A more advanced badges refresh method is to include `http://your.netdata.ip:19999/refresh-badges.js` in your page. For more information and use example, [check this](../../gui/refresh-badges.js). + +--- + +## Escaping URLs + +Keep in mind that if you add badge URLs to your HTML pages you have to escape the special characters: + +character|name|escape sequence +:-------:|:--:|:-------------: +` `|space (in labels and units)|`%20` +` # `|hash (for colors)|`%23` +` % `|percent (in units)|`%25` +` < `|less than|`%3C` +` > `|greater than|`%3E` +` \ `|backslash (when you need a `/`)|`%5C` +` \| `|pipe (delimiting parameters)|`%7C` + +## FAQ + +#### Is it fast? +On modern hardware, netdata can generate about **2.000 badges per second per core**, before noticing any delays. It generates a badge in about half a millisecond! + +Of course these timing are for badges that use recent data. If you need badges that do calculations over long durations (a day, or more), timing will differ. netdata logs its timings at its `access.log`, so take a look there before adding a heavy badge on a busy web site. Of course, you can cache such badges or have a cron job get them from netdata and save them at your web server at regular intervals. + + +#### Embedding badges in github + +You have 2 options a) SVG images with markdown and b) SVG images with HTML (directly in .md files). + +For example, this is the cpu badge shown above: + +- Markdown example: + +```md +[![A nice name](https://registry.my-netdata.io/api/v1/badge.svg?chart=users.cpu&dimensions=root&value_color=grey:null%7Cgreen%3C10%7Cyellow%3C20%7Corange%3C50%7Cblue%3C100%7Cred&label=root%20user%20cpu%20now&units=%25)](https://registry.my-netdata.io/#apps_cpu) +``` + +- HTML example: + +```html +<a href="https://registry.my-netdata.io/#apps_cpu"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=users.cpu&dimensions=root&value_color=grey:null%7Cgreen%3C10%7Cyellow%3C20%7Corange%3C50%7Cblue%3C100%7Cred&label=root%20user%20cpu%20now&units=%25"></img> +</a> +``` + +Both produce this: + +<a href="https://registry.my-netdata.io/#apps_cpu"> + <img src="https://registry.my-netdata.io/api/v1/badge.svg?chart=users.cpu&dimensions=root&value_color=grey:null%7Cgreen%3C10%7Cyellow%3C20%7Corange%3C50%7Cblue%3C100%7Cred&label=root%20user%20cpu%20now&units=%25"></img> +</a> + +#### auto-refreshing badges in github + +Unfortunately it cannot be done. Github fetches all the images using a proxy and rewrites all the URLs to be served by the proxy. + +You can refresh them from your browser console though. Press F12 to open the web browser console (switch to the console too), paste the following and press enter. They will refresh: + +```js +var len = document.images.length; while(len--) { document.images[len].src = document.images[len].src.replace(/\?cacheBuster=\d*/, "") + "?cacheBuster=" + new Date().getTime().toString(); }; +``` + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fbadges%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/badges/web_buffer_svg.c b/web/api/badges/web_buffer_svg.c new file mode 100644 index 0000000..b24fdde --- /dev/null +++ b/web/api/badges/web_buffer_svg.c @@ -0,0 +1,1142 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web_buffer_svg.h" + +#define BADGE_HORIZONTAL_PADDING 4 +#define VERDANA_KERNING 0.2 +#define VERDANA_PADDING 1.0 + +/* + * verdana11_widths[] has been generated with this method: + * https://github.com/badges/shields/blob/master/measure-text.js +*/ + +static double verdana11_widths[256] = { + [0] = 0.0, + [1] = 0.0, + [2] = 0.0, + [3] = 0.0, + [4] = 0.0, + [5] = 0.0, + [6] = 0.0, + [7] = 0.0, + [8] = 0.0, + [9] = 0.0, + [10] = 0.0, + [11] = 0.0, + [12] = 0.0, + [13] = 0.0, + [14] = 0.0, + [15] = 0.0, + [16] = 0.0, + [17] = 0.0, + [18] = 0.0, + [19] = 0.0, + [20] = 0.0, + [21] = 0.0, + [22] = 0.0, + [23] = 0.0, + [24] = 0.0, + [25] = 0.0, + [26] = 0.0, + [27] = 0.0, + [28] = 0.0, + [29] = 0.0, + [30] = 0.0, + [31] = 0.0, + [32] = 3.8671874999999996, // + [33] = 4.3291015625, // ! + [34] = 5.048828125, // " + [35] = 9.001953125, // # + [36] = 6.9931640625, // $ + [37] = 11.837890625, // % + [38] = 7.992187499999999, // & + [39] = 2.9541015625, // ' + [40] = 4.9951171875, // ( + [41] = 4.9951171875, // ) + [42] = 6.9931640625, // * + [43] = 9.001953125, // + + [44] = 4.00146484375, // , + [45] = 4.9951171875, // - + [46] = 4.00146484375, // . + [47] = 4.9951171875, // / + [48] = 6.9931640625, // 0 + [49] = 6.9931640625, // 1 + [50] = 6.9931640625, // 2 + [51] = 6.9931640625, // 3 + [52] = 6.9931640625, // 4 + [53] = 6.9931640625, // 5 + [54] = 6.9931640625, // 6 + [55] = 6.9931640625, // 7 + [56] = 6.9931640625, // 8 + [57] = 6.9931640625, // 9 + [58] = 4.9951171875, // : + [59] = 4.9951171875, // ; + [60] = 9.001953125, // < + [61] = 9.001953125, // = + [62] = 9.001953125, // > + [63] = 5.99951171875, // ? + [64] = 11.0, // @ + [65] = 7.51953125, // A + [66] = 7.541015625, // B + [67] = 7.680664062499999, // C + [68] = 8.4755859375, // D + [69] = 6.95556640625, // E + [70] = 6.32177734375, // F + [71] = 8.529296875, // G + [72] = 8.26611328125, // H + [73] = 4.6298828125, // I + [74] = 5.00048828125, // J + [75] = 7.62158203125, // K + [76] = 6.123046875, // L + [77] = 9.2705078125, // M + [78] = 8.228515625, // N + [79] = 8.658203125, // O + [80] = 6.63330078125, // P + [81] = 8.658203125, // Q + [82] = 7.6484375, // R + [83] = 7.51953125, // S + [84] = 6.7783203125, // T + [85] = 8.05126953125, // U + [86] = 7.51953125, // V + [87] = 10.87646484375, // W + [88] = 7.53564453125, // X + [89] = 6.767578125, // Y + [90] = 7.53564453125, // Z + [91] = 4.9951171875, // [ + [92] = 4.9951171875, // backslash + [93] = 4.9951171875, // ] + [94] = 9.001953125, // ^ + [95] = 6.9931640625, // _ + [96] = 6.9931640625, // ` + [97] = 6.6064453125, // a + [98] = 6.853515625, // b + [99] = 5.73095703125, // c + [100] = 6.853515625, // d + [101] = 6.552734375, // e + [102] = 3.8671874999999996, // f + [103] = 6.853515625, // g + [104] = 6.9609375, // h + [105] = 3.0185546875, // i + [106] = 3.78662109375, // j + [107] = 6.509765625, // k + [108] = 3.0185546875, // l + [109] = 10.69921875, // m + [110] = 6.9609375, // n + [111] = 6.67626953125, // o + [112] = 6.853515625, // p + [113] = 6.853515625, // q + [114] = 4.6943359375, // r + [115] = 5.73095703125, // s + [116] = 4.33447265625, // t + [117] = 6.9609375, // u + [118] = 6.509765625, // v + [119] = 9.001953125, // w + [120] = 6.509765625, // x + [121] = 6.509765625, // y + [122] = 5.779296875, // z + [123] = 6.982421875, // { + [124] = 4.9951171875, // | + [125] = 6.982421875, // } + [126] = 9.001953125, // ~ + [127] = 0.0, + [128] = 0.0, + [129] = 0.0, + [130] = 0.0, + [131] = 0.0, + [132] = 0.0, + [133] = 0.0, + [134] = 0.0, + [135] = 0.0, + [136] = 0.0, + [137] = 0.0, + [138] = 0.0, + [139] = 0.0, + [140] = 0.0, + [141] = 0.0, + [142] = 0.0, + [143] = 0.0, + [144] = 0.0, + [145] = 0.0, + [146] = 0.0, + [147] = 0.0, + [148] = 0.0, + [149] = 0.0, + [150] = 0.0, + [151] = 0.0, + [152] = 0.0, + [153] = 0.0, + [154] = 0.0, + [155] = 0.0, + [156] = 0.0, + [157] = 0.0, + [158] = 0.0, + [159] = 0.0, + [160] = 0.0, + [161] = 0.0, + [162] = 0.0, + [163] = 0.0, + [164] = 0.0, + [165] = 0.0, + [166] = 0.0, + [167] = 0.0, + [168] = 0.0, + [169] = 0.0, + [170] = 0.0, + [171] = 0.0, + [172] = 0.0, + [173] = 0.0, + [174] = 0.0, + [175] = 0.0, + [176] = 0.0, + [177] = 0.0, + [178] = 0.0, + [179] = 0.0, + [180] = 0.0, + [181] = 0.0, + [182] = 0.0, + [183] = 0.0, + [184] = 0.0, + [185] = 0.0, + [186] = 0.0, + [187] = 0.0, + [188] = 0.0, + [189] = 0.0, + [190] = 0.0, + [191] = 0.0, + [192] = 0.0, + [193] = 0.0, + [194] = 0.0, + [195] = 0.0, + [196] = 0.0, + [197] = 0.0, + [198] = 0.0, + [199] = 0.0, + [200] = 0.0, + [201] = 0.0, + [202] = 0.0, + [203] = 0.0, + [204] = 0.0, + [205] = 0.0, + [206] = 0.0, + [207] = 0.0, + [208] = 0.0, + [209] = 0.0, + [210] = 0.0, + [211] = 0.0, + [212] = 0.0, + [213] = 0.0, + [214] = 0.0, + [215] = 0.0, + [216] = 0.0, + [217] = 0.0, + [218] = 0.0, + [219] = 0.0, + [220] = 0.0, + [221] = 0.0, + [222] = 0.0, + [223] = 0.0, + [224] = 0.0, + [225] = 0.0, + [226] = 0.0, + [227] = 0.0, + [228] = 0.0, + [229] = 0.0, + [230] = 0.0, + [231] = 0.0, + [232] = 0.0, + [233] = 0.0, + [234] = 0.0, + [235] = 0.0, + [236] = 0.0, + [237] = 0.0, + [238] = 0.0, + [239] = 0.0, + [240] = 0.0, + [241] = 0.0, + [242] = 0.0, + [243] = 0.0, + [244] = 0.0, + [245] = 0.0, + [246] = 0.0, + [247] = 0.0, + [248] = 0.0, + [249] = 0.0, + [250] = 0.0, + [251] = 0.0, + [252] = 0.0, + [253] = 0.0, + [254] = 0.0, + [255] = 0.0 +}; + +// find the width of the string using the verdana 11points font +// re-write the string in place, skiping zero-length characters +static inline double verdana11_width(char *s) { + double w = 0.0; + char *d = s; + + while(*s) { + double t = verdana11_widths[(unsigned char)*s]; + if(t == 0.0) + s++; + else { + w += t + VERDANA_KERNING; + if(d != s) + *d++ = *s++; + else + d = ++s; + } + } + + *d = '\0'; + w -= VERDANA_KERNING; + w += VERDANA_PADDING; + return w; +} + +static inline size_t escape_xmlz(char *dst, const char *src, size_t len) { + size_t i = len; + + // required escapes from + // https://github.com/badges/shields/blob/master/badge.js + while(*src && i) { + switch(*src) { + case '\\': + *dst++ = '/'; + src++; + i--; + break; + + case '&': + if(i > 5) { + strcpy(dst, "&"); + i -= 5; + dst += 5; + src++; + } + else goto cleanup; + break; + + case '<': + if(i > 4) { + strcpy(dst, "<"); + i -= 4; + dst += 4; + src++; + } + else goto cleanup; + break; + + case '>': + if(i > 4) { + strcpy(dst, ">"); + i -= 4; + dst += 4; + src++; + } + else goto cleanup; + break; + + case '"': + if(i > 6) { + strcpy(dst, """); + i -= 6; + dst += 6; + src++; + } + else goto cleanup; + break; + + case '\'': + if(i > 6) { + strcpy(dst, "'"); + i -= 6; + dst += 6; + src++; + } + else goto cleanup; + break; + + default: + i--; + *dst++ = *src++; + break; + } + } + +cleanup: + *dst = '\0'; + return len - i; +} + +static inline char *format_value_with_precision_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) { + if(unlikely(isnan(value) || isinf(value))) + value = 0.0; + + char *separator = ""; + if(unlikely(isalnum(*units))) + separator = " "; + + if(precision < 0) { + int len, lstop = 0, trim_zeros = 1; + + calculated_number abs = value; + if(isless(value, 0)) { + lstop = 1; + abs = calculated_number_fabs(value); + } + + if(isgreaterequal(abs, 1000)) { + len = snprintfz(value_string, value_string_len, "%0.0" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + trim_zeros = 0; + } + else if(isgreaterequal(abs, 10)) len = snprintfz(value_string, value_string_len, "%0.1" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else if(isgreaterequal(abs, 1)) len = snprintfz(value_string, value_string_len, "%0.2" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else if(isgreaterequal(abs, 0.1)) len = snprintfz(value_string, value_string_len, "%0.2" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else if(isgreaterequal(abs, 0.01)) len = snprintfz(value_string, value_string_len, "%0.4" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else if(isgreaterequal(abs, 0.001)) len = snprintfz(value_string, value_string_len, "%0.5" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else if(isgreaterequal(abs, 0.0001)) len = snprintfz(value_string, value_string_len, "%0.6" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + else len = snprintfz(value_string, value_string_len, "%0.7" LONG_DOUBLE_MODIFIER, (LONG_DOUBLE) value); + + if(unlikely(trim_zeros)) { + int l; + // remove trailing zeros from the decimal part + for(l = len - 1; l > lstop; l--) { + if(likely(value_string[l] == '0')) { + value_string[l] = '\0'; + len--; + } + + else if(unlikely(value_string[l] == '.')) { + value_string[l] = '\0'; + len--; + break; + } + + else + break; + } + } + + if(unlikely(len <= 0)) len = 1; + snprintfz(&value_string[len], value_string_len - len, "%s%s", separator, units); + } + else { + if(precision > 50) precision = 50; + snprintfz(value_string, value_string_len, "%0.*" LONG_DOUBLE_MODIFIER "%s%s", precision, (LONG_DOUBLE) value, separator, units); + } + + return value_string; +} + +typedef enum badge_units_format { + UNITS_FORMAT_NONE, + UNITS_FORMAT_SECONDS, + UNITS_FORMAT_SECONDS_AGO, + UNITS_FORMAT_MINUTES, + UNITS_FORMAT_MINUTES_AGO, + UNITS_FORMAT_HOURS, + UNITS_FORMAT_HOURS_AGO, + UNITS_FORMAT_ONOFF, + UNITS_FORMAT_UPDOWN, + UNITS_FORMAT_OKERROR, + UNITS_FORMAT_OKFAILED, + UNITS_FORMAT_EMPTY, + UNITS_FORMAT_PERCENT +} UNITS_FORMAT; + + +static struct units_formatter { + const char *units; + uint32_t hash; + UNITS_FORMAT format; +} badge_units_formatters[] = { + { "seconds", 0, UNITS_FORMAT_SECONDS }, + { "seconds ago", 0, UNITS_FORMAT_SECONDS_AGO }, + { "minutes", 0, UNITS_FORMAT_MINUTES }, + { "minutes ago", 0, UNITS_FORMAT_MINUTES_AGO }, + { "hours", 0, UNITS_FORMAT_HOURS }, + { "hours ago", 0, UNITS_FORMAT_HOURS_AGO }, + { "on/off", 0, UNITS_FORMAT_ONOFF }, + { "on-off", 0, UNITS_FORMAT_ONOFF }, + { "onoff", 0, UNITS_FORMAT_ONOFF }, + { "up/down", 0, UNITS_FORMAT_UPDOWN }, + { "up-down", 0, UNITS_FORMAT_UPDOWN }, + { "updown", 0, UNITS_FORMAT_UPDOWN }, + { "ok/error", 0, UNITS_FORMAT_OKERROR }, + { "ok-error", 0, UNITS_FORMAT_OKERROR }, + { "okerror", 0, UNITS_FORMAT_OKERROR }, + { "ok/failed", 0, UNITS_FORMAT_OKFAILED }, + { "ok-failed", 0, UNITS_FORMAT_OKFAILED }, + { "okfailed", 0, UNITS_FORMAT_OKFAILED }, + { "empty", 0, UNITS_FORMAT_EMPTY }, + { "null", 0, UNITS_FORMAT_EMPTY }, + { "percentage", 0, UNITS_FORMAT_PERCENT }, + { "percent", 0, UNITS_FORMAT_PERCENT }, + { "pcent", 0, UNITS_FORMAT_PERCENT }, + + // terminator + { NULL, 0, UNITS_FORMAT_NONE } +}; + +inline char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision) { + static int max = -1; + int i; + + if(unlikely(max == -1)) { + for(i = 0; badge_units_formatters[i].units; i++) + badge_units_formatters[i].hash = simple_hash(badge_units_formatters[i].units); + + max = i; + } + + if(unlikely(!units)) units = ""; + uint32_t hash_units = simple_hash(units); + + UNITS_FORMAT format = UNITS_FORMAT_NONE; + for(i = 0; i < max; i++) { + struct units_formatter *ptr = &badge_units_formatters[i]; + + if(hash_units == ptr->hash && !strcmp(units, ptr->units)) { + format = ptr->format; + break; + } + } + + if(unlikely(format == UNITS_FORMAT_SECONDS || format == UNITS_FORMAT_SECONDS_AGO)) { + if(value == 0.0) { + snprintfz(value_string, value_string_len, "%s", "now"); + return value_string; + } + else if(isnan(value) || isinf(value)) { + snprintfz(value_string, value_string_len, "%s", "undefined"); + return value_string; + } + + const char *suffix = (format == UNITS_FORMAT_SECONDS_AGO)?" ago":""; + + size_t s = (size_t)value; + size_t d = s / 86400; + s = s % 86400; + + size_t h = s / 3600; + s = s % 3600; + + size_t m = s / 60; + s = s % 60; + + if(d) + snprintfz(value_string, value_string_len, "%zu %s %02zu:%02zu:%02zu%s", d, (d == 1)?"day":"days", h, m, s, suffix); + else + snprintfz(value_string, value_string_len, "%02zu:%02zu:%02zu%s", h, m, s, suffix); + + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_MINUTES || format == UNITS_FORMAT_MINUTES_AGO)) { + if(value == 0.0) { + snprintfz(value_string, value_string_len, "%s", "now"); + return value_string; + } + else if(isnan(value) || isinf(value)) { + snprintfz(value_string, value_string_len, "%s", "undefined"); + return value_string; + } + + const char *suffix = (format == UNITS_FORMAT_MINUTES_AGO)?" ago":""; + + size_t m = (size_t)value; + size_t d = m / (60 * 24); + m = m % (60 * 24); + + size_t h = m / 60; + m = m % 60; + + if(d) + snprintfz(value_string, value_string_len, "%zud %02zuh %02zum%s", d, h, m, suffix); + else + snprintfz(value_string, value_string_len, "%zuh %zum%s", h, m, suffix); + + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_HOURS || format == UNITS_FORMAT_HOURS_AGO)) { + if(value == 0.0) { + snprintfz(value_string, value_string_len, "%s", "now"); + return value_string; + } + else if(isnan(value) || isinf(value)) { + snprintfz(value_string, value_string_len, "%s", "undefined"); + return value_string; + } + + const char *suffix = (format == UNITS_FORMAT_HOURS_AGO)?" ago":""; + + size_t h = (size_t)value; + size_t d = h / 24; + h = h % 24; + + if(d) + snprintfz(value_string, value_string_len, "%zud %zuh%s", d, h, suffix); + else + snprintfz(value_string, value_string_len, "%zuh%s", h, suffix); + + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_ONOFF)) { + snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"on":"off"); + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_UPDOWN)) { + snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"up":"down"); + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_OKERROR)) { + snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"error"); + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_OKFAILED)) { + snprintfz(value_string, value_string_len, "%s", (value != 0.0)?"ok":"failed"); + return value_string; + } + + else if(unlikely(format == UNITS_FORMAT_EMPTY)) + units = ""; + + else if(unlikely(format == UNITS_FORMAT_PERCENT)) + units = "%"; + + if(unlikely(isnan(value) || isinf(value))) { + strcpy(value_string, "-"); + return value_string; + } + + return format_value_with_precision_and_unit(value_string, value_string_len, value, units, precision); +} + +static struct badge_color { + const char *name; + uint32_t hash; + const char *color; +} badge_colors[] = { + + // colors from: + // https://github.com/badges/shields/blob/master/colorscheme.json + + { "brightgreen", 0, "#4c1" }, + { "green", 0, "#97CA00" }, + { "yellow", 0, "#dfb317" }, + { "yellowgreen", 0, "#a4a61d" }, + { "orange", 0, "#fe7d37" }, + { "red", 0, "#e05d44" }, + { "blue", 0, "#007ec6" }, + { "grey", 0, "#555" }, + { "gray", 0, "#555" }, + { "lightgrey", 0, "#9f9f9f" }, + { "lightgray", 0, "#9f9f9f" }, + + // terminator + { NULL, 0, NULL } +}; + +static inline const char *color_map(const char *color) { + static int max = -1; + int i; + + if(unlikely(max == -1)) { + for(i = 0; badge_colors[i].name ;i++) + badge_colors[i].hash = simple_hash(badge_colors[i].name); + + max = i; + } + + uint32_t hash = simple_hash(color); + + for(i = 0; i < max; i++) { + struct badge_color *ptr = &badge_colors[i]; + + if(hash == ptr->hash && !strcmp(color, ptr->name)) + return ptr->color; + } + + return color; +} + +typedef enum color_comparison { + COLOR_COMPARE_EQUAL, + COLOR_COMPARE_NOTEQUAL, + COLOR_COMPARE_LESS, + COLOR_COMPARE_LESSEQUAL, + COLOR_COMPARE_GREATER, + COLOR_COMPARE_GREATEREQUAL, +} BADGE_COLOR_COMPARISON; + +static inline void calc_colorz(const char *color, char *final, size_t len, calculated_number value) { + if(isnan(value) || isinf(value)) + value = NAN; + + char color_buffer[256 + 1] = ""; + char value_buffer[256 + 1] = ""; + BADGE_COLOR_COMPARISON comparison = COLOR_COMPARE_GREATER; + + // example input: + // color<max|color>min|color:null... + + const char *c = color; + while(*c) { + char *dc = color_buffer, *dv = NULL; + size_t ci = 0, vi = 0; + + const char *t = c; + + while(*t && *t != '|') { + switch(*t) { + case '!': + if(t[1] == '=') t++; + comparison = COLOR_COMPARE_NOTEQUAL; + dv = value_buffer; + break; + + case '=': + case ':': + comparison = COLOR_COMPARE_EQUAL; + dv = value_buffer; + break; + + case '}': + case ')': + case '>': + if(t[1] == '=') { + comparison = COLOR_COMPARE_GREATEREQUAL; + t++; + } + else + comparison = COLOR_COMPARE_GREATER; + dv = value_buffer; + break; + + case '{': + case '(': + case '<': + if(t[1] == '=') { + comparison = COLOR_COMPARE_LESSEQUAL; + t++; + } + else if(t[1] == '>' || t[1] == ')' || t[1] == '}') { + comparison = COLOR_COMPARE_NOTEQUAL; + t++; + } + else + comparison = COLOR_COMPARE_LESS; + dv = value_buffer; + break; + + default: + if(dv) { + if(vi < 256) { + vi++; + *dv++ = *t; + } + } + else { + if(ci < 256) { + ci++; + *dc++ = *t; + } + } + break; + } + + t++; + } + + // prepare for next iteration + if(*t == '|') t++; + c = t; + + // do the math + *dc = '\0'; + if(dv) { + *dv = '\0'; + calculated_number v; + + if(!*value_buffer || !strcmp(value_buffer, "null")) { + v = NAN; + } + else { + v = str2l(value_buffer); + if(isnan(v) || isinf(v)) + v = NAN; + } + + if(unlikely(isnan(value) || isnan(v))) { + if(isnan(value) && isnan(v)) + break; + } + else { + if (unlikely(comparison == COLOR_COMPARE_LESS && isless(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_LESSEQUAL && islessequal(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_GREATER && isgreater(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_GREATEREQUAL && isgreaterequal(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_EQUAL && !islessgreater(value, v))) break; + else if (unlikely(comparison == COLOR_COMPARE_NOTEQUAL && islessgreater(value, v))) break; + } + } + else + break; + } + + const char *b; + if(color_buffer[0]) + b = color_buffer; + else + b = color; + + strncpyz(final, b, len); +} + +// value + units +#define VALUE_STRING_SIZE 100 + +// label +#define LABEL_STRING_SIZE 200 + +// colors +#define COLOR_STRING_SIZE 100 + +void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options) { + char label_buffer[LABEL_STRING_SIZE + 1] + , value_color_buffer[COLOR_STRING_SIZE + 1] + , value_string[VALUE_STRING_SIZE + 1] + , label_escaped[LABEL_STRING_SIZE + 1] + , value_escaped[VALUE_STRING_SIZE + 1] + , label_color_escaped[COLOR_STRING_SIZE + 1] + , value_color_escaped[COLOR_STRING_SIZE + 1]; + + double label_width, value_width, total_width, height = 20.0, font_size = 11.0, text_offset = 5.8, round_corner = 3.0; + + if(scale < 100) scale = 100; + + if(unlikely(!label_color || !*label_color)) + label_color = "#555"; + + if(unlikely(!value_color || !*value_color)) + value_color = (isnan(value) || isinf(value))?"#999":"#4c1"; + + calc_colorz(value_color, value_color_buffer, COLOR_STRING_SIZE, value); + format_value_and_unit(value_string, VALUE_STRING_SIZE, (options & RRDR_OPTION_DISPLAY_ABS)?calculated_number_fabs(value):value, units, precision); + + // we need to copy the label, since verdana11_width may write to it + strncpyz(label_buffer, label, LABEL_STRING_SIZE); + + label_width = verdana11_width(label_buffer) + (BADGE_HORIZONTAL_PADDING * 2); + value_width = verdana11_width(value_string) + (BADGE_HORIZONTAL_PADDING * 2); + total_width = label_width + value_width; + + escape_xmlz(label_escaped, label_buffer, LABEL_STRING_SIZE); + escape_xmlz(value_escaped, value_string, VALUE_STRING_SIZE); + escape_xmlz(label_color_escaped, color_map(label_color), COLOR_STRING_SIZE); + escape_xmlz(value_color_escaped, color_map(value_color_buffer), COLOR_STRING_SIZE); + + wb->contenttype = CT_IMAGE_SVG_XML; + + total_width = total_width * scale / 100.0; + height = height * scale / 100.0; + font_size = font_size * scale / 100.0; + text_offset = text_offset * scale / 100.0; + label_width = label_width * scale / 100.0; + value_width = value_width * scale / 100.0; + round_corner = round_corner * scale / 100.0; + + // svg template from: + // https://raw.githubusercontent.com/badges/shields/master/templates/flat-template.svg + buffer_sprintf(wb, + "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"%0.2f\" height=\"%0.2f\">" + "<linearGradient id=\"smooth\" x2=\"0\" y2=\"100%%\">" + "<stop offset=\"0\" stop-color=\"#bbb\" stop-opacity=\".1\"/>" + "<stop offset=\"1\" stop-opacity=\".1\"/>" + "</linearGradient>" + "<mask id=\"round\">" + "<rect width=\"%0.2f\" height=\"%0.2f\" rx=\"%0.2f\" fill=\"#fff\"/>" + "</mask>" + "<g mask=\"url(#round)\">" + "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>" + "<rect x=\"%0.2f\" width=\"%0.2f\" height=\"%0.2f\" fill=\"%s\"/>" + "<rect width=\"%0.2f\" height=\"%0.2f\" fill=\"url(#smooth)\"/>" + "</g>" + "<g fill=\"#fff\" text-anchor=\"middle\" font-family=\"DejaVu Sans,Verdana,Geneva,sans-serif\" font-size=\"%0.2f\">" + "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>" + "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>" + "<text x=\"%0.2f\" y=\"%0.0f\" fill=\"#010101\" fill-opacity=\".3\">%s</text>" + "<text x=\"%0.2f\" y=\"%0.0f\">%s</text>" + "</g>" + "</svg>", + total_width, height, + total_width, height, round_corner, + label_width, height, label_color_escaped, + label_width, value_width, height, value_color_escaped, + total_width, height, + font_size, + label_width / 2, ceil(height - text_offset), label_escaped, + label_width / 2, ceil(height - text_offset - 1.0), label_escaped, + label_width + value_width / 2 -1, ceil(height - text_offset), value_escaped, + label_width + value_width / 2 -1, ceil(height - text_offset - 1.0), value_escaped); +} + +int web_client_api_request_v1_badge(RRDHOST *host, struct web_client *w, char *url) { + int ret = 400; + buffer_flush(w->response.data); + + BUFFER *dimensions = NULL; + + const char *chart = NULL + , *before_str = NULL + , *after_str = NULL + , *points_str = NULL + , *multiply_str = NULL + , *divide_str = NULL + , *label = NULL + , *units = NULL + , *label_color = NULL + , *value_color = NULL + , *refresh_str = NULL + , *precision_str = NULL + , *scale_str = NULL + , *alarm = NULL; + + int group = RRDR_GROUPING_AVERAGE; + uint32_t options = 0x00000000; + + while(url) { + char *value = mystrsep(&url, "&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 badge.svg query param '%s' with value '%s'", w->id, name, value); + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { + if(!dimensions) + dimensions = buffer_create(100); + + buffer_strcat(dimensions, "|"); + buffer_strcat(dimensions, value); + } + else if(!strcmp(name, "after")) after_str = value; + else if(!strcmp(name, "before")) before_str = value; + else if(!strcmp(name, "points")) points_str = value; + else if(!strcmp(name, "group")) { + group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE); + } + else if(!strcmp(name, "options")) { + options |= web_client_api_request_v1_data_options(value); + } + else if(!strcmp(name, "label")) label = value; + else if(!strcmp(name, "units")) units = value; + else if(!strcmp(name, "label_color")) label_color = value; + else if(!strcmp(name, "value_color")) value_color = value; + else if(!strcmp(name, "multiply")) multiply_str = value; + else if(!strcmp(name, "divide")) divide_str = value; + else if(!strcmp(name, "refresh")) refresh_str = value; + else if(!strcmp(name, "precision")) precision_str = value; + else if(!strcmp(name, "scale")) scale_str = value; + else if(!strcmp(name, "alarm")) alarm = value; + } + + if(!chart || !*chart) { + buffer_no_cacheable(w->response.data); + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + int scale = (scale_str && *scale_str)?str2i(scale_str):100; + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "chart not found", NAN, "", NULL, NULL, -1, scale, 0); + ret = 200; + goto cleanup; + } + st->last_accessed_time = now_realtime_sec(); + + RRDCALC *rc = NULL; + if(alarm) { + rc = rrdcalc_find(st, alarm); + if (!rc) { + buffer_no_cacheable(w->response.data); + buffer_svg(w->response.data, "alarm not found", NAN, "", NULL, NULL, -1, scale, 0); + ret = 200; + goto cleanup; + } + } + + long long multiply = (multiply_str && *multiply_str )?str2l(multiply_str):1; + long long divide = (divide_str && *divide_str )?str2l(divide_str):1; + long long before = (before_str && *before_str )?str2l(before_str):0; + long long after = (after_str && *after_str )?str2l(after_str):-st->update_every; + int points = (points_str && *points_str )?str2i(points_str):1; + int precision = (precision_str && *precision_str)?str2i(precision_str):-1; + + if(!multiply) multiply = 1; + if(!divide) divide = 1; + + int refresh = 0; + if(refresh_str && *refresh_str) { + if(!strcmp(refresh_str, "auto")) { + if(rc) refresh = rc->update_every; + else if(options & RRDR_OPTION_NOT_ALIGNED) + refresh = st->update_every; + else { + refresh = (int)(before - after); + if(refresh < 0) refresh = -refresh; + } + } + else { + refresh = str2i(refresh_str); + if(refresh < 0) refresh = -refresh; + } + } + + if(!label) { + if(alarm) { + char *s = (char *)alarm; + while(*s) { + if(*s == '_') *s = ' '; + s++; + } + label = alarm; + } + else if(dimensions) { + const char *dim = buffer_tostring(dimensions); + if(*dim == '|') dim++; + label = dim; + } + else + label = st->name; + } + if(!units) { + if(alarm) { + if(rc->units) + units = rc->units; + else + units = ""; + } + else if(options & RRDR_OPTION_PERCENTAGE) + units = "%"; + else + units = st->units; + } + + debug(D_WEB_CLIENT, "%llu: API command 'badge.svg' for chart '%s', alarm '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', options '0x%08x'" + , w->id + , chart + , alarm?alarm:"" + , (dimensions)?buffer_tostring(dimensions):"" + , after + , before + , points + , group + , options + ); + + if(rc) { + if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + if(!value_color) { + switch(rc->status) { + case RRDCALC_STATUS_CRITICAL: + value_color = "red"; + break; + + case RRDCALC_STATUS_WARNING: + value_color = "orange"; + break; + + case RRDCALC_STATUS_CLEAR: + value_color = "brightgreen"; + break; + + case RRDCALC_STATUS_UNDEFINED: + value_color = "lightgrey"; + break; + + case RRDCALC_STATUS_UNINITIALIZED: + value_color = "#000"; + break; + + default: + value_color = "grey"; + break; + } + } + + buffer_svg(w->response.data, + label, + (isnan(rc->value)||isinf(rc->value)) ? rc->value : rc->value * multiply / divide, + units, + label_color, + value_color, + precision, + scale, + options + ); + ret = 200; + } + else { + time_t latest_timestamp = 0; + int value_is_null = 1; + calculated_number n = NAN; + ret = 500; + + // if the collected value is too old, don't calculate its value + if (rrdset_last_entry_t(st) >= (now_realtime_sec() - (st->update_every * st->gap_when_lost_iterations_above))) + ret = rrdset2value_api_v1(st, w->response.data, &n, (dimensions) ? buffer_tostring(dimensions) : NULL + , points, after, before, group, 0, options, NULL, &latest_timestamp, &value_is_null); + + // if the value cannot be calculated, show empty badge + if (ret != 200) { + buffer_no_cacheable(w->response.data); + value_is_null = 1; + n = 0; + ret = 200; + } + else if (refresh > 0) { + buffer_sprintf(w->response.header, "Refresh: %d\r\n", refresh); + w->response.data->expires = now_realtime_sec() + refresh; + } + else buffer_no_cacheable(w->response.data); + + // render the badge + buffer_svg(w->response.data, + label, + (value_is_null)?NAN:(n * multiply / divide), + units, + label_color, + value_color, + precision, + scale, + options + ); + } + + cleanup: + buffer_free(dimensions); + return ret; +} diff --git a/web/api/badges/web_buffer_svg.h b/web/api/badges/web_buffer_svg.h new file mode 100644 index 0000000..f75677b --- /dev/null +++ b/web/api/badges/web_buffer_svg.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_BUFFER_SVG_H +#define NETDATA_WEB_BUFFER_SVG_H 1 + +#include "libnetdata/libnetdata.h" +#include "web/server/web_client.h" + +extern void buffer_svg(BUFFER *wb, const char *label, calculated_number value, const char *units, const char *label_color, const char *value_color, int precision, int scale, uint32_t options); +extern char *format_value_and_unit(char *value_string, size_t value_string_len, calculated_number value, const char *units, int precision); + +extern int web_client_api_request_v1_badge(struct rrdhost *host, struct web_client *w, char *url); + +#include "web/api/web_api_v1.h" + +#endif /* NETDATA_WEB_BUFFER_SVG_H */ diff --git a/web/api/exporters/Makefile.am b/web/api/exporters/Makefile.am new file mode 100644 index 0000000..3dce98a --- /dev/null +++ b/web/api/exporters/Makefile.am @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + shell \ + prometheus \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/exporters/README.md b/web/api/exporters/README.md new file mode 100644 index 0000000..ff711d7 --- /dev/null +++ b/web/api/exporters/README.md @@ -0,0 +1,5 @@ +# Exporters + +TBD + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fexporters%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/exporters/allmetrics.c b/web/api/exporters/allmetrics.c new file mode 100644 index 0000000..91bb0f9 --- /dev/null +++ b/web/api/exporters/allmetrics.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "allmetrics.h" + +struct prometheus_output_options { + char *name; + PROMETHEUS_OUTPUT_OPTIONS flag; +} prometheus_output_flags_root[] = { + { "help", PROMETHEUS_OUTPUT_HELP }, + { "types", PROMETHEUS_OUTPUT_TYPES }, + { "names", PROMETHEUS_OUTPUT_NAMES }, + { "timestamps", PROMETHEUS_OUTPUT_TIMESTAMPS }, + { "variables", PROMETHEUS_OUTPUT_VARIABLES }, + + // terminator + { NULL, PROMETHEUS_OUTPUT_NONE }, +}; + +inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) { + int format = ALLMETRICS_SHELL; + const char *prometheus_server = w->client_ip; + uint32_t prometheus_backend_options = global_backend_options; + PROMETHEUS_OUTPUT_OPTIONS prometheus_output_options = PROMETHEUS_OUTPUT_TIMESTAMPS | ((global_backend_options & BACKEND_OPTION_SEND_NAMES)?PROMETHEUS_OUTPUT_NAMES:0); + const char *prometheus_prefix = global_backend_prefix; + + while(url) { + char *value = mystrsep(&url, "&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + if(!strcmp(name, "format")) { + if(!strcmp(value, ALLMETRICS_FORMAT_SHELL)) + format = ALLMETRICS_SHELL; + else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS)) + format = ALLMETRICS_PROMETHEUS; + else if(!strcmp(value, ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS)) + format = ALLMETRICS_PROMETHEUS_ALL_HOSTS; + else if(!strcmp(value, ALLMETRICS_FORMAT_JSON)) + format = ALLMETRICS_JSON; + else + format = 0; + } + else if(!strcmp(name, "server")) { + prometheus_server = value; + } + else if(!strcmp(name, "prefix")) { + prometheus_prefix = value; + } + else if(!strcmp(name, "data") || !strcmp(name, "source") || !strcmp(name, "data source") || !strcmp(name, "data-source") || !strcmp(name, "data_source") || !strcmp(name, "datasource")) { + prometheus_backend_options = backend_parse_data_source(value, prometheus_backend_options); + } + else { + int i; + for(i = 0; prometheus_output_flags_root[i].name ; i++) { + if(!strcmp(name, prometheus_output_flags_root[i].name)) { + if(!strcmp(value, "yes") || !strcmp(value, "1") || !strcmp(value, "true")) + prometheus_output_options |= prometheus_output_flags_root[i].flag; + else + prometheus_output_options &= ~prometheus_output_flags_root[i].flag; + + break; + } + } + } + } + + buffer_flush(w->response.data); + buffer_no_cacheable(w->response.data); + + switch(format) { + case ALLMETRICS_JSON: + w->response.data->contenttype = CT_APPLICATION_JSON; + rrd_stats_api_v1_charts_allmetrics_json(host, w->response.data); + return 200; + + case ALLMETRICS_SHELL: + w->response.data->contenttype = CT_TEXT_PLAIN; + rrd_stats_api_v1_charts_allmetrics_shell(host, w->response.data); + return 200; + + case ALLMETRICS_PROMETHEUS: + w->response.data->contenttype = CT_PROMETHEUS; + rrd_stats_api_v1_charts_allmetrics_prometheus_single_host( + host + , w->response.data + , prometheus_server + , prometheus_prefix + , prometheus_backend_options + , prometheus_output_options + ); + return 200; + + case ALLMETRICS_PROMETHEUS_ALL_HOSTS: + w->response.data->contenttype = CT_PROMETHEUS; + rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts( + host + , w->response.data + , prometheus_server + , prometheus_prefix + , prometheus_backend_options + , prometheus_output_options + ); + return 200; + + default: + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_strcat(w->response.data, "Which format? '" ALLMETRICS_FORMAT_SHELL "', '" ALLMETRICS_FORMAT_PROMETHEUS "', '" ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "' and '" ALLMETRICS_FORMAT_JSON "' are currently supported."); + return 400; + } +} diff --git a/web/api/exporters/allmetrics.h b/web/api/exporters/allmetrics.h new file mode 100644 index 0000000..e8dedab --- /dev/null +++ b/web/api/exporters/allmetrics.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_ALLMETRICS_H +#define NETDATA_API_ALLMETRICS_H + +#include "web/api/formatters/rrd2json.h" +#include "shell/allmetrics_shell.h" + +extern int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url); + +#endif //NETDATA_API_ALLMETRICS_H diff --git a/web/api/exporters/prometheus/Makefile.am b/web/api/exporters/prometheus/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/exporters/prometheus/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/exporters/prometheus/README.md b/web/api/exporters/prometheus/README.md new file mode 100644 index 0000000..88e79ec --- /dev/null +++ b/web/api/exporters/prometheus/README.md @@ -0,0 +1,5 @@ +# prometheus exporter + +The prometheus exporter for netdata is located at the [backends section for prometheus](../../../../backends/prometheus). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fexporters%2Fprometheus%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/exporters/shell/Makefile.am b/web/api/exporters/shell/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/exporters/shell/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/exporters/shell/README.md b/web/api/exporters/shell/README.md new file mode 100644 index 0000000..ab412eb --- /dev/null +++ b/web/api/exporters/shell/README.md @@ -0,0 +1,66 @@ +# shell exporter + +Shell scripts can now query netdata: + +```sh +eval "$(curl -s 'http://localhost:19999/api/v1/allmetrics')" +``` + +after this command, all the netdata metrics are exposed to shell. Check: + +```sh +# source the metrics +eval "$(curl -s 'http://localhost:19999/api/v1/allmetrics')" + +# let's see if there are variables exposed by netdata for system.cpu +set | grep "^NETDATA_SYSTEM_CPU" + +NETDATA_SYSTEM_CPU_GUEST=0 +NETDATA_SYSTEM_CPU_GUEST_NICE=0 +NETDATA_SYSTEM_CPU_IDLE=95 +NETDATA_SYSTEM_CPU_IOWAIT=0 +NETDATA_SYSTEM_CPU_IRQ=0 +NETDATA_SYSTEM_CPU_NICE=0 +NETDATA_SYSTEM_CPU_SOFTIRQ=0 +NETDATA_SYSTEM_CPU_STEAL=0 +NETDATA_SYSTEM_CPU_SYSTEM=1 +NETDATA_SYSTEM_CPU_USER=4 +NETDATA_SYSTEM_CPU_VISIBLETOTAL=5 + +# let's see the total cpu utilization of the system +echo ${NETDATA_SYSTEM_CPU_VISIBLETOTAL} +5 + +# what about alarms? +set | grep "^NETDATA_ALARM_SYSTEM_SWAP_" +NETDATA_ALARM_SYSTEM_SWAP_RAM_IN_SWAP_STATUS=CRITICAL +NETDATA_ALARM_SYSTEM_SWAP_RAM_IN_SWAP_VALUE=53 +NETDATA_ALARM_SYSTEM_SWAP_USED_SWAP_STATUS=CLEAR +NETDATA_ALARM_SYSTEM_SWAP_USED_SWAP_VALUE=51 + +# let's get the current status of the alarm 'ram in swap' +echo ${NETDATA_ALARM_SYSTEM_SWAP_RAM_IN_SWAP_STATUS} +CRITICAL + +# is it fast? +time curl -s 'http://localhost:19999/api/v1/allmetrics' >/dev/null + +real 0m0,070s +user 0m0,000s +sys 0m0,007s + +# it is... +# 0.07 seconds for curl to be loaded, connect to netdata and fetch the response back... +``` + +The `_VISIBLETOTAL` variable sums up all the dimensions of each chart. + +The format of the variables is: + +```sh +NETDATA_${chart_id^^}_${dimension_id^^}="${value}" +``` + +The value is rounded to the closest integer, since shell script cannot process decimal numbers. + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fexporters%2Fshell%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/exporters/shell/allmetrics_shell.c b/web/api/exporters/shell/allmetrics_shell.c new file mode 100644 index 0000000..e380dee --- /dev/null +++ b/web/api/exporters/shell/allmetrics_shell.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "allmetrics_shell.h" + +// ---------------------------------------------------------------------------- +// BASH +// /api/v1/allmetrics?format=bash + +static inline size_t shell_name_copy(char *d, const char *s, size_t usable) { + size_t n; + + for(n = 0; *s && n < usable ; d++, s++, n++) { + register char c = *s; + + if(unlikely(!isalnum(c))) *d = '_'; + else *d = (char)toupper(c); + } + *d = '\0'; + + return n; +} + +#define SHELL_ELEMENT_MAX 100 + +void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb) { + rrdhost_rdlock(host); + + // for each chart + RRDSET *st; + rrdset_foreach_read(st, host) { + calculated_number total = 0.0; + char chart[SHELL_ELEMENT_MAX + 1]; + shell_name_copy(chart, st->name?st->name:st->id, SHELL_ELEMENT_MAX); + + buffer_sprintf(wb, "\n# chart: %s (name: %s)\n", st->id, st->name); + if(rrdset_is_available_for_viewers(st)) { + rrdset_rdlock(st); + + // for each dimension + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + if(rd->collections_counter) { + char dimension[SHELL_ELEMENT_MAX + 1]; + shell_name_copy(dimension, rd->name?rd->name:rd->id, SHELL_ELEMENT_MAX); + + calculated_number n = rd->last_stored_value; + + if(isnan(n) || isinf(n)) + buffer_sprintf(wb, "NETDATA_%s_%s=\"\" # %s\n", chart, dimension, st->units); + else { + if(rd->multiplier < 0 || rd->divisor < 0) n = -n; + n = calculated_number_round(n); + if(!rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) total += n; + buffer_sprintf(wb, "NETDATA_%s_%s=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, dimension, n, st->units); + } + } + } + + total = calculated_number_round(total); + buffer_sprintf(wb, "NETDATA_%s_VISIBLETOTAL=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, total, st->units); + rrdset_unlock(st); + } + } + + buffer_strcat(wb, "\n# NETDATA ALARMS RUNNING\n"); + + RRDCALC *rc; + for(rc = host->alarms; rc ;rc = rc->next) { + if(!rc->rrdset) continue; + + char chart[SHELL_ELEMENT_MAX + 1]; + shell_name_copy(chart, rc->rrdset->name?rc->rrdset->name:rc->rrdset->id, SHELL_ELEMENT_MAX); + + char alarm[SHELL_ELEMENT_MAX + 1]; + shell_name_copy(alarm, rc->name, SHELL_ELEMENT_MAX); + + calculated_number n = rc->value; + + if(isnan(n) || isinf(n)) + buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"\" # %s\n", chart, alarm, rc->units); + else { + n = calculated_number_round(n); + buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_VALUE=\"" CALCULATED_NUMBER_FORMAT_ZERO "\" # %s\n", chart, alarm, n, rc->units); + } + + buffer_sprintf(wb, "NETDATA_ALARM_%s_%s_STATUS=\"%s\"\n", chart, alarm, rrdcalc_status2string(rc->status)); + } + + rrdhost_unlock(host); +} + +// ---------------------------------------------------------------------------- + +void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb) { + rrdhost_rdlock(host); + + buffer_strcat(wb, "{"); + + size_t chart_counter = 0; + size_t dimension_counter = 0; + + // for each chart + RRDSET *st; + rrdset_foreach_read(st, host) { + if(rrdset_is_available_for_viewers(st)) { + rrdset_rdlock(st); + + buffer_sprintf(wb, "%s\n" + "\t\"%s\": {\n" + "\t\t\"name\":\"%s\",\n" + "\t\t\"context\":\"%s\",\n" + "\t\t\"units\":\"%s\",\n" + "\t\t\"last_updated\": %ld,\n" + "\t\t\"dimensions\": {" + , chart_counter?",":"" + , st->id + , st->name + , st->context + , st->units + , rrdset_last_entry_t(st) + ); + + chart_counter++; + dimension_counter = 0; + + // for each dimension + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + if(rd->collections_counter) { + + buffer_sprintf(wb, "%s\n" + "\t\t\t\"%s\": {\n" + "\t\t\t\t\"name\": \"%s\",\n" + "\t\t\t\t\"value\": " + , dimension_counter?",":"" + , rd->id + , rd->name + ); + + if(isnan(rd->last_stored_value)) + buffer_strcat(wb, "null"); + else + buffer_sprintf(wb, CALCULATED_NUMBER_FORMAT, rd->last_stored_value); + + buffer_strcat(wb, "\n\t\t\t}"); + + dimension_counter++; + } + } + + buffer_strcat(wb, "\n\t\t}\n\t}"); + rrdset_unlock(st); + } + } + + buffer_strcat(wb, "\n}"); + rrdhost_unlock(host); +} + diff --git a/web/api/exporters/shell/allmetrics_shell.h b/web/api/exporters/shell/allmetrics_shell.h new file mode 100644 index 0000000..1d7611a --- /dev/null +++ b/web/api/exporters/shell/allmetrics_shell.h @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_ALLMETRICS_SHELL_H +#define NETDATA_API_ALLMETRICS_SHELL_H + +#include "../allmetrics.h" + +#define ALLMETRICS_FORMAT_SHELL "shell" +#define ALLMETRICS_FORMAT_PROMETHEUS "prometheus" +#define ALLMETRICS_FORMAT_PROMETHEUS_ALL_HOSTS "prometheus_all_hosts" +#define ALLMETRICS_FORMAT_JSON "json" + +#define ALLMETRICS_SHELL 1 +#define ALLMETRICS_PROMETHEUS 2 +#define ALLMETRICS_JSON 3 +#define ALLMETRICS_PROMETHEUS_ALL_HOSTS 4 + +extern void rrd_stats_api_v1_charts_allmetrics_json(RRDHOST *host, BUFFER *wb); +extern void rrd_stats_api_v1_charts_allmetrics_shell(RRDHOST *host, BUFFER *wb); + +#endif //NETDATA_API_ALLMETRICS_SHELL_H diff --git a/web/api/formatters/Makefile.am b/web/api/formatters/Makefile.am new file mode 100644 index 0000000..3245759 --- /dev/null +++ b/web/api/formatters/Makefile.am @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + csv \ + json \ + ssv \ + value \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/formatters/README.md b/web/api/formatters/README.md new file mode 100644 index 0000000..b4ce1e3 --- /dev/null +++ b/web/api/formatters/README.md @@ -0,0 +1,74 @@ +# Query formatting + +API data queries need to be formatted before returned to the caller. +Using API parameters, the caller may define the format he/she wishes to get back. + +The following formats are supported: + +format|module|content type|description +:---:|:---:|:---:|:----- +`array`|[ssv](ssv)|application/json|a JSON array +`csv`|[csv](csv)|text/plain|a text table, comma separated, with a header line (dimension names) and `\r\n` at the end of the lines +`csvjsonarray`|[csv](csv)|application/json|a JSON array, with each row as another array (the first row has the dimension names) +`datasource`|[json](json)|application/json|a Google Visualization Provider `datasource` javascript callback +`datatable`|[json](json)|application/json|a Google `datatable` +`html`|[csv](csv)|text/html|an html table +`json`|[json](json)|application/json|a JSON object +`jsonp`|[json](json)|application/json|a JSONP javascript callback +`markdown`|[csv](csv)|text/plain|a markdown table +`ssv`|[ssv](ssv)|text/plain|a space separated list of values +`ssvcomma`|[ssv](ssv)|text/plain|a comma separated list of values +`tsv`|[csv](csv)|text/plain|a TAB delimited `csv` (MS Excel flavor) + +For examples of each format, check the relative module documentation. + +## Metadata with the `jsonwrap` option + +All data queries can be encapsulated to JSON object having metadata about the query and the results. + +This is done by adding the `options=jsonwrap` to the API URL (if there are other `options` append +`,jsonwrap` to the existing ones). + +This is such an object: + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=system.cpu&after=-3600&points=6&group=average&format=csv&options=nonzero,jsonwrap' +{ + "api": 1, + "id": "system.cpu", + "name": "system.cpu", + "view_update_every": 600, + "update_every": 1, + "first_entry": 1540387074, + "last_entry": 1540647070, + "before": 1540647000, + "after": 1540644000, + "dimension_names": ["steal", "softirq", "user", "system", "iowait"], + "dimension_ids": ["steal", "softirq", "user", "system", "iowait"], + "latest_values": [0, 0.2493766, 1.745636, 0.4987531, 0], + "view_latest_values": [0.0158314, 0.0516506, 0.866549, 0.7196127, 0.0050002], + "dimensions": 5, + "points": 6, + "format": "csv", + "result": "time,steal,softirq,user,system,iowait\n2018-10-27 13:30:00,0.0158314,0.0516506,0.866549,0.7196127,0.0050002\n2018-10-27 13:20:00,0.0149856,0.0529183,0.8673155,0.7121144,0.0049979\n2018-10-27 13:10:00,0.0137501,0.053315,0.8578097,0.7197613,0.0054209\n2018-10-27 13:00:00,0.0154252,0.0554688,0.899432,0.7200638,0.0067252\n2018-10-27 12:50:00,0.0145866,0.0495922,0.8404341,0.7011141,0.0041688\n2018-10-27 12:40:00,0.0162366,0.0595954,0.8827475,0.7020573,0.0041636\n", + "min": 0, + "max": 0 +} +``` + +## Downloading data query result files + +Following the [Google Visualization Provider guidelines](https://developers.google.com/chart/interactive/docs/dev/implementing_data_source), +netdata supports parsing `tqx` options. + +Using these options, any netdata data query can instruct the web browser to download +the result and save it under a given filename. + +For example, to download a CSV file with CPU utilization of the last hour, +[click here](https://registry.my-netdata.io/api/v1/data?chart=system.cpu&after=-3600&format=csv&options=nonzero&tqx=outFileName:system+cpu+utilization+of+the+last_hour.csv). + + +This is done by appending `&tqx=outFileName:FILENAME` to any data query. +The output will be in the format given with `&format=`. + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fformatters%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/formatters/charts2json.c b/web/api/formatters/charts2json.c new file mode 100644 index 0000000..f60f7f5 --- /dev/null +++ b/web/api/formatters/charts2json.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "charts2json.h" + +// generate JSON for the /api/v1/charts API call + +void charts2json(RRDHOST *host, BUFFER *wb) { + static char *custom_dashboard_info_js_filename = NULL; + size_t c, dimensions = 0, memory = 0, alarms = 0; + RRDSET *st; + + time_t now = now_realtime_sec(); + + if(unlikely(!custom_dashboard_info_js_filename)) + custom_dashboard_info_js_filename = config_get(CONFIG_SECTION_WEB, "custom dashboard_info.js", ""); + + buffer_sprintf(wb, "{\n" + "\t\"hostname\": \"%s\"" + ",\n\t\"version\": \"%s\"" + ",\n\t\"os\": \"%s\"" + ",\n\t\"timezone\": \"%s\"" + ",\n\t\"update_every\": %d" + ",\n\t\"history\": %ld" + ",\n\t\"custom_info\": \"%s\"" + ",\n\t\"charts\": {" + , host->hostname + , host->program_version + , host->os + , host->timezone + , host->rrd_update_every + , host->rrd_history_entries + , custom_dashboard_info_js_filename + ); + + c = 0; + rrdhost_rdlock(host); + rrdset_foreach_read(st, host) { + if(rrdset_is_available_for_viewers(st)) { + if(c) buffer_strcat(wb, ","); + buffer_strcat(wb, "\n\t\t\""); + buffer_strcat(wb, st->id); + buffer_strcat(wb, "\": "); + rrdset2json(st, wb, &dimensions, &memory); + + c++; + st->last_accessed_time = now; + } + } + + RRDCALC *rc; + for(rc = host->alarms; rc ; rc = rc->next) { + if(rc->rrdset) + alarms++; + } + rrdhost_unlock(host); + + buffer_sprintf(wb + , "\n\t}" + ",\n\t\"charts_count\": %zu" + ",\n\t\"dimensions_count\": %zu" + ",\n\t\"alarms_count\": %zu" + ",\n\t\"rrd_memory_bytes\": %zu" + ",\n\t\"hosts_count\": %zu" + ",\n\t\"hosts\": [" + , c + , dimensions + , alarms + , memory + , rrd_hosts_available + ); + + if(unlikely(rrd_hosts_available > 1)) { + rrd_rdlock(); + + size_t found = 0; + RRDHOST *h; + rrdhost_foreach_read(h) { + if(!rrdhost_should_be_removed(h, host, now)) { + buffer_sprintf(wb + , "%s\n\t\t{" + "\n\t\t\t\"hostname\": \"%s\"" + "\n\t\t}" + , (found > 0) ? "," : "" + , h->hostname + ); + + found++; + } + } + + rrd_unlock(); + } + else { + buffer_sprintf(wb + , "\n\t\t{" + "\n\t\t\t\"hostname\": \"%s\"" + "\n\t\t}" + , host->hostname + ); + } + + buffer_sprintf(wb, "\n\t]\n}\n"); +} diff --git a/web/api/formatters/charts2json.h b/web/api/formatters/charts2json.h new file mode 100644 index 0000000..5d6d800 --- /dev/null +++ b/web/api/formatters/charts2json.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_CHARTS2JSON_H +#define NETDATA_API_FORMATTER_CHARTS2JSON_H + +#include "rrd2json.h" + +extern void charts2json(RRDHOST *host, BUFFER *wb); + +#endif //NETDATA_API_FORMATTER_CHARTS2JSON_H diff --git a/web/api/formatters/csv/Makefile.am b/web/api/formatters/csv/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/formatters/csv/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/formatters/csv/README.md b/web/api/formatters/csv/README.md new file mode 100644 index 0000000..995e740 --- /dev/null +++ b/web/api/formatters/csv/README.md @@ -0,0 +1,141 @@ +# CSV formatter + +The CSV formatter presents [results of database queries](../../queries) in the following formats: + +format|content type|description +:---:|:---:|:----- +`csv`|text/plain|a text table, comma separated, with a header line (dimension names) and `\r\n` at the end of the lines +`csvjsonarray`|application/json|a JSON array, with each row as another array (the first row has the dimension names) +`tsv`|text/plain|like `csv` but TAB is used instead of comma to separate values (MS Excel flavor) +`html`|text/html|an html table +`markdown`|text/plain|markdown table + +In all formats the date and time is the first column. + +The CSV formatter respects the following API `&options=`: + +option|supported|description +:---:|:---:|:--- +`nonzero`|yes|to return only the dimensions that have at least a non-zero value +`flip`|yes|to return the rows older to newer (the default is newer to older) +`seconds`|yes|to return the date and time in unix timestamp +`ms`|yes|to return the date and time in unit timestamp as milliseconds +`percent`|yes|to replace all values with their percentage over the row total +`abs`|yes|to turn all values positive +`null2zero`|yes|to replace gaps with zeros (the default prints the string `null` + + +## Examples + +Get the system total bandwidth for all physical network interfaces, over the last hour, +in 6 rows (one for every 10 minutes), in `csv` format: + +Netdata always returns bandwidth in `kilobits`. + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=system.net&format=csv&after=-3600&group=sum&points=6&options=abs' +time,received,sent +2018-10-26 23:50:00,90214.67847,215137.79762 +2018-10-26 23:40:00,90126.32286,238587.57522 +2018-10-26 23:30:00,86061.22688,213389.23526 +2018-10-26 23:20:00,85590.75164,206129.01608 +2018-10-26 23:10:00,83163.30691,194311.77384 +2018-10-26 23:00:00,85167.29657,197538.07773 +``` + +--- + +Get the max RAM used by the SQL server and any cron jobs, over the last hour, in 2 rows (one for every 30 +minutes), in `tsv` format, and format the date and time as unix timestamp: + +Netdata always returns memory in `MB`. + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=apps.mem&format=tsv&after=-3600&group=max&points=2&options=nonzero,seconds&dimensions=sql,cron' +time sql cron +1540598400 61.95703 0.25 +1540596600 61.95703 0.25 +``` + +--- + +Get an HTML table of the last 4 values (4 seconds) of system CPU utilization: + +Netdata always returns CPU utilization as `%`. + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=system.cpu&format=html&after=-4&options=nonzero' +<html> +<center> +<table border="0" cellpadding="5" cellspacing="5"> +<tr><td>time</td><td>softirq</td><td>user</td><td>system</td></tr> +<tr><td>2018-10-27 00:16:07</td><td>0.25</td><td>1</td><td>0.75</td></tr> +<tr><td>2018-10-27 00:16:06</td><td>0</td><td>1.0025063</td><td>0.5012531</td></tr> +<tr><td>2018-10-27 00:16:05</td><td>0</td><td>1</td><td>0.75</td></tr> +<tr><td>2018-10-27 00:16:04</td><td>0</td><td>1.0025063</td><td>0.7518797</td></tr> +</table> +</center> +</html> +``` + +This is how it looks when rendered by a web browser: + +![image](https://user-images.githubusercontent.com/2662304/47597887-bafbf480-d99c-11e8-864a-d880bb8d2e5b.png) + + +--- + +Get a JSON array with the average bandwidth rate of the mysql server, over the last hour, in 6 values +(one every 10 minutes), and return the date and time in milliseconds: + +Netdata always returns bandwidth rates in `kilobits/s`. + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=mysql_local.net&format=csvjsonarray&after=-3600&points=6&group=average&options=abs,ms' +[ +["time","in","out"], +[1540599600000,0.7499986,120.2810185], +[1540599000000,0.7500019,120.2815509], +[1540598400000,0.7499999,120.2812319], +[1540597800000,0.7500044,120.2819634], +[1540597200000,0.7499968,120.2807337], +[1540596600000,0.7499988,120.2810527] +] +``` + +--- + +Get the number of processes started per minute, for the last 10 minutes, in `markdown` format: + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=system.forks&format=markdown&after=-600&points=10&group=sum' +time|started +:---:|:---: +2018-10-27 03:52:00|245.1706149 +2018-10-27 03:51:00|152.6654636 +2018-10-27 03:50:00|163.1755789 +2018-10-27 03:49:00|176.1574766 +2018-10-27 03:48:00|178.0137076 +2018-10-27 03:47:00|183.8306543 +2018-10-27 03:46:00|264.1635621 +2018-10-27 03:45:00|205.001551 +2018-10-27 03:44:00|7026.9852167 +2018-10-27 03:43:00|205.9904794 +``` + +And this is how it looks when formatted: + +time|started +:---:|:---: +2018-10-27 03:52:00|245.1706149 +2018-10-27 03:51:00|152.6654636 +2018-10-27 03:50:00|163.1755789 +2018-10-27 03:49:00|176.1574766 +2018-10-27 03:48:00|178.0137076 +2018-10-27 03:47:00|183.8306543 +2018-10-27 03:46:00|264.1635621 +2018-10-27 03:45:00|205.001551 +2018-10-27 03:44:00|7026.9852167 +2018-10-27 03:43:00|205.9904794 + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fformatters%2Fcsv%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/formatters/csv/csv.c b/web/api/formatters/csv/csv.c new file mode 100644 index 0000000..53bf298 --- /dev/null +++ b/web/api/formatters/csv/csv.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "libnetdata/libnetdata.h" +#include "csv.h" + +void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, const char *startline, const char *separator, const char *endline, const char *betweenlines) { + rrdset_check_rdlock(r->st); + + //info("RRD2CSV(): %s: BEGIN", r->st->id); + long c, i; + RRDDIM *d; + + // print the csv header + for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(!i) { + buffer_strcat(wb, startline); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + buffer_strcat(wb, "time"); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + } + buffer_strcat(wb, separator); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + buffer_strcat(wb, d->name); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + i++; + } + buffer_strcat(wb, endline); + + if(format == DATASOURCE_CSV_MARKDOWN) { + // print the --- line after header + for(c = 0, i = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(!i) { + buffer_strcat(wb, startline); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + buffer_strcat(wb, ":---:"); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + } + buffer_strcat(wb, separator); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + buffer_strcat(wb, ":---:"); + if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\""); + i++; + } + buffer_strcat(wb, endline); + } + + if(!i) { + // no dimensions present + return; + } + + long start = 0, end = rrdr_rows(r), step = 1; + if(!(options & RRDR_OPTION_REVERSED)) { + start = rrdr_rows(r) - 1; + end = -1; + step = -1; + } + + // for each line in the array + calculated_number total = 1; + for(i = start; i != end ;i += step) { + calculated_number *cn = &r->v[ i * r->d ]; + RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ]; + + buffer_strcat(wb, betweenlines); + buffer_strcat(wb, startline); + + time_t now = r->t[i]; + + if((options & RRDR_OPTION_SECONDS) || (options & RRDR_OPTION_MILLISECONDS)) { + // print the timestamp of the line + buffer_rrd_value(wb, (calculated_number)now); + // in ms + if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000"); + } + else { + // generate the local date time + struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); + if(!tm) { error("localtime() failed."); continue; } + buffer_date(wb, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + } + + int set_min_max = 0; + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + total = 0; + for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + calculated_number n = cn[c]; + + if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + total += n; + } + // prevent a division by zero + if(total == 0) total = 1; + set_min_max = 1; + } + + // for each dimension + for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + buffer_strcat(wb, separator); + + calculated_number n = cn[c]; + + if(co[c] & RRDR_VALUE_EMPTY) { + if(options & RRDR_OPTION_NULL2ZERO) + buffer_strcat(wb, "0"); + else + buffer_strcat(wb, "null"); + } + else { + if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + n = n * 100 / total; + + if(unlikely(set_min_max)) { + r->min = r->max = n; + set_min_max = 0; + } + + if(n < r->min) r->min = n; + if(n > r->max) r->max = n; + } + + buffer_rrd_value(wb, n); + } + } + + buffer_strcat(wb, endline); + } + //info("RRD2CSV(): %s: END", r->st->id); +} diff --git a/web/api/formatters/csv/csv.h b/web/api/formatters/csv/csv.h new file mode 100644 index 0000000..a89742d --- /dev/null +++ b/web/api/formatters/csv/csv.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_CSV_H +#define NETDATA_API_FORMATTER_CSV_H + +#include "web/api/queries/rrdr.h" + +extern void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, const char *startline, const char *separator, const char *endline, const char *betweenlines); + +#include "../rrd2json.h" + +#endif //NETDATA_API_FORMATTER_CSV_H diff --git a/web/api/formatters/json/Makefile.am b/web/api/formatters/json/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/formatters/json/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/formatters/json/README.md b/web/api/formatters/json/README.md new file mode 100644 index 0000000..033bf8e --- /dev/null +++ b/web/api/formatters/json/README.md @@ -0,0 +1,152 @@ +# JSON formatter + +The CSV formatter presents [results of database queries](../../queries) in the following formats: + +format|content type|description +:---:|:---:|:----- +`json`|application/json|return the query result as a json object +`jsonp`|application/json|return the query result as a JSONP javascript callback +`datatable`|application/json|return the query result as a Google `datatable` +`datasource`|application/json|return the query result as a Google Visualization Provider `datasource` javascript callback + +The CSV formatter respects the following API `&options=`: + +option|supported|description +:---:|:---:|:--- +`google_json`|yes|enable the Google flavor of JSON (using double quotes for strings and `Date()` function for dates +`objectrows`|yes|return each row as an object, instead of an array +`nonzero`|yes|to return only the dimensions that have at least a non-zero value +`flip`|yes|to return the rows older to newer (the default is newer to older) +`seconds`|yes|to return the date and time in unix timestamp +`ms`|yes|to return the date and time in unit timestamp as milliseconds +`percent`|yes|to replace all values with their percentage over the row total +`abs`|yes|to turn all values positive +`null2zero`|yes|to replace gaps with zeros (the default prints the string `null` + +## Examples + +To show the differences between each format, in the following examples we query the same +chart (having just one dimension called `active`), changing only the query `format` and its `options`. + +> Using `format=json` and `options=` + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&format=json&options=' +{ + "labels": ["time", "active"], + "data": + [ + [ 1540644600, 224.2516667], + [ 1540644000, 229.29], + [ 1540643400, 222.41], + [ 1540642800, 226.6816667], + [ 1540642200, 246.4083333], + [ 1540641600, 241.0966667] + ] +} +``` + +> Using `format=json` and `options=objectrows` + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&format=json&options=objectrows' +{ + "labels": ["time", "active"], + "data": + [ + { "time": 1540644600, "active": 224.2516667}, + { "time": 1540644000, "active": 229.29}, + { "time": 1540643400, "active": 222.41}, + { "time": 1540642800, "active": 226.6816667}, + { "time": 1540642200, "active": 246.4083333}, + { "time": 1540641600, "active": 241.0966667} + ] +} +``` + +> Using `format=json` and `options=objectrows,google_json` + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&formatjson&options=objectrows,google_json' +{ + "labels": ["time", "active"], + "data": + [ + { "time": new Date(2018,9,27,12,50,0), "active": 224.2516667}, + { "time": new Date(2018,9,27,12,40,0), "active": 229.29}, + { "time": new Date(2018,9,27,12,30,0), "active": 222.41}, + { "time": new Date(2018,9,27,12,20,0), "active": 226.6816667}, + { "time": new Date(2018,9,27,12,10,0), "active": 246.4083333}, + { "time": new Date(2018,9,27,12,0,0), "active": 241.0966667} + ] +} +``` + +> Using `format=jsonp` and `options=` + +```bash +curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&formjsonp&options=' +callback({ + "labels": ["time", "active"], + "data": + [ + [ 1540645200, 235.885], + [ 1540644600, 224.2516667], + [ 1540644000, 229.29], + [ 1540643400, 222.41], + [ 1540642800, 226.6816667], + [ 1540642200, 246.4083333] + ] +}); +``` + +> Using `format=datatable` and `options=` + +```bash +$ curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&formdatatable&options=' +{ + "cols": + [ + {"id":"","label":"time","pattern":"","type":"datetime"}, + {"id":"","label":"","pattern":"","type":"string","p":{"role":"annotation"}}, + {"id":"","label":"","pattern":"","type":"string","p":{"role":"annotationText"}}, + {"id":"","label":"active","pattern":"","type":"number"} + ], + "rows": + [ + {"c":[{"v":"Date(2018,9,27,13,0,0)"},{"v":null},{"v":null},{"v":235.885}]}, + {"c":[{"v":"Date(2018,9,27,12,50,0)"},{"v":null},{"v":null},{"v":224.2516667}]}, + {"c":[{"v":"Date(2018,9,27,12,40,0)"},{"v":null},{"v":null},{"v":229.29}]}, + {"c":[{"v":"Date(2018,9,27,12,30,0)"},{"v":null},{"v":null},{"v":222.41}]}, + {"c":[{"v":"Date(2018,9,27,12,20,0)"},{"v":null},{"v":null},{"v":226.6816667}]}, + {"c":[{"v":"Date(2018,9,27,12,10,0)"},{"v":null},{"v":null},{"v":246.4083333}]} + ] +} +``` + +> Using `format=datasource` and `options=` + +```bash +curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&after=-3600&points=6&group=average&format=datasource&options=' +google.visualization.Query.setResponse({version:'0.6',reqId:'0',status:'ok',sig:'1540645368',table:{ + "cols": + [ + {"id":"","label":"time","pattern":"","type":"datetime"}, + {"id":"","label":"","pattern":"","type":"string","p":{"role":"annotation"}}, + {"id":"","label":"","pattern":"","type":"string","p":{"role":"annotationText"}}, + {"id":"","label":"active","pattern":"","type":"number"} + ], + "rows": + [ + {"c":[{"v":"Date(2018,9,27,13,0,0)"},{"v":null},{"v":null},{"v":235.885}]}, + {"c":[{"v":"Date(2018,9,27,12,50,0)"},{"v":null},{"v":null},{"v":224.2516667}]}, + {"c":[{"v":"Date(2018,9,27,12,40,0)"},{"v":null},{"v":null},{"v":229.29}]}, + {"c":[{"v":"Date(2018,9,27,12,30,0)"},{"v":null},{"v":null},{"v":222.41}]}, + {"c":[{"v":"Date(2018,9,27,12,20,0)"},{"v":null},{"v":null},{"v":226.6816667}]}, + {"c":[{"v":"Date(2018,9,27,12,10,0)"},{"v":null},{"v":null},{"v":246.4083333}]} + ] +}}); +``` + + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fformatters%2Fjson%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/formatters/json/json.c b/web/api/formatters/json/json.c new file mode 100644 index 0000000..66b3b9c --- /dev/null +++ b/web/api/formatters/json/json.c @@ -0,0 +1,246 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "json.h" + +#define JSON_DATES_JS 1 +#define JSON_DATES_TIMESTAMP 2 + +void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable) { + rrdset_check_rdlock(r->st); + + //info("RRD2JSON(): %s: BEGIN", r->st->id); + int row_annotations = 0, dates, dates_with_new = 0; + char kq[2] = "", // key quote + sq[2] = "", // string quote + pre_label[101] = "", // before each label + post_label[101] = "", // after each label + pre_date[101] = "", // the beginning of line, to the date + post_date[101] = "", // closing the date + pre_value[101] = "", // before each value + post_value[101] = "", // after each value + post_line[101] = "", // at the end of each row + normal_annotation[201] = "", // default row annotation + overflow_annotation[201] = "", // overflow row annotation + data_begin[101] = "", // between labels and values + finish[101] = ""; // at the end of everything + + if(datatable) { + dates = JSON_DATES_JS; + if( options & RRDR_OPTION_GOOGLE_JSON ) { + kq[0] = '\0'; + sq[0] = '\''; + } + else { + kq[0] = '"'; + sq[0] = '"'; + } + row_annotations = 1; + snprintfz(pre_date, 100, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq); + snprintfz(post_date, 100, "%s}", sq); + snprintfz(pre_label, 100, ",\n {%sid%s:%s%s,%slabel%s:%s", kq, kq, sq, sq, kq, kq, sq); + snprintfz(post_label, 100, "%s,%spattern%s:%s%s,%stype%s:%snumber%s}", sq, kq, kq, sq, sq, kq, kq, sq, sq); + snprintfz(pre_value, 100, ",{%sv%s:", kq, kq); + strcpy(post_value, "}"); + strcpy(post_line, "]}"); + snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq); + strcpy(finish, "\n ]\n}"); + + snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq); + snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq); + + buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq); + buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq); + buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); + buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq); + + // remove the valueobjects flag + // google wants its own keys + if(options & RRDR_OPTION_OBJECTSROWS) + options &= ~RRDR_OPTION_OBJECTSROWS; + } + else { + kq[0] = '"'; + sq[0] = '"'; + if(options & RRDR_OPTION_GOOGLE_JSON) { + dates = JSON_DATES_JS; + dates_with_new = 1; + } + else { + dates = JSON_DATES_TIMESTAMP; + dates_with_new = 0; + } + if( options & RRDR_OPTION_OBJECTSROWS ) + strcpy(pre_date, " { "); + else + strcpy(pre_date, " [ "); + strcpy(pre_label, ", \""); + strcpy(post_label, "\""); + strcpy(pre_value, ", "); + if( options & RRDR_OPTION_OBJECTSROWS ) + strcpy(post_line, "}"); + else + strcpy(post_line, "]"); + snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq); + strcpy(finish, "\n ]\n}"); + + buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq); + buffer_sprintf(wb, "%stime%s", sq, sq); + } + + // ------------------------------------------------------------------------- + // print the JSON header + + long c, i; + RRDDIM *rd; + + // print the header lines + for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + buffer_strcat(wb, pre_label); + buffer_strcat(wb, rd->name); + buffer_strcat(wb, post_label); + i++; + } + if(!i) { + buffer_strcat(wb, pre_label); + buffer_strcat(wb, "no data"); + buffer_strcat(wb, post_label); + } + + // print the begin of row data + buffer_strcat(wb, data_begin); + + // if all dimensions are hidden, print a null + if(!i) { + buffer_strcat(wb, finish); + return; + } + + long start = 0, end = rrdr_rows(r), step = 1; + if(!(options & RRDR_OPTION_REVERSED)) { + start = rrdr_rows(r) - 1; + end = -1; + step = -1; + } + + // for each line in the array + calculated_number total = 1; + for(i = start; i != end ;i += step) { + calculated_number *cn = &r->v[ i * r->d ]; + RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ]; + + time_t now = r->t[i]; + + if(dates == JSON_DATES_JS) { + // generate the local date time + struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); + if(!tm) { error("localtime_r() failed."); continue; } + + if(likely(i != start)) buffer_strcat(wb, ",\n"); + buffer_strcat(wb, pre_date); + + if( options & RRDR_OPTION_OBJECTSROWS ) + buffer_sprintf(wb, "%stime%s: ", kq, kq); + + if(dates_with_new) + buffer_strcat(wb, "new "); + + buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + + buffer_strcat(wb, post_date); + + if(row_annotations) { + // google supports one annotation per row + int annotation_found = 0; + for(c = 0, rd = r->st->dimensions; rd ;c++, rd = rd->next) { + if(unlikely(!(r->od[c] & RRDR_DIMENSION_SELECTED))) continue; + + if(co[c] & RRDR_VALUE_RESET) { + buffer_strcat(wb, overflow_annotation); + annotation_found = 1; + break; + } + } + if(!annotation_found) + buffer_strcat(wb, normal_annotation); + } + } + else { + // print the timestamp of the line + if(likely(i != start)) buffer_strcat(wb, ",\n"); + buffer_strcat(wb, pre_date); + + if( options & RRDR_OPTION_OBJECTSROWS ) + buffer_sprintf(wb, "%stime%s: ", kq, kq); + + buffer_rrd_value(wb, (calculated_number)r->t[i]); + // in ms + if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000"); + + buffer_strcat(wb, post_date); + } + + int set_min_max = 0; + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + total = 0; + for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + calculated_number n = cn[c]; + + if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + total += n; + } + // prevent a division by zero + if(total == 0) total = 1; + set_min_max = 1; + } + + // for each dimension + for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + calculated_number n = cn[c]; + + buffer_strcat(wb, pre_value); + + if( options & RRDR_OPTION_OBJECTSROWS ) + buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq); + + if(co[c] & RRDR_VALUE_EMPTY) { + if(options & RRDR_OPTION_NULL2ZERO) + buffer_strcat(wb, "0"); + else + buffer_strcat(wb, "null"); + } + else { + if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + n = n * 100 / total; + + if(unlikely(set_min_max)) { + r->min = r->max = n; + set_min_max = 0; + } + + if(n < r->min) r->min = n; + if(n > r->max) r->max = n; + } + + buffer_rrd_value(wb, n); + } + + buffer_strcat(wb, post_value); + } + + buffer_strcat(wb, post_line); + } + + buffer_strcat(wb, finish); + //info("RRD2JSON(): %s: END", r->st->id); +} diff --git a/web/api/formatters/json/json.h b/web/api/formatters/json/json.h new file mode 100644 index 0000000..01363ce --- /dev/null +++ b/web/api/formatters/json/json.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_JSON_H +#define NETDATA_API_FORMATTER_JSON_H + +#include "../rrd2json.h" + +extern void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable); + +#endif //NETDATA_API_FORMATTER_JSON_H diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c new file mode 100644 index 0000000..2538835 --- /dev/null +++ b/web/api/formatters/json_wrapper.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "json_wrapper.h" + +void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value) { + rrdset_check_rdlock(r->st); + + long rows = rrdr_rows(r); + long c, i; + RRDDIM *rd; + + //info("JSONWRAPPER(): %s: BEGIN", r->st->id); + char kq[2] = "", // key quote + sq[2] = ""; // string quote + + if( options & RRDR_OPTION_GOOGLE_JSON ) { + kq[0] = '\0'; + sq[0] = '\''; + } + else { + kq[0] = '"'; + sq[0] = '"'; + } + + buffer_sprintf(wb, "{\n" + " %sapi%s: 1,\n" + " %sid%s: %s%s%s,\n" + " %sname%s: %s%s%s,\n" + " %sview_update_every%s: %d,\n" + " %supdate_every%s: %d,\n" + " %sfirst_entry%s: %u,\n" + " %slast_entry%s: %u,\n" + " %sbefore%s: %u,\n" + " %safter%s: %u,\n" + " %sdimension_names%s: [" + , kq, kq + , kq, kq, sq, r->st->id, sq + , kq, kq, sq, r->st->name, sq + , kq, kq, r->update_every + , kq, kq, r->st->update_every + , kq, kq, (uint32_t)rrdset_first_entry_t(r->st) + , kq, kq, (uint32_t)rrdset_last_entry_t(r->st) + , kq, kq, (uint32_t)r->before + , kq, kq, (uint32_t)r->after + , kq, kq); + + for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(i) buffer_strcat(wb, ", "); + buffer_strcat(wb, sq); + buffer_strcat(wb, rd->name); + buffer_strcat(wb, sq); + i++; + } + if(!i) { +#ifdef NETDATA_INTERNAL_CHECKS + error("RRDR is empty for %s (RRDR has %d dimensions, options is 0x%08x)", r->st->id, r->d, options); +#endif + rows = 0; + buffer_strcat(wb, sq); + buffer_strcat(wb, "no data"); + buffer_strcat(wb, sq); + } + + buffer_sprintf(wb, "],\n" + " %sdimension_ids%s: [" + , kq, kq); + + for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(i) buffer_strcat(wb, ", "); + buffer_strcat(wb, sq); + buffer_strcat(wb, rd->id); + buffer_strcat(wb, sq); + i++; + } + if(!i) { + rows = 0; + buffer_strcat(wb, sq); + buffer_strcat(wb, "no data"); + buffer_strcat(wb, sq); + } + + buffer_sprintf(wb, "],\n" + " %slatest_values%s: [" + , kq, kq); + + for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(i) buffer_strcat(wb, ", "); + i++; + + storage_number n = rd->values[rrdset_last_slot(r->st)]; + + if(!does_storage_number_exist(n)) + buffer_strcat(wb, "null"); + else + buffer_rrd_value(wb, unpack_storage_number(n)); + } + if(!i) { + rows = 0; + buffer_strcat(wb, "null"); + } + + buffer_sprintf(wb, "],\n" + " %sview_latest_values%s: [" + , kq, kq); + + i = 0; + if(rows) { + calculated_number total = 1; + + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + total = 0; + for(c = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + calculated_number *cn = &r->v[ (rrdr_rows(r) - 1) * r->d ]; + calculated_number n = cn[c]; + + if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + total += n; + } + // prevent a division by zero + if(total == 0) total = 1; + } + + for(c = 0, i = 0, rd = r->st->dimensions; rd && c < r->d ;c++, rd = rd->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(i) buffer_strcat(wb, ", "); + i++; + + calculated_number *cn = &r->v[ (rrdr_rows(r) - 1) * r->d ]; + RRDR_VALUE_FLAGS *co = &r->o[ (rrdr_rows(r) - 1) * r->d ]; + calculated_number n = cn[c]; + + if(co[c] & RRDR_VALUE_EMPTY) { + if(options & RRDR_OPTION_NULL2ZERO) + buffer_strcat(wb, "0"); + else + buffer_strcat(wb, "null"); + } + else { + if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) + n = n * 100 / total; + + buffer_rrd_value(wb, n); + } + } + } + if(!i) { + rows = 0; + buffer_strcat(wb, "null"); + } + + buffer_sprintf(wb, "],\n" + " %sdimensions%s: %ld,\n" + " %spoints%s: %ld,\n" + " %sformat%s: %s" + , kq, kq, i + , kq, kq, rows + , kq, kq, sq + ); + + rrdr_buffer_print_format(wb, format); + + buffer_sprintf(wb, "%s,\n" + " %sresult%s: " + , sq + , kq, kq + ); + + if(string_value) buffer_strcat(wb, sq); + //info("JSONWRAPPER(): %s: END", r->st->id); +} + +void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value) { + (void)format; + + char kq[2] = "", // key quote + sq[2] = ""; // string quote + + if( options & RRDR_OPTION_GOOGLE_JSON ) { + kq[0] = '\0'; + sq[0] = '\''; + } + else { + kq[0] = '"'; + sq[0] = '"'; + } + + if(string_value) buffer_strcat(wb, sq); + + buffer_sprintf(wb, ",\n %smin%s: ", kq, kq); + buffer_rrd_value(wb, r->min); + buffer_sprintf(wb, ",\n %smax%s: ", kq, kq); + buffer_rrd_value(wb, r->max); + buffer_strcat(wb, "\n}\n"); +} diff --git a/web/api/formatters/json_wrapper.h b/web/api/formatters/json_wrapper.h new file mode 100644 index 0000000..7cb7d34 --- /dev/null +++ b/web/api/formatters/json_wrapper.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_JSON_WRAPPER_H +#define NETDATA_API_FORMATTER_JSON_WRAPPER_H + +#include "rrd2json.h" + +extern void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value); +extern void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value); + +#endif //NETDATA_API_FORMATTER_JSON_WRAPPER_H diff --git a/web/api/formatters/rrd2json.c b/web/api/formatters/rrd2json.c new file mode 100644 index 0000000..5cdcc80 --- /dev/null +++ b/web/api/formatters/rrd2json.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web/api/web_api_v1.h" + +void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb) { + rrdset2json(st, wb, NULL, NULL); +} + +void rrdr_buffer_print_format(BUFFER *wb, uint32_t format) { + switch(format) { + case DATASOURCE_JSON: + buffer_strcat(wb, DATASOURCE_FORMAT_JSON); + break; + + case DATASOURCE_DATATABLE_JSON: + buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSON); + break; + + case DATASOURCE_DATATABLE_JSONP: + buffer_strcat(wb, DATASOURCE_FORMAT_DATATABLE_JSONP); + break; + + case DATASOURCE_JSONP: + buffer_strcat(wb, DATASOURCE_FORMAT_JSONP); + break; + + case DATASOURCE_SSV: + buffer_strcat(wb, DATASOURCE_FORMAT_SSV); + break; + + case DATASOURCE_CSV: + buffer_strcat(wb, DATASOURCE_FORMAT_CSV); + break; + + case DATASOURCE_TSV: + buffer_strcat(wb, DATASOURCE_FORMAT_TSV); + break; + + case DATASOURCE_HTML: + buffer_strcat(wb, DATASOURCE_FORMAT_HTML); + break; + + case DATASOURCE_JS_ARRAY: + buffer_strcat(wb, DATASOURCE_FORMAT_JS_ARRAY); + break; + + case DATASOURCE_SSV_COMMA: + buffer_strcat(wb, DATASOURCE_FORMAT_SSV_COMMA); + break; + + default: + buffer_strcat(wb, "unknown"); + break; + } +} + +int rrdset2value_api_v1( + RRDSET *st + , BUFFER *wb + , calculated_number *n + , const char *dimensions + , long points + , long long after + , long long before + , int group_method + , long group_time + , uint32_t options + , time_t *db_after + , time_t *db_before + , int *value_is_null +) { + RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions); + if(!r) { + if(value_is_null) *value_is_null = 1; + return 500; + } + + if(rrdr_rows(r) == 0) { + rrdr_free(r); + + if(db_after) *db_after = 0; + if(db_before) *db_before = 0; + if(value_is_null) *value_is_null = 1; + + return 400; + } + + if(wb) { + if (r->result_options & RRDR_RESULT_OPTION_RELATIVE) + buffer_no_cacheable(wb); + else if (r->result_options & RRDR_RESULT_OPTION_ABSOLUTE) + buffer_cacheable(wb); + } + + if(db_after) *db_after = r->after; + if(db_before) *db_before = r->before; + + long i = (!(options & RRDR_OPTION_REVERSED))?rrdr_rows(r) - 1:0; + *n = rrdr2value(r, i, options, value_is_null); + + rrdr_free(r); + return 200; +} + +int rrdset2anything_api_v1( + RRDSET *st + , BUFFER *wb + , BUFFER *dimensions + , uint32_t format + , long points + , long long after + , long long before + , int group_method + , long group_time + , uint32_t options + , time_t *latest_timestamp +) { + st->last_accessed_time = now_realtime_sec(); + + RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL); + if(!r) { + buffer_strcat(wb, "Cannot generate output with these parameters on this chart."); + return 500; + } + + if(r->result_options & RRDR_RESULT_OPTION_RELATIVE) + buffer_no_cacheable(wb); + else if(r->result_options & RRDR_RESULT_OPTION_ABSOLUTE) + buffer_cacheable(wb); + + if(latest_timestamp && rrdr_rows(r) > 0) + *latest_timestamp = r->before; + + switch(format) { + case DATASOURCE_SSV: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + rrdr2ssv(r, wb, options, "", " ", ""); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_PLAIN; + rrdr2ssv(r, wb, options, "", " ", ""); + } + break; + + case DATASOURCE_SSV_COMMA: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + rrdr2ssv(r, wb, options, "", ",", ""); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_PLAIN; + rrdr2ssv(r, wb, options, "", ",", ""); + } + break; + + case DATASOURCE_JS_ARRAY: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 0); + rrdr2ssv(r, wb, options, "[", ",", "]"); + rrdr_json_wrapper_end(r, wb, format, options, 0); + } + else { + wb->contenttype = CT_APPLICATION_JSON; + rrdr2ssv(r, wb, options, "[", ",", "]"); + } + break; + + case DATASOURCE_CSV: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + rrdr2csv(r, wb, format, options, "", ",", "\\n", ""); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_PLAIN; + rrdr2csv(r, wb, format, options, "", ",", "\r\n", ""); + } + break; + + case DATASOURCE_CSV_MARKDOWN: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + rrdr2csv(r, wb, format, options, "", "|", "\\n", ""); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_PLAIN; + rrdr2csv(r, wb, format, options, "", "|", "\r\n", ""); + } + break; + + case DATASOURCE_CSV_JSON_ARRAY: + wb->contenttype = CT_APPLICATION_JSON; + if(options & RRDR_OPTION_JSON_WRAP) { + rrdr_json_wrapper_begin(r, wb, format, options, 0); + buffer_strcat(wb, "[\n"); + rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n"); + buffer_strcat(wb, "\n]"); + rrdr_json_wrapper_end(r, wb, format, options, 0); + } + else { + wb->contenttype = CT_APPLICATION_JSON; + buffer_strcat(wb, "[\n"); + rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n"); + buffer_strcat(wb, "\n]"); + } + break; + + case DATASOURCE_TSV: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + rrdr2csv(r, wb, format, options, "", "\t", "\\n", ""); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_PLAIN; + rrdr2csv(r, wb, format, options, "", "\t", "\r\n", ""); + } + break; + + case DATASOURCE_HTML: + if(options & RRDR_OPTION_JSON_WRAP) { + wb->contenttype = CT_APPLICATION_JSON; + rrdr_json_wrapper_begin(r, wb, format, options, 1); + buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n"); + rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\\n", ""); + buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n"); + rrdr_json_wrapper_end(r, wb, format, options, 1); + } + else { + wb->contenttype = CT_TEXT_HTML; + buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n"); + rrdr2csv(r, wb, format, options, "<tr><td>", "</td><td>", "</td></tr>\n", ""); + buffer_strcat(wb, "</table>\n</center>\n</html>\n"); + } + break; + + case DATASOURCE_DATATABLE_JSONP: + wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_begin(r, wb, format, options, 0); + + rrdr2json(r, wb, options, 1); + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_end(r, wb, format, options, 0); + break; + + case DATASOURCE_DATATABLE_JSON: + wb->contenttype = CT_APPLICATION_JSON; + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_begin(r, wb, format, options, 0); + + rrdr2json(r, wb, options, 1); + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_end(r, wb, format, options, 0); + break; + + case DATASOURCE_JSONP: + wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_begin(r, wb, format, options, 0); + + rrdr2json(r, wb, options, 0); + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_end(r, wb, format, options, 0); + break; + + case DATASOURCE_JSON: + default: + wb->contenttype = CT_APPLICATION_JSON; + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_begin(r, wb, format, options, 0); + + rrdr2json(r, wb, options, 0); + + if(options & RRDR_OPTION_JSON_WRAP) + rrdr_json_wrapper_end(r, wb, format, options, 0); + break; + } + + rrdr_free(r); + return 200; +} diff --git a/web/api/formatters/rrd2json.h b/web/api/formatters/rrd2json.h new file mode 100644 index 0000000..bac6130 --- /dev/null +++ b/web/api/formatters/rrd2json.h @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_RRD2JSON_H +#define NETDATA_RRD2JSON_H 1 + +#include "web/api/web_api_v1.h" +#include "web/api/exporters/allmetrics.h" +#include "web/api/queries/rrdr.h" + +#include "web/api/formatters/csv/csv.h" +#include "web/api/formatters/ssv/ssv.h" +#include "web/api/formatters/json/json.h" +#include "web/api/formatters/value/value.h" + +#include "web/api/formatters/rrdset2json.h" +#include "web/api/formatters/charts2json.h" +#include "web/api/formatters/json_wrapper.h" + +#define HOSTNAME_MAX 1024 + +#define API_RELATIVE_TIME_MAX (3 * 365 * 86400) + +// type of JSON generations +#define DATASOURCE_INVALID (-1) +#define DATASOURCE_JSON 0 +#define DATASOURCE_DATATABLE_JSON 1 +#define DATASOURCE_DATATABLE_JSONP 2 +#define DATASOURCE_SSV 3 +#define DATASOURCE_CSV 4 +#define DATASOURCE_JSONP 5 +#define DATASOURCE_TSV 6 +#define DATASOURCE_HTML 7 +#define DATASOURCE_JS_ARRAY 8 +#define DATASOURCE_SSV_COMMA 9 +#define DATASOURCE_CSV_JSON_ARRAY 10 +#define DATASOURCE_CSV_MARKDOWN 11 + +#define DATASOURCE_FORMAT_JSON "json" +#define DATASOURCE_FORMAT_DATATABLE_JSON "datatable" +#define DATASOURCE_FORMAT_DATATABLE_JSONP "datasource" +#define DATASOURCE_FORMAT_JSONP "jsonp" +#define DATASOURCE_FORMAT_SSV "ssv" +#define DATASOURCE_FORMAT_CSV "csv" +#define DATASOURCE_FORMAT_TSV "tsv" +#define DATASOURCE_FORMAT_HTML "html" +#define DATASOURCE_FORMAT_JS_ARRAY "array" +#define DATASOURCE_FORMAT_SSV_COMMA "ssvcomma" +#define DATASOURCE_FORMAT_CSV_JSON_ARRAY "csvjsonarray" +#define DATASOURCE_FORMAT_CSV_MARKDOWN "markdown" + +extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); +extern void rrdr_buffer_print_format(BUFFER *wb, uint32_t format); + +extern int rrdset2anything_api_v1( + RRDSET *st + , BUFFER *wb + , BUFFER *dimensions + , uint32_t format + , long points + , long long after + , long long before + , int group_method + , long group_time + , uint32_t options + , time_t *latest_timestamp +); + +extern int rrdset2value_api_v1( + RRDSET *st + , BUFFER *wb + , calculated_number *n + , const char *dimensions + , long points + , long long after + , long long before + , int group_method + , long group_time + , uint32_t options + , time_t *db_after + , time_t *db_before + , int *value_is_null +); + +#endif /* NETDATA_RRD2JSON_H */ diff --git a/web/api/formatters/rrdset2json.c b/web/api/formatters/rrdset2json.c new file mode 100644 index 0000000..6d57e34 --- /dev/null +++ b/web/api/formatters/rrdset2json.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrdset2json.h" + +// generate JSON for the /api/v1/chart API call + +void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used) { + rrdset_rdlock(st); + + buffer_sprintf(wb, + "\t\t{\n" + "\t\t\t\"id\": \"%s\",\n" + "\t\t\t\"name\": \"%s\",\n" + "\t\t\t\"type\": \"%s\",\n" + "\t\t\t\"family\": \"%s\",\n" + "\t\t\t\"context\": \"%s\",\n" + "\t\t\t\"title\": \"%s (%s)\",\n" + "\t\t\t\"priority\": %ld,\n" + "\t\t\t\"plugin\": \"%s\",\n" + "\t\t\t\"module\": \"%s\",\n" + "\t\t\t\"enabled\": %s,\n" + "\t\t\t\"units\": \"%s\",\n" + "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n" + "\t\t\t\"chart_type\": \"%s\",\n" + "\t\t\t\"duration\": %ld,\n" + "\t\t\t\"first_entry\": %ld,\n" + "\t\t\t\"last_entry\": %ld,\n" + "\t\t\t\"update_every\": %d,\n" + "\t\t\t\"dimensions\": {\n" + , st->id + , st->name + , st->type + , st->family + , st->context + , st->title, st->name + , st->priority + , st->plugin_name?st->plugin_name:"" + , st->module_name?st->module_name:"" + , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?"true":"false" + , st->units + , st->name + , rrdset_type_name(st->chart_type) + , st->entries * st->update_every + , rrdset_first_entry_t(st) + , rrdset_last_entry_t(st) + , st->update_every + ); + + unsigned long memory = st->memsize; + + size_t dimensions = 0; + RRDDIM *rd; + rrddim_foreach_read(rd, st) { + if(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)) continue; + + memory += rd->memsize; + + buffer_sprintf( + wb + , "%s" + "\t\t\t\t\"%s\": { \"name\": \"%s\" }" + , dimensions ? ",\n" : "" + , rd->id + , rd->name + ); + + dimensions++; + } + + if(dimensions_count) *dimensions_count += dimensions; + if(memory_used) *memory_used += memory; + + buffer_strcat(wb, "\n\t\t\t},\n\t\t\t\"green\": "); + buffer_rrd_value(wb, st->green); + buffer_strcat(wb, ",\n\t\t\t\"red\": "); + buffer_rrd_value(wb, st->red); + + buffer_strcat(wb, ",\n\t\t\t\"alarms\": {\n"); + size_t alarms = 0; + RRDCALC *rc; + for(rc = st->alarms; rc ; rc = rc->rrdset_next) { + + buffer_sprintf( + wb + , "%s" + "\t\t\t\t\"%s\": {\n" + "\t\t\t\t\t\"id\": %u,\n" + "\t\t\t\t\t\"status\": \"%s\",\n" + "\t\t\t\t\t\"units\": \"%s\",\n" + "\t\t\t\t\t\"update_every\": %d\n" + "\t\t\t\t}" + , (alarms) ? ",\n" : "" + , rc->name + , rc->id + , rrdcalc_status2string(rc->status) + , rc->units + , rc->update_every + ); + + alarms++; + } + + buffer_sprintf(wb, + "\n\t\t\t}\n\t\t}" + ); + + rrdset_unlock(st); +} diff --git a/web/api/formatters/rrdset2json.h b/web/api/formatters/rrdset2json.h new file mode 100644 index 0000000..b2669ec --- /dev/null +++ b/web/api/formatters/rrdset2json.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_RRDSET2JSON_H +#define NETDATA_API_FORMATTER_RRDSET2JSON_H + +#include "rrd2json.h" + +extern void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memory_used); + +#endif //NETDATA_API_FORMATTER_RRDSET2JSON_H diff --git a/web/api/formatters/ssv/Makefile.am b/web/api/formatters/ssv/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/formatters/ssv/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/formatters/ssv/README.md b/web/api/formatters/ssv/README.md new file mode 100644 index 0000000..a289299 --- /dev/null +++ b/web/api/formatters/ssv/README.md @@ -0,0 +1,54 @@ +# SSV formatter + +The SSV formatter sums all dimensions in [results of database queries](../../queries) +to a single value and returns a list of such values showing how it changes through time. + +It supports the following formats: + +format|content type|description +:---:|:---:|:----- +`ssv`|text/plain|a space separated list of values +`ssvcomma`|text/plain|a comma separated list of values +`array`|application/json|a JSON array + +The CSV formatter respects the following API `&options=`: + +option|supported|description +:---:|:---:|:--- +`nonzero`|yes|to return only the dimensions that have at least a non-zero value +`flip`|yes|to return the numbers older to newer (the default is newer to older) +`percent`|yes|to replace all values with their percentage over the row total +`abs`|yes|to turn all values positive, before using them +`min2max`|yes|to return the delta from the minimum value to the maximum value (across dimensions) + +## Examples + +Get the average system CPU utilization of the last hour, in 6 values (one every 10 minutes): + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=system.cpu&format=ssv&after=-3600&points=6&group=average' +1.741352 1.6800467 1.769411 1.6761112 1.629862 1.6807968 +``` + +--- + +Get the total mysql bandwidth (in + out) for the last hour, in 6 values (one every 10 minutes): + +Netdata returns bandwidth in `kilobits`. + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=mysql_local.net&format=ssvcomma&after=-3600&points=6&group=sum&options=abs' +72618.7936215,72618.778889,72618.788084,72618.9195918,72618.7760612,72618.6712421 +``` + +--- + +Get the web server max connections for the last hour, in 12 values (one every 5 minutes) +in a JSON array: + +```bash +# curl -Ss 'https://registry.my-netdata.io/api/v1/data?chart=nginx_local.connections&format=array&after=-3600&points=12&group=max' +[278,258,268,239,259,260,243,266,278,318,264,258] +``` + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fformatters%2Fssv%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/formatters/ssv/ssv.c b/web/api/formatters/ssv/ssv.c new file mode 100644 index 0000000..eeba028 --- /dev/null +++ b/web/api/formatters/ssv/ssv.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ssv.h" + +void rrdr2ssv(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, const char *prefix, const char *separator, const char *suffix) { + //info("RRD2SSV(): %s: BEGIN", r->st->id); + long i; + + buffer_strcat(wb, prefix); + long start = 0, end = rrdr_rows(r), step = 1; + if(!(options & RRDR_OPTION_REVERSED)) { + start = rrdr_rows(r) - 1; + end = -1; + step = -1; + } + + // for each line in the array + for(i = start; i != end ;i += step) { + int all_values_are_null = 0; + calculated_number v = rrdr2value(r, i, options, &all_values_are_null); + + if(likely(i != start)) { + if(r->min > v) r->min = v; + if(r->max < v) r->max = v; + } + else { + r->min = v; + r->max = v; + } + + if(likely(i != start)) + buffer_strcat(wb, separator); + + if(all_values_are_null) { + if(options & RRDR_OPTION_NULL2ZERO) + buffer_strcat(wb, "0"); + else + buffer_strcat(wb, "null"); + } + else + buffer_rrd_value(wb, v); + } + buffer_strcat(wb, suffix); + //info("RRD2SSV(): %s: END", r->st->id); +} diff --git a/web/api/formatters/ssv/ssv.h b/web/api/formatters/ssv/ssv.h new file mode 100644 index 0000000..6963dcf --- /dev/null +++ b/web/api/formatters/ssv/ssv.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_SSV_H +#define NETDATA_API_FORMATTER_SSV_H + +#include "../rrd2json.h" + +extern void rrdr2ssv(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, const char *prefix, const char *separator, const char *suffix); + +#endif //NETDATA_API_FORMATTER_SSV_H diff --git a/web/api/formatters/value/Makefile.am b/web/api/formatters/value/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/formatters/value/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/formatters/value/README.md b/web/api/formatters/value/README.md new file mode 100644 index 0000000..50974de --- /dev/null +++ b/web/api/formatters/value/README.md @@ -0,0 +1,19 @@ +# Value formatter + +The Value formatter presents [results of database queries](../../queries) as a single value. + +To calculate the single value to be returned, it sums the values of all dimensions. + +The Value formatter respects the following API `&options=`: + +option|supported|description +:---:|:---:|:--- +`percent`|yes|to replace all values with their percentage over the row total +`abs`|yes|to turn all values positive, before using them +`min2max`|yes|to return the delta from the minimum value to the maximum value (across dimensions) + +The Value formatter is not exposed by the API by itself. +Instead it is used by the [`ssv`](../ssv) formatter +and [health monitoring queries](../../../../health). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fformatters%2Fvalue%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/formatters/value/value.c b/web/api/formatters/value/value.c new file mode 100644 index 0000000..aea6c16 --- /dev/null +++ b/web/api/formatters/value/value.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "value.h" + + +inline calculated_number rrdr2value(RRDR *r, long i, RRDR_OPTIONS options, int *all_values_are_null) { + rrdset_check_rdlock(r->st); + + long c; + RRDDIM *d; + + calculated_number *cn = &r->v[ i * r->d ]; + RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ]; + + calculated_number sum = 0, min = 0, max = 0, v; + int all_null = 1, init = 1; + + calculated_number total = 1; + int set_min_max = 0; + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + total = 0; + for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + calculated_number n = cn[c]; + + if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + total += n; + } + // prevent a division by zero + if(total == 0) total = 1; + set_min_max = 1; + } + + // for each dimension + for(c = 0, d = r->st->dimensions; d && c < r->d ;c++, d = d->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + calculated_number n = cn[c]; + + if(likely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) + n = -n; + + if(unlikely(options & RRDR_OPTION_PERCENTAGE)) { + n = n * 100 / total; + + if(unlikely(set_min_max)) { + r->min = r->max = n; + set_min_max = 0; + } + + if(n < r->min) r->min = n; + if(n > r->max) r->max = n; + } + + if(unlikely(init)) { + if(n > 0) { + min = 0; + max = n; + } + else { + min = n; + max = 0; + } + init = 0; + } + + if(likely(!(co[c] & RRDR_VALUE_EMPTY))) { + all_null = 0; + sum += n; + } + + if(n < min) min = n; + if(n > max) max = n; + } + + if(unlikely(all_null)) { + if(likely(all_values_are_null)) + *all_values_are_null = 1; + return 0; + } + else { + if(likely(all_values_are_null)) + *all_values_are_null = 0; + } + + if(options & RRDR_OPTION_MIN2MAX) + v = max - min; + else + v = sum; + + return v; +} diff --git a/web/api/formatters/value/value.h b/web/api/formatters/value/value.h new file mode 100644 index 0000000..d9e981f --- /dev/null +++ b/web/api/formatters/value/value.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_VALUE_H +#define NETDATA_API_FORMATTER_VALUE_H + +#include "../rrd2json.h" + +extern calculated_number rrdr2value(RRDR *r, long i, RRDR_OPTIONS options, int *all_values_are_null); + +#endif //NETDATA_API_FORMATTER_VALUE_H diff --git a/web/api/health/Makefile.am b/web/api/health/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/health/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/health/README.md b/web/api/health/README.md new file mode 100644 index 0000000..2003a61 --- /dev/null +++ b/web/api/health/README.md @@ -0,0 +1,163 @@ +# Health API Calls + +## Health Read API + +### Enabled Alarms + +NetData enables alarms on demand, i.e. when the chart they should be linked to starts collecting data. So, although many more alarms are configured, only the useful ones are enabled. + +To get the list of all enabled alarms: + +`http://your.netdata.ip:19999/api/v1/alarms?all` + +### Raised Alarms + +This API call will return the alarms currently in WARNING or CRITICAL state. + +`http://your.netdata.ip:19999/api/v1/alarms` + +### Event Log + +The size of the alarm log is configured in `netdata.conf`. There are 2 settings: the rotation of the alarm log file and the in memory size of the alarm log. + +``` +[health] + in memory max health log entries = 1000 + rotate log every lines = 2000 +``` + +The API call retrieves all entries of the alarm log: + +`http://your.netdata.ip:19999/api/v1/alarm_log` + +### Alarm Log Incremental Updates + +`http://your.netdata.ip:19999/api/v1/alarm_log?after=UNIQUEID` + +The above returns all the events in the alarm log that occurred after UNIQUEID (you poll it once without `after=`, remember the last UNIQUEID of the returned set, which you give back to get incrementally the next events). + +### Alarm badges + +The following will return an SVG badge of the alarm named `NAME`, attached to the chart named `CHART`. + +`http://your.netdata.ip:19999/api/v1/badge.svg?alarm=NAME&chart=CHART` + +## Health Management API + +Netdata v1.12 and beyond provides a command API to control health checks and notifications at runtime. The feature is especially useful for maintenance periods, during which you receive meaningless alarms. + +Specifically, the API allows you to: + - Disable health checks completely. Alarm conditions will not be evaluated at all and no entries will be added to the alarm log. + - Silence alarm notifications. Alarm conditions will be evaluated, the alarms will appear in the log and the netdata UI will show the alarms as active, but no notifications will be sent. + - Disable or Silence specific alarms that match selectors on alarm/template name, chart, context, host and family. + +The API is available by default, but it is protected by an `api authorization token` that is stored in the file you will see in the following entry of `http://localhost:19999/netdata.conf`: + +```bash +[registry] + # netdata management api key file = /var/lib/netdata/netdata.api.key +``` + +You can access the API via GET requests, by adding the bearer token to an `Authorization` http header, like this: + +``` +curl "http://myserver/api/v1/manage/health?cmd=RESET" -H "X-Auth-Token: Mytoken" +``` + +The command `RESET` just returns netdata to the default operation, with all health checks and notifications enabled. +If you've configured and entered your token correclty, you should see the plain text response `All health checks and notifications are enabled`. + +### Disable or silence all alarms + +If all you need is temporarily disable all health checks, then you issue the following before your maintenance period starts: +``` +curl "http://myserver/api/v1/manage/health?cmd=DISABLE ALL" -H "X-Auth-Token: Mytoken" +``` +The effect of disabling health checks is that the alarm criteria are not evaluated at all and nothing is written in the alarm log. +If you want the health checks to be running but to not receive any notifications during your maintenance period, you can instead use this: + +``` +curl "http://myserver/api/v1/manage/health?cmd=SILENCE ALL" -H "X-Auth-Token: Mytoken" +``` + +Alarms may then still be raised and logged in netdata, so you'll be able to see them via the UI. + +Regardless of the option you choose, at the end of your maintenance period you revert to the normal state via the RESET command. + +``` + curl "http://myserver/api/v1/manage/health?cmd=RESET" -H "X-Auth-Token: Mytoken" +``` + +### Disable or silence specific alarms + +If you do not wish to disable/silence all alarms, then the `DISABLE ALL` and `SILENCE ALL` commands can't be used. +Instead, the following commands expect that one or more alarm selectors will be added, so that only alarms that match the selectors are disabled or silenced. +- `DISABLE` : Set the mode to disable health checks. +- `SILENCE` : Set the mode to silence notifications. + +You will normally put one of these commands in the same request with your first alarm selector, but it's possible to issue them separately as well. +You will get a warning in the response, if a selector was added without a SILENCE/DISABLE command, or vice versa. + +Each request can specify a single alarm `selector`, with one or more `selection criteria`. +A single alarm will match a `selector` if all selection criteria match the alarm. +You can add as many selectors as you like. +In essence, the rule is: IF (alarm matches all the criteria in selector1 OR all the criteria in selector2 OR ...) THEN apply the DISABLE or SILENCE command. + +To clear all selectors and reset the mode to default, use the `RESET` command. + +The following example silences notifications for all the alarms with context=load: + +``` +curl "http://myserver/api/v1/manage/health?cmd=SILENCE&context=load" -H "X-Auth-Token: Mytoken" +``` + +#### Selection criteria + +The `selection criteria` are key/value pairs, in the format `key : value`, where value is a netdata [simple pattern](../../../libnetdata/simple_pattern/). This means that you can create very powerful selectors (you will rarely need more than one or two). + +The accepted keys for the `selection criteria` are the following: +- `alarm` : The expression provided will match both `alarm` and `template` names. +- `chart` : Chart ids/names, as shown on the dashboard. These will match the `on` entry of a configured `alarm`. +- `context` : Chart context, as shown on the dashboard. These will match the `on` entry of a configured `template`. +- `hosts` : The hostnames that will need to match. +- `families` : The alarm families. + +You can add any of the selection criteria you need on the request, to ensure that only the alarms you are interested in are matched and disabled/silenced. e.g. there is no reason to add `hosts: *`, if you want the criteria to be applied to alarms for all hosts. + +Example 1: Disable all health checks for context = `random` + +``` +http://localhost/api/v1/manage/health?cmd=DISABLE&context=random +``` + +Example 2: Silence all alarms and templates with name starting with `out_of` on host `myhost` + +``` +http://localhost/api/v1/manage/health?cmd=SILENCE&alarm=out_of*&hosts=myhost +``` + +Example 2.2: Add one more selector, to also silence alarms for cpu1 and cpu2 + +``` +http://localhost/api/v1/manage/health?families=cpu1 cpu2 +``` + +### Responses + +- "Auth Error" : Token authentication failed +- "All alarm notifications are silenced" : Successful response to cmd=SILENCE ALL +- "All health checks are disabled" : Successful response to cmd=DISABLE ALL +- "All health checks and notifications are enabled" : Successful response to cmd=RESET +- "Health checks disabled for alarms matching the selectors" : Added to the response for a cmd=DISABLE +- "Alarm notifications silenced for alarms matching the selectors" : Added to the response for a cmd=SILENCE +- "Alarm selector added" : Added to the response when a new selector is added +- "Invalid key. Ignoring it." : Wrong name of a parameter. Added to the response and ignored. +- "WARNING: Added alarm selector to silence/disable alarms without a SILENCE or DISABLE command." : Added to the response if a selector is added without a selector-specific command. +- "WARNING: SILENCE or DISABLE command is ineffective without defining any alarm selectors." : Added to the response if a selector-specific command is issued without a selector. + +### Further reading + +The test script under [tests/health_mgmtapi](../../../tests/health_mgmtapi) contains a series of tests that you can either run or read through to understand the various calls and responses better. + + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fhealth%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/health/health_cmdapi.c b/web/api/health/health_cmdapi.c new file mode 100644 index 0000000..ec17775 --- /dev/null +++ b/web/api/health/health_cmdapi.c @@ -0,0 +1,166 @@ +// +// Created by christopher on 11/12/18. +// + +#include "health_cmdapi.h" + + +static SILENCER *create_silencer(void) { + SILENCER *t = callocz(1, sizeof(SILENCER)); + debug(D_HEALTH, "HEALTH command API: Created empty silencer"); + + return t; +} + +void free_silencers(SILENCER *t) { + if (!t) return; + if (t->next) free_silencers(t->next); + debug(D_HEALTH, "HEALTH command API: Freeing silencer %s:%s:%s:%s:%s", t->alarms, + t->charts, t->contexts, t->hosts, t->families); + simple_pattern_free(t->alarms_pattern); + simple_pattern_free(t->charts_pattern); + simple_pattern_free(t->contexts_pattern); + simple_pattern_free(t->hosts_pattern); + simple_pattern_free(t->families_pattern); + freez(t->alarms); + freez(t->charts); + freez(t->contexts); + freez(t->hosts); + freez(t->families); + freez(t); + return; +} + + + +int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, char *url) { + int ret = 400; + (void) host; + + + + BUFFER *wb = w->response.data; + buffer_flush(wb); + wb->contenttype = CT_TEXT_PLAIN; + + buffer_flush(w->response.data); + + static uint32_t + hash_alarm = 0, + hash_template = 0, + hash_chart = 0, + hash_context = 0, + hash_host = 0, + hash_families = 0; + + if (unlikely(!hash_alarm)) { + hash_alarm = simple_uhash(HEALTH_ALARM_KEY); + hash_template = simple_uhash(HEALTH_TEMPLATE_KEY); + hash_chart = simple_uhash(HEALTH_CHART_KEY); + hash_context = simple_uhash(HEALTH_CONTEXT_KEY); + hash_host = simple_uhash(HEALTH_HOST_KEY); + hash_families = simple_uhash(HEALTH_FAMILIES_KEY); + } + + SILENCER *silencer = NULL; + + if (!w->auth_bearer_token) { + buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR); + ret = 403; + } else { + debug(D_HEALTH, "HEALTH command API: Comparing secret '%s' to '%s'", w->auth_bearer_token, api_secret); + if (strcmp(w->auth_bearer_token, api_secret)) { + buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR); + ret = 403; + } else { + while (url) { + char *value = mystrsep(&url, "&"); + if (!value || !*value) continue; + + char *key = mystrsep(&value, "="); + if (!key || !*key) continue; + if (!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 health query param '%s' with value '%s'", w->id, key, value); + + // name and value are now the parameters + if (!strcmp(key, "cmd")) { + if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCEALL)) { + silencers->all_alarms = 1; + silencers->stype = STYPE_SILENCE_NOTIFICATIONS; + buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCEALL); + } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLEALL)) { + silencers->all_alarms = 1; + silencers->stype = STYPE_DISABLE_ALARMS; + buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLEALL); + } else if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCE)) { + silencers->stype = STYPE_SILENCE_NOTIFICATIONS; + buffer_strcat(wb, HEALTH_CMDAPI_MSG_SILENCE); + } else if (!strcmp(value, HEALTH_CMDAPI_CMD_DISABLE)) { + silencers->stype = STYPE_DISABLE_ALARMS; + buffer_strcat(wb, HEALTH_CMDAPI_MSG_DISABLE); + } else if (!strcmp(value, HEALTH_CMDAPI_CMD_RESET)) { + silencers->all_alarms = 0; + silencers->stype = STYPE_NONE; + free_silencers(silencers->silencers); + silencers->silencers = NULL; + buffer_strcat(wb, HEALTH_CMDAPI_MSG_RESET); + } + } else { + uint32_t hash = simple_uhash(key); + if (unlikely(silencer == NULL)) { + if ( + (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) || + (hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) || + (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) || + (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) || + (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) || + (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) + ) { + silencer = create_silencer(); + } + } + + if (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) { + silencer->alarms = strdupz(value); + silencer->alarms_pattern = simple_pattern_create(silencer->alarms, NULL, SIMPLE_PATTERN_EXACT); + } else if (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) { + silencer->charts = strdupz(value); + silencer->charts_pattern = simple_pattern_create(silencer->charts, NULL, SIMPLE_PATTERN_EXACT); + } else if (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) { + silencer->contexts = strdupz(value); + silencer->contexts_pattern = simple_pattern_create(silencer->contexts, NULL, SIMPLE_PATTERN_EXACT); + } else if (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) { + silencer->hosts = strdupz(value); + silencer->hosts_pattern = simple_pattern_create(silencer->hosts, NULL, SIMPLE_PATTERN_EXACT); + } else if (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) { + silencer->families = strdupz(value); + silencer->families_pattern = simple_pattern_create(silencer->families, NULL, SIMPLE_PATTERN_EXACT); + } else { + buffer_strcat(wb, HEALTH_CMDAPI_MSG_INVALID_KEY); + } + } + + } + if (likely(silencer)) { + // Add the created instance to the linked list in silencers + silencer->next = silencers->silencers; + silencers->silencers = silencer; + debug(D_HEALTH, "HEALTH command API: Added silencer %s:%s:%s:%s:%s", silencer->alarms, + silencer->charts, silencer->contexts, silencer->hosts, silencer->families + ); + buffer_strcat(wb, HEALTH_CMDAPI_MSG_ADDED); + if (silencers->stype == STYPE_NONE) { + buffer_strcat(wb, HEALTH_CMDAPI_MSG_STYPEWARNING); + } + } + if (unlikely(silencers->stype != STYPE_NONE && !silencers->all_alarms && !silencers->silencers)) { + buffer_strcat(wb, HEALTH_CMDAPI_MSG_NOSELECTORWARNING); + } + ret = 200; + } + } + w->response.data = wb; + buffer_no_cacheable(w->response.data); + return ret; +} diff --git a/web/api/health/health_cmdapi.h b/web/api/health/health_cmdapi.h new file mode 100644 index 0000000..d0f3040 --- /dev/null +++ b/web/api/health/health_cmdapi.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_HEALTH_SVG_H +#define NETDATA_WEB_HEALTH_SVG_H 1 + +#include "libnetdata/libnetdata.h" +#include "web/server/web_client.h" +#include "health/health.h" + +#define HEALTH_CMDAPI_CMD_SILENCEALL "SILENCE ALL" +#define HEALTH_CMDAPI_CMD_DISABLEALL "DISABLE ALL" +#define HEALTH_CMDAPI_CMD_SILENCE "SILENCE" +#define HEALTH_CMDAPI_CMD_DISABLE "DISABLE" +#define HEALTH_CMDAPI_CMD_RESET "RESET" + +#define HEALTH_CMDAPI_MSG_AUTHERROR "Auth Error\n" +#define HEALTH_CMDAPI_MSG_SILENCEALL "All alarm notifications are silenced\n" +#define HEALTH_CMDAPI_MSG_DISABLEALL "All health checks are disabled\n" +#define HEALTH_CMDAPI_MSG_RESET "All health checks and notifications are enabled\n" +#define HEALTH_CMDAPI_MSG_DISABLE "Health checks disabled for alarms matching the selectors\n" +#define HEALTH_CMDAPI_MSG_SILENCE "Alarm notifications silenced for alarms matching the selectors\n" +#define HEALTH_CMDAPI_MSG_ADDED "Alarm selector added\n" +#define HEALTH_CMDAPI_MSG_INVALID_KEY "Invalid key. Ignoring it.\n" +#define HEALTH_CMDAPI_MSG_STYPEWARNING "WARNING: Added alarm selector to silence/disable alarms without a SILENCE or DISABLE command.\n" +#define HEALTH_CMDAPI_MSG_NOSELECTORWARNING "WARNING: SILENCE or DISABLE command is ineffective without defining any alarm selectors.\n" + +extern int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, char *url); + +#include "web/api/web_api_v1.h" + +#endif /* NETDATA_WEB_HEALTH_SVG_H */ diff --git a/web/api/netdata-swagger.json b/web/api/netdata-swagger.json new file mode 100644 index 0000000..ac84b75 --- /dev/null +++ b/web/api/netdata-swagger.json @@ -0,0 +1,1230 @@ +{ + "swagger": "2.0", + "info": { + "title": "NetData API", + "description": "Real-time performance and health monitoring.", + "version": "1.11.1_rolling" + }, + "host": "registry.my-netdata.io", + "schemes": [ + "https", + "http" + ], + "basePath": "/api/v1", + "produces": [ + "application/json" + ], + "paths": { + "/info": { + "get": { + "summary": "Get netdata basic information", + "description": "The info endpoint returns basic information about netdata. It provides:\n* netdata version\n* netdata unique id\n* list of hosts mirrored (includes itself)\n* number of alarms in the host\n * number of alarms in normal state\n * number of alarms in warning state\n * number of alarms in critical state\n", + "responses": { + "200": { + "description": "netdata basic information", + "schema": { + "$ref": "#/definitions/info" + } + } + } + } + }, + "/charts": { + "get": { + "summary": "Get a list of all charts available at the server", + "description": "The charts endpoint returns a summary about all charts stored in the netdata server.", + "responses": { + "200": { + "description": "An array of charts", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/chart_summary" + } + } + } + } + } + }, + "/chart": { + "get": { + "summary": "Get info about a specific chart", + "description": "The Chart endpoint returns detailed information about a chart.", + "parameters": [ + { + "name": "chart", + "in": "query", + "description": "The id of the chart as returned by the /charts call.", + "required": true, + "type": "string", + "format": "as returned by /charts", + "default": "system.cpu" + } + ], + "responses": { + "200": { + "description": "A javascript object with detailed information about the chart.", + "schema": { + "$ref": "#/definitions/chart" + } + }, + "404": { + "description": "No chart with the given id is found." + } + } + } + }, + "/data": { + "get": { + "summary": "Get collected data for a specific chart", + "description": "The Data endpoint returns data stored in the round robin database of a chart.\n", + "parameters": [ + { + "name": "chart", + "in": "query", + "description": "The id of the chart as returned by the /charts call.", + "required": true, + "type": "string", + "format": "as returned by /charts", + "allowEmptyValue": false, + "default": "system.cpu" + }, + { + "name": "dimension", + "in": "query", + "description": "zero, one or more dimension ids or names, as returned by the /chart call, separated with comma or pipe. Netdata simple patterns are supported.", + "required": false, + "type": "array", + "items": { + "type": "string", + "collectionFormat": "pipes", + "format": "as returned by /charts" + }, + "allowEmptyValue": false + }, + { + "name": "after", + "in": "query", + "description": "This parameter can either be an absolute timestamp specifying the starting point of the data to be returned, or a relative number of seconds (negative, relative to parameter: before). Netdata will assume it is a relative number if it is less that 3 years (in seconds). Netdata will adapt this parameter to the boundaries of the round robin database. The default is the beginning of the round robin database (i.e. by default netdata will attempt to return data for the entire database).", + "required": true, + "type": "number", + "format": "integer", + "allowEmptyValue": false, + "default": -600 + }, + { + "name": "before", + "in": "query", + "description": "This parameter can either be an absolute timestamp specifying the ending point of the data to be returned, or a relative number of seconds (negative), relative to the last collected timestamp. Netdata will assume it is a relative number if it is less than 3 years (in seconds). Netdata will adapt this parameter to the boundaries of the round robin database. The default is zero (i.e. the timestamp of the last value collected).", + "required": false, + "type": "number", + "format": "integer", + "default": 0 + }, + { + "name": "points", + "in": "query", + "description": "The number of points to be returned. If not given, or it is <= 0, or it is bigger than the points stored in the round robin database for this chart for the given duration, all the available collected values for the given duration will be returned.", + "required": true, + "type": "number", + "format": "integer", + "allowEmptyValue": false, + "default": 20 + }, + { + "name": "group", + "in": "query", + "description": "The grouping method. If multiple collected values are to be grouped in order to return fewer points, this parameters defines the method of grouping. methods supported \"min\", \"max\", \"average\", \"sum\", \"incremental-sum\". \"max\" is actually calculated on the absolute value collected (so it works for both positive and negative dimesions to return the most extreme value in either direction).", + "required": true, + "type": "string", + "enum": [ + "min", + "max", + "average", + "median", + "stddev", + "sum", + "incremental-sum" + ], + "default": "average", + "allowEmptyValue": false + }, + { + "name": "gtime", + "in": "query", + "description": "The grouping number of seconds. This is used in conjunction with group=average to change the units of metrics (ie when the data is per-second, setting gtime=60 will turn them to per-minute).", + "required": false, + "type": "number", + "format": "integer", + "allowEmptyValue": false, + "default": 0 + }, + { + "name": "format", + "in": "query", + "description": "The format of the data to be returned.", + "required": true, + "type": "string", + "enum": [ + "json", + "jsonp", + "csv", + "tsv", + "tsv-excel", + "ssv", + "ssvcomma", + "datatable", + "datasource", + "html", + "markdown", + "array", + "csvjsonarray" + ], + "default": "json", + "allowEmptyValue": false + }, + { + "name": "options", + "in": "query", + "description": "Options that affect data generation.", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "nonzero", + "flip", + "jsonwrap", + "min2max", + "seconds", + "milliseconds", + "abs", + "absolute", + "absolute-sum", + "null2zero", + "objectrows", + "google_json", + "percentage", + "unaligned", + "match-ids", + "match-names" + ], + "collectionFormat": "pipes" + }, + "default": [ + "seconds", + "jsonwrap" + ], + "allowEmptyValue": false + }, + { + "name": "callback", + "in": "query", + "description": "For JSONP responses, the callback function name.", + "required": false, + "type": "string", + "allowEmptyValue": true + }, + { + "name": "filename", + "in": "query", + "description": "Add Content-Disposition: attachment; filename=<filename> header to the response, that will instruct the browser to save the response with the given filename.", + "required": false, + "type": "string", + "allowEmptyValue": true + }, + { + "name": "tqx", + "in": "query", + "description": "[Google Visualization API](https://developers.google.com/chart/interactive/docs/dev/implementing_data_source?hl=en) formatted parameter.", + "required": false, + "type": "string", + "allowEmptyValue": true + } + ], + "responses": { + "200": { + "description": "The call was successful. The response should include the data.", + "schema": { + "$ref": "#/definitions/chart" + } + }, + "400": { + "description": "Bad request - the body will include a message stating what is wrong." + }, + "404": { + "description": "No chart with the given id is found." + }, + "500": { + "description": "Internal server error. This usually means the server is out of memory." + } + } + } + }, + "/badge.svg": { + "get": { + "summary": "Generate a SVG image for a chart (or dimension)", + "description": "Successful responses are SVG images\n", + "parameters": [ + { + "name": "chart", + "in": "query", + "description": "The id of the chart as returned by the /charts call.", + "required": true, + "type": "string", + "format": "as returned by /charts", + "allowEmptyValue": false, + "default": "system.cpu" + }, + { + "name": "alarm", + "in": "query", + "description": "the name of an alarm linked to the chart", + "required": false, + "type": "string", + "format": "any text", + "allowEmptyValue": true + }, + { + "name": "dimension", + "in": "query", + "description": "zero, one or more dimension ids, as returned by the /chart call.", + "required": false, + "type": "array", + "items": { + "type": "string", + "collectionFormat": "pipes", + "format": "as returned by /charts" + }, + "allowEmptyValue": false + }, + { + "name": "after", + "in": "query", + "description": "This parameter can either be an absolute timestamp specifying the starting point of the data to be returned, or a relative number of seconds, to the last collected timestamp. Netdata will assume it is a relative number if it is smaller than the duration of the round robin database for this chart. So, if the round robin database is 3600 seconds, any value from -3600 to 3600 will trigger relative arithmetics. Netdata will adapt this parameter to the boundaries of the round robin database.", + "required": true, + "type": "number", + "format": "integer", + "allowEmptyValue": false, + "default": -600 + }, + { + "name": "before", + "in": "query", + "description": "This parameter can either be an absolute timestamp specifying the ending point of the data to be returned, or a relative number of seconds, to the last collected timestamp. Netdata will assume it is a relative number if it is smaller than the duration of the round robin database for this chart. So, if the round robin database is 3600 seconds, any value from -3600 to 3600 will trigger relative arithmetics. Netdata will adapt this parameter to the boundaries of the round robin database.", + "required": false, + "type": "number", + "format": "integer", + "default": 0 + }, + { + "name": "group", + "in": "query", + "description": "The grouping method. If multiple collected values are to be grouped in order to return fewer points, this parameters defines the method of grouping. methods are supported \"min\", \"max\", \"average\", \"sum\", \"incremental-sum\". \"max\" is actually calculated on the absolute value collected (so it works for both positive and negative dimesions to return the most extreme value in either direction).", + "required": true, + "type": "string", + "enum": [ + "min", + "max", + "average", + "median", + "stddev", + "sum", + "incremental-sum" + ], + "default": "average", + "allowEmptyValue": false + }, + { + "name": "options", + "in": "query", + "description": "Options that affect data generation.", + "required": false, + "type": "array", + "items": { + "type": "string", + "enum": [ + "abs", + "absolute", + "display-absolute", + "absolute-sum", + "null2zero", + "percentage", + "unaligned" + ], + "collectionFormat": "pipes" + }, + "default": [ + "absolute" + ], + "allowEmptyValue": true + }, + { + "name": "label", + "in": "query", + "description": "a text to be used as the label", + "required": false, + "type": "string", + "format": "any text", + "allowEmptyValue": true + }, + { + "name": "units", + "in": "query", + "description": "a text to be used as the units", + "required": false, + "type": "string", + "format": "any text", + "allowEmptyValue": true + }, + { + "name": "label_color", + "in": "query", + "description": "a color to be used for the background of the label", + "required": false, + "type": "string", + "format": "any text", + "allowEmptyValue": true + }, + { + "name": "value_color", + "in": "query", + "description": "a color to be used for the background of the label. You can set multiple using a pipe with a condition each, like this: color<value|color>value|color:null The following operators are supported: >, <, >=, <=, =, :null (to check if no value exists).", + "required": false, + "type": "string", + "format": "any text", + "allowEmptyValue": true + }, + { + "name": "multiply", + "in": "query", + "description": "multiply the value with this number for rendering it at the image (integer value required)", + "required": false, + "type": "number", + "format": "integer", + "allowEmptyValue": true + }, + { + "name": "divide", + "in": "query", + "description": "divide the value with this number for rendering it at the image (integer value required)", + "required": false, + "type": "number", + "format": "integer", + "allowEmptyValue": true + }, + { + "name": "scale", + "in": "query", + "description": "set the scale of the badge (greater or equal to 100)", + "required": false, + "type": "number", + "format": "integer", + "allowEmptyValue": true + } + ], + "responses": { + "200": { + "description": "The call was successful. The response should be an SVG image." + }, + "400": { + "description": "Bad request - the body will include a message stating what is wrong." + }, + "404": { + "description": "No chart with the given id is found." + }, + "500": { + "description": "Internal server error. This usually means the server is out of memory." + } + } + } + }, + "/allmetrics": { + "get": { + "summary": "Get a value of all the metrics maintained by netdata", + "description": "The charts endpoint returns the latest value of all charts and dimensions stored in the netdata server.", + "parameters": [ + { + "name": "format", + "in": "query", + "description": "The format of the response to be returned", + "required": true, + "type": "string", + "enum": [ + "shell", + "prometheus", + "prometheus_all_hosts", + "json" + ], + "default": "shell" + }, + { + "name": "help", + "in": "query", + "description": "enable or disable HELP lines in prometheus output", + "required": false, + "type": "string", + "enum": [ + "yes", + "no" + ], + "default": "no" + }, + { + "name": "types", + "in": "query", + "description": "enable or disable TYPE lines in prometheus output", + "required": false, + "type": "string", + "enum": [ + "yes", + "no" + ], + "default": "no" + }, + { + "name": "timestamps", + "in": "query", + "description": "enable or disable timestamps in prometheus output", + "required": false, + "type": "string", + "enum": [ + "yes", + "no" + ], + "default": "yes" + }, + { + "name": "names", + "in": "query", + "description": "When enabled netdata will report dimension names. When disabled netdata will report dimension IDs. The default is controlled in netdata.conf.", + "required": false, + "type": "string", + "enum": [ + "yes", + "no" + ], + "default": "yes" + }, + { + "name": "server", + "in": "query", + "description": "Set a distinct name of the client querying prometheus metrics. Netdata will use the client IP if this is not set.", + "required": false, + "type": "string", + "format": "any text" + }, + { + "name": "prefix", + "in": "query", + "description": "Prefix all prometheus metrics with this string.", + "required": false, + "type": "string", + "format": "any text" + }, + { + "name": "data", + "in": "query", + "description": "Select the prometheus response data source. The default is controlled in netdata.conf", + "required": false, + "type": "string", + "enum": [ + "as-collected", + "average", + "sum" + ], + "default": "average" + } + ], + "responses": { + "200": { + "description": "All the metrics returned in the format requested" + }, + "400": { + "description": "The format requested is not supported" + } + } + } + }, + "/alarms": { + "get": { + "summary": "Get a list of active or raised alarms on the server", + "description": "The alarms endpoint returns the list of all raised or enabled alarms on the netdata server. Called without any parameters, the raised alarms in state WARNING or CRITICAL are returned. By passing \"?all\", all the enabled alarms are returned.", + "parameters": [ + { + "name": "all", + "in": "query", + "description": "If passed, all enabled alarms are returned", + "required": false, + "type": "boolean", + "allowEmptyValue": true + } + ], + "responses": { + "200": { + "description": "An object containing general info and a linked list of alarms", + "schema": { + "$ref": "#/definitions/alarms" + } + } + } + } + }, + "/alarm_log": { + "get": { + "summary": "Retrieves the entries of the alarm log", + "description": "Returns an array of alarm_log entries, with historical information on raised and cleared alarms.", + "parameters": [ + { + "name": "after", + "in": "query", + "description": "Passing the parameter after=UNIQUEID returns all the events in the alarm log that occurred after UNIQUEID. An automated series of calls would call the interface once without after=, store the last UNIQUEID of the returned set, and give it back to get incrementally the next events", + "required": false, + "type": "integer" + } + ], + "responses": { + "200": { + "description": "An array of alarm log entries", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/alarm_log_entry" + } + } + } + } + } + }, + "/manage/health": { + "get": { + "summary": "Accesses the health management API to control health checks and notifications at runtime.", + "description": "Available from Netdata v1.12 and above, protected via bearer authorization. Especially useful for maintenance periods, the API allows you to disable health checks completely, silence alarm notifications, or Disable/Silence specific alarms that match selectors on alarm/template name, chart, context, host and family. For the simple disable/silence all scenaria, only the cmd parameter is required. The other parameters are used to define alarm selectors. For more information and examples, refer to the netdata documentation.", + "parameters": [ + { + "name": "cmd", + "in": "query", + "description": "DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors.", + "required": false, + "type": "string", + "enum": [ + "DISABLE ALL", + "SILENCE ALL", + "DISABLE", + "SILENCE", + "RESET" + ] + }, + { + "name": "alarm", + "in": "query", + "description": "The expression provided will match both `alarm` and `template` names.", + "type": "string" + }, + { + "name": "chart", + "in": "query", + "description": "Chart ids/names, as shown on the dashboard. These will match the `on` entry of a configured `alarm`", + "type": "string" + }, + { + "name": "context", + "in": "query", + "description": "Chart context, as shown on the dashboard. These will match the `on` entry of a configured `template`.", + "type": "string" + }, + { + "name": "hosts", + "in": "query", + "description": "The hostnames that will need to match.", + "type": "string" + }, + { + "name": "families", + "in": "query", + "description": "The alarm families.", + "type": "string" + } + ], + "responses": { + "200": { + "description": "A plain text response based on the result of the command" + }, + "403": { + "description": "Bearer authentication error." + } + } + } + } + }, + "definitions": { + "info": { + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "netdata version of the server.", + "example": "1.11.1_rolling" + }, + "uid": { + "type": "string", + "description": "netdata unique id of the server.", + "example": "24e9fe3c-f2ac-11e8-bafc-0242ac110002" + }, + "mirrored_hosts": { + "type": "array", + "description": "list of hosts mirrored of the server (include itself).", + "items": { + "type": "string" + }, + "example": [ + "host1.example.com", + "host2.example.com" + ] + }, + "alarms": { + "type": "object", + "description": "number of alarms in the server.", + "properties": { + "normal": { + "type": "integer", + "description": "number of alarms in normal state." + }, + "warning": { + "type": "integer", + "description": "number of alarms in warning state." + }, + "critical": { + "type": "integer", + "description": "number of alarms in critical state." + } + } + } + } + }, + "chart_summary": { + "type": "object", + "properties": { + "hostname": { + "type": "string", + "description": "The hostname of the netdata server." + }, + "version": { + "type": "string", + "description": "netdata version of the server." + }, + "os": { + "type": "string", + "description": "The netdata server host operating system.", + "enum": [ + "macos", + "linux", + "freebsd" + ] + }, + "history": { + "type": "number", + "description": "The duration, in seconds, of the round robin database maintained by netdata." + }, + "update_every": { + "type": "number", + "description": "The default update frequency of the netdata server. All charts have an update frequency equal or bigger than this." + }, + "charts": { + "type": "object", + "description": "An object containing all the chart objects available at the netdata server. This is used as an indexed array. The key of each chart object is the id of the chart.", + "properties": { + "key": { + "$ref": "#/definitions/chart" + } + } + }, + "charts_count": { + "type": "number", + "description": "The number of charts." + }, + "dimensions_count": { + "type": "number", + "description": "The total number of dimensions." + }, + "alarms_count": { + "type": "number", + "description": "The number of alarms." + }, + "rrd_memory_bytes": { + "type": "number", + "description": "The size of the round robin database in bytes." + } + } + }, + "chart": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The unique id of the chart" + }, + "name": { + "type": "string", + "description": "The name of the chart" + }, + "type": { + "type": "string", + "description": "The type of the chart. Types are not handled by netdata. You can use this field for anything you like." + }, + "family": { + "type": "string", + "description": "The family of the chart. Families are not handled by netdata. You can use this field for anything you like." + }, + "title": { + "type": "string", + "description": "The title of the chart." + }, + "priority": { + "type": "string", + "description": "The relative priority of the chart. NetData does not care about priorities. This is just an indication of importance for the chart viewers to sort charts of higher priority (lower number) closer to the top. Priority sorting should only be used among charts of the same type or family." + }, + "enabled": { + "type": "boolean", + "description": "True when the chart is enabled. Disabled charts do not currently collect values, but they may have historical values available." + }, + "units": { + "type": "string", + "description": "The unit of measurement for the values of all dimensions of the chart." + }, + "data_url": { + "type": "string", + "description": "The absolute path to get data values for this chart. You are expected to use this path as the base when constructing the URL to fetch data values for this chart." + }, + "chart_type": { + "type": "string", + "description": "The chart type.", + "enum": [ + "line", + "area", + "stacked" + ] + }, + "duration": { + "type": "number", + "description": "The duration, in seconds, of the round robin database maintained by netdata." + }, + "first_entry": { + "type": "number", + "description": "The UNIX timestamp of the first entry (the oldest) in the round robin database." + }, + "last_entry": { + "type": "number", + "description": "The UNIX timestamp of the latest entry in the round robin database." + }, + "update_every": { + "type": "number", + "description": "The update frequency of this chart, in seconds. One value every this amount of time is kept in the round robin database." + }, + "dimensions": { + "type": "object", + "description": "An object containing all the chart dimensions available for the chart. This is used as an indexed array. The key of the object the id of the dimension.", + "properties": { + "key": { + "$ref": "#/definitions/dimension" + } + } + }, + "green": { + "type": "number", + "description": "Chart health green threshold" + }, + "red": { + "type": "number", + "description": "Chart health red trheshold" + } + } + }, + "dimension": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The name of the dimension" + } + } + }, + "json_wrap": { + "type": "object", + "properties": { + "api": { + "type": "number", + "description": "The API version this conforms to, currently 1" + }, + "id": { + "type": "string", + "description": "The unique id of the chart" + }, + "name": { + "type": "string", + "description": "The name of the chart" + }, + "update_every": { + "type": "number", + "description": "The update frequency of this chart, in seconds. One value every this amount of time is kept in the round robin database (indepedently of the current view)." + }, + "view_update_every": { + "type": "number", + "description": "The current view appropriate update frequency of this chart, in seconds. There is no point to request chart refreshes, using the same settings, more frequently than this." + }, + "first_entry": { + "type": "number", + "description": "The UNIX timestamp of the first entry (the oldest) in the round robin database (indepedently of the current view)." + }, + "last_entry": { + "type": "number", + "description": "The UNIX timestamp of the latest entry in the round robin database (indepedently of the current view)." + }, + "after": { + "type": "number", + "description": "The UNIX timestamp of the first entry (the oldest) returned in this response." + }, + "before": { + "type": "number", + "description": "The UNIX timestamp of the latest entry returned in this response." + }, + "min": { + "type": "number", + "description": "The minimum value returned in the current view. This can be used to size the y-series of the chart." + }, + "max": { + "type": "number", + "description": "The maximum value returned in the current view. This can be used to size the y-series of the chart." + }, + "dimension_names": { + "description": "The dimension names of the chart as returned in the current view.", + "type": "array", + "items": { + "type": "string" + } + }, + "dimension_ids": { + "description": "The dimension IDs of the chart as returned in the current view.", + "type": "array", + "items": { + "type": "string" + } + }, + "latest_values": { + "description": "The latest values collected for the chart (indepedently of the current view).", + "type": "array", + "items": { + "type": "string" + } + }, + "view_latest_values": { + "description": "The latest values returned with this response.", + "type": "array", + "items": { + "type": "string" + } + }, + "dimensions": { + "type": "number", + "description": "The number of dimensions returned." + }, + "points": { + "type": "number", + "description": "The number of rows / points returned." + }, + "format": { + "type": "string", + "description": "The format of the result returned." + }, + "result": { + "description": "The result requested, in the format requested." + } + } + }, + "alarms": { + "type": "object", + "properties": { + "hostname": { + "type": "string" + }, + "latest_alarm_log_unique_id": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "boolean" + }, + "now": { + "type": "integer", + "format": "int32" + }, + "alarms": { + "type": "object", + "properties": { + "chart-name.alarm-name": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string", + "description": "Full alarm name" + }, + "chart": { + "type": "string" + }, + "family": { + "type": "string" + }, + "active": { + "type": "boolean", + "description": "Will be false only if the alarm is disabled in the configuration" + }, + "disabled": { + "type": "boolean", + "description": "Whether the health check for this alarm has been disabled via a health command API DISABLE command." + }, + "silenced": { + "type": "boolean", + "description": "Whether notifications for this alarm have been silenced via a health command API SILENCE command." + }, + "exec": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "source": { + "type": "string" + }, + "units": { + "type": "string" + }, + "info": { + "type": "string" + }, + "status": { + "type": "string" + }, + "last_status_change": { + "type": "integer", + "format": "int32" + }, + "last_updated": { + "type": "integer", + "format": "int32" + }, + "next_update": { + "type": "integer", + "format": "int32" + }, + "update_every": { + "type": "integer", + "format": "int32" + }, + "delay_up_duration": { + "type": "integer", + "format": "int32" + }, + "delay_down_duration": { + "type": "integer", + "format": "int32" + }, + "delay_max_duration": { + "type": "integer", + "format": "int32" + }, + "delay_multiplier": { + "type": "integer", + "format": "int32" + }, + "delay": { + "type": "integer", + "format": "int32" + }, + "delay_up_to_timestamp": { + "type": "integer", + "format": "int32" + }, + "value_string": { + "type": "string" + }, + "no_clear_notification": { + "type": "boolean" + }, + "lookup_dimensions": { + "type": "string" + }, + "db_after": { + "type": "integer", + "format": "int32" + }, + "db_before": { + "type": "integer", + "format": "int32" + }, + "lookup_method": { + "type": "string" + }, + "lookup_after": { + "type": "integer", + "format": "int32" + }, + "lookup_before": { + "type": "integer", + "format": "int32" + }, + "lookup_options": { + "type": "string" + }, + "calc": { + "type": "string" + }, + "calc_parsed": { + "type": "string" + }, + "warn": { + "type": "string" + }, + "warn_parsed": { + "type": "string" + }, + "crit": { + "type": "string" + }, + "crit_parsed": { + "type": "string" + }, + "green": { + "type": "string", + "format": "nullable" + }, + "red": { + "type": "string", + "format": "nullable" + }, + "value": { + "type": "number" + } + } + } + } + } + } + }, + "alarm_log_entry": { + "type": "object", + "properties": { + "hostname": { + "type": "string" + }, + "unique_id": { + "type": "integer", + "format": "int32" + }, + "alarm_id": { + "type": "integer", + "format": "int32" + }, + "alarm_event_id": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + }, + "chart": { + "type": "string" + }, + "family": { + "type": "string" + }, + "processed": { + "type": "boolean" + }, + "updated": { + "type": "boolean" + }, + "exec_run": { + "type": "integer", + "format": "int32" + }, + "exec_failed": { + "type": "boolean" + }, + "exec": { + "type": "string" + }, + "recipient": { + "type": "string" + }, + "exec_code": { + "type": "integer", + "format": "int32" + }, + "source": { + "type": "string" + }, + "units": { + "type": "string" + }, + "when": { + "type": "integer", + "format": "int32" + }, + "duration": { + "type": "integer", + "format": "int32" + }, + "non_clear_duration": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "string" + }, + "old_status": { + "type": "string" + }, + "delay": { + "type": "integer", + "format": "int32" + }, + "delay_up_to_timestamp": { + "type": "integer", + "format": "int32" + }, + "updated_by_id": { + "type": "integer", + "format": "int32" + }, + "updates_id": { + "type": "integer", + "format": "int32" + }, + "value_string": { + "type": "string" + }, + "old_value_string": { + "type": "string" + }, + "silenced": { + "type": "string" + }, + "info": { + "type": "string" + }, + "value": { + "type": "string", + "format": "nullable" + }, + "old_value": { + "type": "string", + "format": "nullable" + } + } + } + } +}
\ No newline at end of file diff --git a/web/api/netdata-swagger.yaml b/web/api/netdata-swagger.yaml new file mode 100644 index 0000000..bf62fb9 --- /dev/null +++ b/web/api/netdata-swagger.yaml @@ -0,0 +1,830 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +swagger: '2.0' +info: + title: NetData API + description: 'Real-time performance and health monitoring.' + version: 1.11.1_rolling +host: registry.my-netdata.io +schemes: + - https + - http +basePath: /api/v1 +produces: + - application/json +paths: + /info: + get: + summary: Get netdata basic information + description: | + The info endpoint returns basic information about netdata. It provides: + * netdata version + * netdata unique id + * list of hosts mirrored (includes itself) + * number of alarms in the host + * number of alarms in normal state + * number of alarms in warning state + * number of alarms in critical state + responses: + '200': + description: netdata basic information + schema: + $ref: '#/definitions/info' + /charts: + get: + summary: 'Get a list of all charts available at the server' + description: 'The charts endpoint returns a summary about all charts stored in the netdata server.' + responses: + '200': + description: 'An array of charts' + schema: + type: array + items: + $ref: '#/definitions/chart_summary' + /chart: + get: + summary: 'Get info about a specific chart' + description: 'The Chart endpoint returns detailed information about a chart.' + parameters: + - name: chart + in: query + description: 'The id of the chart as returned by the /charts call.' + required: true + type: string + format: 'as returned by /charts' + default: 'system.cpu' + responses: + '200': + description: 'A javascript object with detailed information about the chart.' + schema: + $ref: '#/definitions/chart' + '404': + description: 'No chart with the given id is found.' + /data: + get: + summary: 'Get collected data for a specific chart' + description: | + The Data endpoint returns data stored in the round robin database of a chart. + parameters: + - name: chart + in: query + description: 'The id of the chart as returned by the /charts call.' + required: true + type: string + format: 'as returned by /charts' + allowEmptyValue: false + default: system.cpu + - name: dimension + in: query + description: 'zero, one or more dimension ids or names, as returned by the /chart call, separated with comma or pipe. Netdata simple patterns are supported.' + required: false + type: array + items: + type: string + collectionFormat: pipes + format: 'as returned by /charts' + allowEmptyValue: false + - name: after + in: query + description: 'This parameter can either be an absolute timestamp specifying the starting point of the data to be returned, or a relative number of seconds (negative, relative to parameter: before). Netdata will assume it is a relative number if it is less that 3 years (in seconds). Netdata will adapt this parameter to the boundaries of the round robin database. The default is the beginning of the round robin database (i.e. by default netdata will attempt to return data for the entire database).' + required: true + type: number + format: integer + allowEmptyValue: false + default: -600 + - name: before + in: query + description: 'This parameter can either be an absolute timestamp specifying the ending point of the data to be returned, or a relative number of seconds (negative), relative to the last collected timestamp. Netdata will assume it is a relative number if it is less than 3 years (in seconds). Netdata will adapt this parameter to the boundaries of the round robin database. The default is zero (i.e. the timestamp of the last value collected).' + required: false + type: number + format: integer + default: 0 + - name: points + in: query + description: 'The number of points to be returned. If not given, or it is <= 0, or it is bigger than the points stored in the round robin database for this chart for the given duration, all the available collected values for the given duration will be returned.' + required: true + type: number + format: integer + allowEmptyValue: false + default: 20 + - name: group + in: query + description: 'The grouping method. If multiple collected values are to be grouped in order to return fewer points, this parameters defines the method of grouping. methods supported "min", "max", "average", "sum", "incremental-sum". "max" is actually calculated on the absolute value collected (so it works for both positive and negative dimesions to return the most extreme value in either direction).' + required: true + type: string + enum: [ 'min', 'max', 'average', 'median', 'stddev', 'sum', 'incremental-sum' ] + default: 'average' + allowEmptyValue: false + - name: gtime + in: query + description: 'The grouping number of seconds. This is used in conjunction with group=average to change the units of metrics (ie when the data is per-second, setting gtime=60 will turn them to per-minute).' + required: false + type: number + format: integer + allowEmptyValue: false + default: 0 + - name: format + in: query + description: 'The format of the data to be returned.' + required: true + type: string + enum: [ 'json', 'jsonp', 'csv', 'tsv', 'tsv-excel', 'ssv', 'ssvcomma', 'datatable', 'datasource', 'html', 'markdown', 'array', 'csvjsonarray' ] + default: json + allowEmptyValue: false + - name: options + in: query + description: 'Options that affect data generation.' + required: false + type: array + items: + type: string + enum: [ 'nonzero', 'flip', 'jsonwrap', 'min2max', 'seconds', 'milliseconds', 'abs', 'absolute', 'absolute-sum', 'null2zero', 'objectrows', 'google_json', 'percentage', 'unaligned', 'match-ids', 'match-names' ] + collectionFormat: pipes + default: [seconds, jsonwrap] + allowEmptyValue: false + - name: callback + in: query + description: 'For JSONP responses, the callback function name.' + required: false + type: string + allowEmptyValue: true + - name: filename + in: query + description: 'Add Content-Disposition: attachment; filename=<filename> header to the response, that will instruct the browser to save the response with the given filename.' + required: false + type: string + allowEmptyValue: true + - name: tqx + in: query + description: '[Google Visualization API](https://developers.google.com/chart/interactive/docs/dev/implementing_data_source?hl=en) formatted parameter.' + required: false + type: string + allowEmptyValue: true + responses: + '200': + description: 'The call was successful. The response should include the data.' + schema: + $ref: '#/definitions/chart' + '400': + description: 'Bad request - the body will include a message stating what is wrong.' + '404': + description: 'No chart with the given id is found.' + '500': + description: 'Internal server error. This usually means the server is out of memory.' + /badge.svg: + get: + summary: 'Generate a SVG image for a chart (or dimension)' + description: | + Successful responses are SVG images + parameters: + - name: chart + in: query + description: 'The id of the chart as returned by the /charts call.' + required: true + type: string + format: 'as returned by /charts' + allowEmptyValue: false + default: system.cpu + - name: alarm + in: query + description: 'the name of an alarm linked to the chart' + required: false + type: string + format: 'any text' + allowEmptyValue: true + - name: dimension + in: query + description: 'zero, one or more dimension ids, as returned by the /chart call.' + required: false + type: array + items: + type: string + collectionFormat: pipes + format: 'as returned by /charts' + allowEmptyValue: false + - name: after + in: query + description: 'This parameter can either be an absolute timestamp specifying the starting point of the data to be returned, or a relative number of seconds, to the last collected timestamp. Netdata will assume it is a relative number if it is smaller than the duration of the round robin database for this chart. So, if the round robin database is 3600 seconds, any value from -3600 to 3600 will trigger relative arithmetics. Netdata will adapt this parameter to the boundaries of the round robin database.' + required: true + type: number + format: integer + allowEmptyValue: false + default: -600 + - name: before + in: query + description: 'This parameter can either be an absolute timestamp specifying the ending point of the data to be returned, or a relative number of seconds, to the last collected timestamp. Netdata will assume it is a relative number if it is smaller than the duration of the round robin database for this chart. So, if the round robin database is 3600 seconds, any value from -3600 to 3600 will trigger relative arithmetics. Netdata will adapt this parameter to the boundaries of the round robin database.' + required: false + type: number + format: integer + default: 0 + - name: group + in: query + description: 'The grouping method. If multiple collected values are to be grouped in order to return fewer points, this parameters defines the method of grouping. methods are supported "min", "max", "average", "sum", "incremental-sum". "max" is actually calculated on the absolute value collected (so it works for both positive and negative dimesions to return the most extreme value in either direction).' + required: true + type: string + enum: [ 'min', 'max', 'average', 'median', 'stddev', 'sum', 'incremental-sum' ] + default: 'average' + allowEmptyValue: false + - name: options + in: query + description: 'Options that affect data generation.' + required: false + type: array + items: + type: string + enum: [ 'abs', 'absolute', 'display-absolute', 'absolute-sum', 'null2zero', 'percentage', 'unaligned' ] + collectionFormat: pipes + default: ['absolute'] + allowEmptyValue: true + - name: label + in: query + description: 'a text to be used as the label' + required: false + type: string + format: 'any text' + allowEmptyValue: true + - name: units + in: query + description: 'a text to be used as the units' + required: false + type: string + format: 'any text' + allowEmptyValue: true + - name: label_color + in: query + description: 'a color to be used for the background of the label' + required: false + type: string + format: 'any text' + allowEmptyValue: true + - name: value_color + in: query + description: 'a color to be used for the background of the label. You can set multiple using a pipe with a condition each, like this: color<value|color>value|color:null The following operators are supported: >, <, >=, <=, =, :null (to check if no value exists).' + required: false + type: string + format: 'any text' + allowEmptyValue: true + - name: multiply + in: query + description: 'multiply the value with this number for rendering it at the image (integer value required)' + required: false + type: number + format: integer + allowEmptyValue: true + - name: divide + in: query + description: 'divide the value with this number for rendering it at the image (integer value required)' + required: false + type: number + format: integer + allowEmptyValue: true + - name: scale + in: query + description: 'set the scale of the badge (greater or equal to 100)' + required: false + type: number + format: integer + allowEmptyValue: true + responses: + '200': + description: 'The call was successful. The response should be an SVG image.' + '400': + description: 'Bad request - the body will include a message stating what is wrong.' + '404': + description: 'No chart with the given id is found.' + '500': + description: 'Internal server error. This usually means the server is out of memory.' + /allmetrics: + get: + summary: 'Get a value of all the metrics maintained by netdata' + description: 'The charts endpoint returns the latest value of all charts and dimensions stored in the netdata server.' + parameters: + - name: format + in: query + description: 'The format of the response to be returned' + required: true + type: string + enum: [ 'shell', 'prometheus', 'prometheus_all_hosts', 'json' ] + default: 'shell' + - name: help + in: query + description: 'enable or disable HELP lines in prometheus output' + required: false + type: string + enum: [ 'yes', 'no' ] + default: 'no' + - name: types + in: query + description: 'enable or disable TYPE lines in prometheus output' + required: false + type: string + enum: [ 'yes', 'no' ] + default: 'no' + - name: timestamps + in: query + description: 'enable or disable timestamps in prometheus output' + required: false + type: string + enum: [ 'yes', 'no' ] + default: 'yes' + - name: names + in: query + description: 'When enabled netdata will report dimension names. When disabled netdata will report dimension IDs. The default is controlled in netdata.conf.' + required: false + type: string + enum: [ 'yes', 'no' ] + default: 'yes' + - name: server + in: query + description: 'Set a distinct name of the client querying prometheus metrics. Netdata will use the client IP if this is not set.' + required: false + type: string + format: 'any text' + - name: prefix + in: query + description: 'Prefix all prometheus metrics with this string.' + required: false + type: string + format: 'any text' + - name: data + in: query + description: 'Select the prometheus response data source. The default is controlled in netdata.conf' + required: false + type: string + enum: [ 'as-collected', 'average', 'sum' ] + default: 'average' + responses: + '200': + description: 'All the metrics returned in the format requested' + '400': + description: 'The format requested is not supported' + /alarms: + get: + summary: 'Get a list of active or raised alarms on the server' + description: 'The alarms endpoint returns the list of all raised or enabled alarms on the netdata server. Called without any parameters, the raised alarms in state WARNING or CRITICAL are returned. By passing "?all", all the enabled alarms are returned.' + parameters: + - name: all + in: query + description: 'If passed, all enabled alarms are returned' + required: false + type: boolean + allowEmptyValue: true + responses: + '200': + description: 'An object containing general info and a linked list of alarms' + schema: + $ref: '#/definitions/alarms' + /alarm_log: + get: + summary: 'Retrieves the entries of the alarm log' + description: 'Returns an array of alarm_log entries, with historical information on raised and cleared alarms.' + parameters: + - name: after + in: query + description: 'Passing the parameter after=UNIQUEID returns all the events in the alarm log that occurred after UNIQUEID. An automated series of calls would call the interface once without after=, store the last UNIQUEID of the returned set, and give it back to get incrementally the next events' + required: false + type: integer + responses: + '200': + description: 'An array of alarm log entries' + schema: + type: array + items: + $ref: '#/definitions/alarm_log_entry' + /manage/health: + get: + summary: 'Accesses the health management API to control health checks and notifications at runtime.' + description: 'Available from Netdata v1.12 and above, protected via bearer authorization. Especially useful for maintenance periods, the API allows you to disable health checks completely, silence alarm notifications, or Disable/Silence specific alarms that match selectors on alarm/template name, chart, context, host and family. For the simple disable/silence all scenaria, only the cmd parameter is required. The other parameters are used to define alarm selectors. For more information and examples, refer to the netdata documentation.' + parameters: + - name: cmd + in: query + description: 'DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors.' + required: false + type: string + enum: ['DISABLE ALL', 'SILENCE ALL', 'DISABLE', 'SILENCE', 'RESET'] + - name: alarm + in: query + description: 'The expression provided will match both `alarm` and `template` names.' + type: string + - name: chart + in: query + description: 'Chart ids/names, as shown on the dashboard. These will match the `on` entry of a configured `alarm`' + type: string + - name: context + in: query + description: 'Chart context, as shown on the dashboard. These will match the `on` entry of a configured `template`.' + type: string + - name: hosts + in: query + description: 'The hostnames that will need to match.' + type: string + - name: families + in: query + description: 'The alarm families.' + type: string + responses: + '200': + description: 'A plain text response based on the result of the command' + '403': + description: 'Bearer authentication error.' +definitions: + info: + type: object + properties: + version: + type: string + description: netdata version of the server. + example: 1.11.1_rolling + uid: + type: string + description: netdata unique id of the server. + example: 24e9fe3c-f2ac-11e8-bafc-0242ac110002 + mirrored_hosts: + type: array + description: list of hosts mirrored of the server (include itself). + items: + type: string + example: + - host1.example.com + - host2.example.com + alarms: + type: object + description: number of alarms in the server. + properties: + normal: + type: integer + description: number of alarms in normal state. + warning: + type: integer + description: number of alarms in warning state. + critical: + type: integer + description: number of alarms in critical state. + chart_summary: + type: object + properties: + hostname: + type: string + description: 'The hostname of the netdata server.' + version: + type: string + description: 'netdata version of the server.' + os: + type: string + description: 'The netdata server host operating system.' + enum: [ 'macos', 'linux', 'freebsd' ] + history: + type: number + description: 'The duration, in seconds, of the round robin database maintained by netdata.' + update_every: + type: number + description: 'The default update frequency of the netdata server. All charts have an update frequency equal or bigger than this.' + charts: + type: object + description: 'An object containing all the chart objects available at the netdata server. This is used as an indexed array. The key of each chart object is the id of the chart.' + properties: + key: + $ref: '#/definitions/chart' + charts_count: + type: number + description: 'The number of charts.' + dimensions_count: + type: number + description: 'The total number of dimensions.' + alarms_count: + type: number + description: 'The number of alarms.' + rrd_memory_bytes: + type: number + description: 'The size of the round robin database in bytes.' + chart: + type: object + properties: + id: + type: string + description: 'The unique id of the chart' + name: + type: string + description: 'The name of the chart' + type: + type: string + description: 'The type of the chart. Types are not handled by netdata. You can use this field for anything you like.' + family: + type: string + description: 'The family of the chart. Families are not handled by netdata. You can use this field for anything you like.' + title: + type: string + description: 'The title of the chart.' + priority: + type: string + description: 'The relative priority of the chart. NetData does not care about priorities. This is just an indication of importance for the chart viewers to sort charts of higher priority (lower number) closer to the top. Priority sorting should only be used among charts of the same type or family.' + enabled: + type: boolean + description: 'True when the chart is enabled. Disabled charts do not currently collect values, but they may have historical values available.' + units: + type: string + description: 'The unit of measurement for the values of all dimensions of the chart.' + data_url: + type: string + description: 'The absolute path to get data values for this chart. You are expected to use this path as the base when constructing the URL to fetch data values for this chart.' + chart_type: + type: string + description: 'The chart type.' + enum: [ 'line', 'area', 'stacked' ] + duration: + type: number + description: 'The duration, in seconds, of the round robin database maintained by netdata.' + first_entry: + type: number + description: 'The UNIX timestamp of the first entry (the oldest) in the round robin database.' + last_entry: + type: number + description: 'The UNIX timestamp of the latest entry in the round robin database.' + update_every: + type: number + description: 'The update frequency of this chart, in seconds. One value every this amount of time is kept in the round robin database.' + dimensions: + type: object + description: 'An object containing all the chart dimensions available for the chart. This is used as an indexed array. The key of the object the id of the dimension.' + properties: + key: + $ref: '#/definitions/dimension' + green: + type: number + description: 'Chart health green threshold' + red: + type: number + description: 'Chart health red trheshold' + dimension: + type: object + properties: + name: + type: string + description: 'The name of the dimension' + json_wrap: + type: object + properties: + api: + type: number + description: 'The API version this conforms to, currently 1' + id: + type: string + description: 'The unique id of the chart' + name: + type: string + description: 'The name of the chart' + update_every: + type: number + description: 'The update frequency of this chart, in seconds. One value every this amount of time is kept in the round robin database (indepedently of the current view).' + view_update_every: + type: number + description: 'The current view appropriate update frequency of this chart, in seconds. There is no point to request chart refreshes, using the same settings, more frequently than this.' + first_entry: + type: number + description: 'The UNIX timestamp of the first entry (the oldest) in the round robin database (indepedently of the current view).' + last_entry: + type: number + description: 'The UNIX timestamp of the latest entry in the round robin database (indepedently of the current view).' + after: + type: number + description: 'The UNIX timestamp of the first entry (the oldest) returned in this response.' + before: + type: number + description: 'The UNIX timestamp of the latest entry returned in this response.' + min: + type: number + description: 'The minimum value returned in the current view. This can be used to size the y-series of the chart.' + max: + type: number + description: 'The maximum value returned in the current view. This can be used to size the y-series of the chart.' + dimension_names: + description: 'The dimension names of the chart as returned in the current view.' + type: array + items: + type: string + dimension_ids: + description: 'The dimension IDs of the chart as returned in the current view.' + type: array + items: + type: string + latest_values: + description: 'The latest values collected for the chart (indepedently of the current view).' + type: array + items: + type: string + view_latest_values: + description: 'The latest values returned with this response.' + type: array + items: + type: string + dimensions: + type: number + description: 'The number of dimensions returned.' + points: + type: number + description: 'The number of rows / points returned.' + format: + type: string + description: 'The format of the result returned.' + result: + description: 'The result requested, in the format requested.' + alarms: + type: object + properties: + hostname: + type: string + latest_alarm_log_unique_id: + type: integer + format: int32 + status: + type: boolean + now: + type: integer + format: int32 + alarms: + type: object + properties: + chart-name.alarm-name: + type: object + properties: + id: + type: integer + format: int32 + name: + type: string + description: Full alarm name + chart: + type: string + family: + type: string + active: + type: boolean + description: Will be false only if the alarm is disabled in the configuration + disabled: + type: boolean + description: Whether the health check for this alarm has been disabled via a health command API DISABLE command. + silenced: + type: boolean + description: Whether notifications for this alarm have been silenced via a health command API SILENCE command. + exec: + type: string + recipient: + type: string + source: + type: string + units: + type: string + info: + type: string + status: + type: string + last_status_change: + type: integer + format: int32 + last_updated: + type: integer + format: int32 + next_update: + type: integer + format: int32 + update_every: + type: integer + format: int32 + delay_up_duration: + type: integer + format: int32 + delay_down_duration: + type: integer + format: int32 + delay_max_duration: + type: integer + format: int32 + delay_multiplier: + type: integer + format: int32 + delay: + type: integer + format: int32 + delay_up_to_timestamp: + type: integer + format: int32 + value_string: + type: string + no_clear_notification: + type: boolean + lookup_dimensions: + type: string + db_after: + type: integer + format: int32 + db_before: + type: integer + format: int32 + lookup_method: + type: string + lookup_after: + type: integer + format: int32 + lookup_before: + type: integer + format: int32 + lookup_options: + type: string + calc: + type: string + calc_parsed: + type: string + warn: + type: string + warn_parsed: + type: string + crit: + type: string + crit_parsed: + type: string + green: + type: string + format: nullable + red: + type: string + format: nullable + value: + type: number + alarm_log_entry: + type: object + properties: + hostname: + type: string + unique_id: + type: integer + format: int32 + alarm_id: + type: integer + format: int32 + alarm_event_id: + type: integer + format: int32 + name: + type: string + chart: + type: string + family: + type: string + processed: + type: boolean + updated: + type: boolean + exec_run: + type: integer + format: int32 + exec_failed: + type: boolean + exec: + type: string + recipient: + type: string + exec_code: + type: integer + format: int32 + source: + type: string + units: + type: string + when: + type: integer + format: int32 + duration: + type: integer + format: int32 + non_clear_duration: + type: integer + format: int32 + status: + type: string + old_status: + type: string + delay: + type: integer + format: int32 + delay_up_to_timestamp: + type: integer + format: int32 + updated_by_id: + type: integer + format: int32 + updates_id: + type: integer + format: int32 + value_string: + type: string + old_value_string: + type: string + silenced: + type: string + info: + type: string + value: + type: string + format: nullable + old_value: + type: string + format: nullable diff --git a/web/api/queries/Makefile.am b/web/api/queries/Makefile.am new file mode 100644 index 0000000..008dbfe --- /dev/null +++ b/web/api/queries/Makefile.am @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + average \ + des \ + incremental_sum \ + max \ + min \ + sum \ + median \ + ses \ + stddev \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/README.md b/web/api/queries/README.md new file mode 100644 index 0000000..6a55398 --- /dev/null +++ b/web/api/queries/README.md @@ -0,0 +1,172 @@ +# Database Queries + +Netdata database can be queried with `/api/v1/data` and `/api/v1/badge.svg` REST API methods. + +Every data query accepts the following parameters: + +name|required|description +:----:|:----:|:--- +`chart`|yes|The chart to be queried. +`points`|no|The number of points to be returned. Netdata can reduce number of points by applying query grouping methods. If not given, the result will have the same granularity as the database (although this relates to `gtime`). +`before`|no|The absolute timestamp or the relative (to now) time the query should finish evaluating data. If not given, it defaults to the timestamp of the latest point in the database. +`after`|no|The absolute timestamp or the relative (to `before`) time the query should start evaluating data. if not given, it defaults to the timestamp of the oldest point in the database. +`group`|no|The grouping method to use when reducing the points the database has. If not given, it defaults to `average`. +`gtime`|no|A resampling period to change the units of the metrics (i.e. setting this to `60` will convert `per second` metrics to `per minute`. If not given it defaults to granularity of the database. +`options`|no|A bitmap of options that can affect the operation of the query. Only 2 options are used by the query engine: `unaligned` and `percentage`. All the other options are used by the output formatters. The default is to return aligned data. +`dimensions`|no|A simple pattern to filter the dimensions to be queried. The default is to return all the dimensions of the chart. + +## Operation + +The query engine works as follows (in this order): + +#### Time-frame + +`after` and `before` define a time-frame, accepting: + +- **absolute timestamps** (unix timestamps, i.e. seconds since epoch). + +- **relative timestamps**: + + `before` is relative to now and `after` is relative to `before`. + + Example: `before=-60&after=-60` evaluates to the time-frame from -120 up to -60 seconds in + the past, relative to the latest entry of the database of the chart. + +The engine verifies that the time-frame requested is available at the database: + +- If the requested time-frame overlaps with the database, the excess requested + will be truncated. + +- If the requested time-frame does not overlap with the database, the engine will + return an empty data set. + +At the end of this operation, `after` and `before` are absolute timestamps. + +#### Data grouping + +Database points grouping is applied when the caller requests a time-frame to be +expressed with fewer points, compared to what is available at the database. + +There are 2 uses that enable this feature: + +- The caller requests a specific number of `points` to be returned. + + For example, for a time-frame of 10 minutes, the database has 600 points (1/sec), + while the caller requested these 10 minutes to be expressed in 200 points. + + This feature is used by netdata dashboards when you zoom-out the charts. + The dashboard is requesting the number of points the user's screen has. + This saves bandwidth and speeds up the browser (fewer points to evaluate for drawing the charts). + +- The caller requests a **re-sampling** of the database, by setting `gtime` to any value + above the granularity of the chart. + + For example, the chart's units is `requests/sec` and caller wants `requests/min`. + +Using `points` and `gtime` the query engine tries to find a best fit for **database-points** +vs **result-points** (we call this ratio `group points`). It always tries to keep `group points` +an integer. Keep in mind the query engine may shift `after` if required. See also the [example](#example). + +#### Time-frame Alignment + +Alignment is a very important aspect of netdata queries. Without it, the animated +charts on the dashboards would constantly [change shape](#example) during incremental updates. + +To provide consistent grouping through time, the query engine (by default) aligns +`after` and `before` to be a multiple of `group points`. + +For example, if `group points` is 60 and alignment is enabled, the engine will return +each point with durations XX:XX:00 - XX:XX:59, matching whole minutes. + +To disable alignment, pass `&options=unaligned` to the query. + +#### Query Execution + +To execute the query, the engine evaluates all dimensions of the chart, one after another. + +The engine does not evaluate dimensions that do not match the [simple pattern](../../../libnetdata/simple_pattern) +given at the `dimensions` parameter, except when `options=percentage` is given (this option +requires all the dimensions to be evaluated to find the percentage of each dimension vs to chart +total). + +For each dimension, it starts evaluating values starting at `after` (not inclusive) towards +`before` (inclusive). + +For each value it calls the **grouping method** given with the `&group=` query parameter +(the default is `average`). + +## Grouping methods + +The following grouping methods are supported. These are given all the values in the time-frame +and they group the values every `group points`. + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min&value_color=blue) finds the minimum value +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max&value_color=lightblue) finds the maximum value +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average&value_color=yellow) finds the average value +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=sum&after=-60&label=sum&units=requests&value_color=orange) adds all the values and returns the sum +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=median&after=-60&label=median&value_color=red) sorts the values and returns the value in the middle of the list +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=stddev&after=-60&label=stddev&value_color=green) finds the standard deviation of the values +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=cv&after=-60&label=cv&units=pcent&value_color=yellow) finds the relative standard deviation (coefficient of variation) of the values +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=ses&after=-60&label=ses&value_color=brown) finds the exponential weighted moving average of the values +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=des&after=-60&label=des&value_color=blue) applies Holt-Winters double exponential smoothing +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=incremental_sum&after=-60&label=incremental_sum&value_color=red) finds the difference of the last vs the first value + +The examples shown above, are live information from the `successful` web requests of the global netdata registry. + +## Further processing + +The result of the query engine is always a structure that has dimensions and values +for each dimension. + +Formatting modules are then used to convert this result in many different formats and return it +to the caller. + +## Performance + +The query engine is highly optimized for speed. Most of its modules implement "online" +versions of the algorithms, requiring just one pass on the database values to produce +the result. + +## Example + +When netdata is reducing metrics, it tries to return always the same boundaries. So, if we want 10s averages, it will always return points starting at a `unix timestamp % 10 = 0`. + +Let's see why this is needed, by looking at the error case. + +Assume we have 5 points: + +| time | value | +| :-: | :-: | +| 00:01 | 1 | +| 00:02 | 2 | +| 00:03 | 3 | +| 00:04 | 4 | +| 00:05 | 5 | + +At 00:04 you ask for 2 points for 4 seconds in the past. So `group = 2`. netdata would return: + +| point | time | value | +| :-: | :-: | :-: | +| 1 | 00:01 - 00:02 | 1.5 | +| 2 | 00:03 - 00:04 | 3.5 | + +A second later the chart is to be refreshed, and makes again the same request at 00:05. These are the points that would have been returned: + +| point | time | value | +| :-: | :-: | :-: | +| 1 | 00:02 - 00:03 | 2.5 | +| 2 | 00:04 - 00:05 | 4.5 | + +**Wait a moment!** The chart was shifted just one point and it changed value! Point 2 was 3.5 and when shifted to point 1 is 2.5! If you see this in a chart, it's a mess. The charts change shape constantly. + +For this reason, netdata always aligns the data it returns to the `group`. + +When you request `points=1`, netdata understands that you need 1 point for the whole database, so `group = 3600`. Then it tries to find the starting point which would be `timestamp % 3600 = 0` Within a database of 3600 seconds, there is one such point for sure. Then it tries to find the average of 3600 points. But, most probably it will not find 3600 of them (for just 1 out of 3600 seconds this query will return something). + +So, the proper way to query the database is to also set at least `after`. The following call will returns 1 point for the last complete 10-second duration (it starts at `timestamp % 10 = 0`): + +http://netdata.firehol.org/api/v1/data?chart=system.cpu&points=1&after=-10&options=seconds + +When you keep calling this URL, you will see that it returns one new value every 10 seconds, and the timestamp always ends with zero. Similarly, if you say `points=1&after=-5` it will always return timestamps ending with 0 or 5. + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/average/Makefile.am b/web/api/queries/average/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/average/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/average/README.md b/web/api/queries/average/README.md new file mode 100644 index 0000000..873b60a --- /dev/null +++ b/web/api/queries/average/README.md @@ -0,0 +1,41 @@ +# Average or Mean + +> This query is available as `average` and `mean`. + +An average is a single number taken as representative of a list of numbers. + +It is calculated as: + +``` +average = sum(numbers) / count(numbers) +``` + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: average -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`average` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=average` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) + +## References + +- [https://en.wikipedia.org/wiki/Average](https://en.wikipedia.org/wiki/Average). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Faverage%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/average/average.c b/web/api/queries/average/average.c new file mode 100644 index 0000000..c871b87 --- /dev/null +++ b/web/api/queries/average/average.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "average.h" + +// ---------------------------------------------------------------------------- +// average + +struct grouping_average { + calculated_number sum; + size_t count; +}; + +void *grouping_create_average(RRDR *r) { + (void)r; + return callocz(1, sizeof(struct grouping_average)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_average(RRDR *r) { + struct grouping_average *g = (struct grouping_average *)r->internal.grouping_data; + g->sum = 0; + g->count = 0; +} + +void grouping_free_average(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_average(RRDR *r, calculated_number value) { + if(!isnan(value)) { + struct grouping_average *g = (struct grouping_average *)r->internal.grouping_data; + g->sum += value; + g->count++; + } +} + +calculated_number grouping_flush_average(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_average *g = (struct grouping_average *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + if(unlikely(r->internal.resampling_group != 1)) + value = g->sum / r->internal.resampling_divisor; + else + value = g->sum / g->count; + } + + g->sum = 0.0; + g->count = 0; + + return value; +} diff --git a/web/api/queries/average/average.h b/web/api/queries/average/average.h new file mode 100644 index 0000000..9fb7de2 --- /dev/null +++ b/web/api/queries/average/average.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERY_AVERAGE_H +#define NETDATA_API_QUERY_AVERAGE_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_average(RRDR *r); +extern void grouping_reset_average(RRDR *r); +extern void grouping_free_average(RRDR *r); +extern void grouping_add_average(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_average(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERY_AVERAGE_H diff --git a/web/api/queries/des/Makefile.am b/web/api/queries/des/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/des/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/des/README.md b/web/api/queries/des/README.md new file mode 100644 index 0000000..486221c --- /dev/null +++ b/web/api/queries/des/README.md @@ -0,0 +1,68 @@ +# double exponential smoothing + +Exponential smoothing is one of many window functions commonly applied to smooth data in signal +processing, acting as low-pass filters to remove high frequency noise. + +Simple exponential smoothing does not do well when there is a trend in the data. +In such situations, several methods were devised under the name "double exponential smoothing" +or "second-order exponential smoothing.", which is the recursive application of an exponential +filter twice, thus being termed "double exponential smoothing". + +In simple terms, this is like an average value, but more recent values are given more weight +and the trend of the values influences significantly the result. + +> **IMPORTANT** +> +> It is common for `des` to provide "average" values that far beyond the minimum or the maximum +> values found in the time-series. +> `des` estimates these values because of it takes into account the trend. + +This module implements the "Holt-Winters double exponential smoothing". + +Netdata automatically adjusts the weight (`alpha`) and the trend (`beta`) based on the number +of values processed, using the formula: + +``` +window = max(number of values, 15) +alpha = 2 / (window + 1) +beta = 2 / (window + 1) +``` + +You can change the fixed value `15` by setting in `netdata.conf`: + +``` +[web] + des max window = 15 +``` + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: des -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`des` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=des` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average&value_color=yellow) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=ses&after=-60&label=single+exponential+smoothing&value_color=yellow) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=des&after=-60&label=double+exponential+smoothing&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) + +## References + +- [https://en.wikipedia.org/wiki/Exponential_smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fdes%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/des/des.c b/web/api/queries/des/des.c new file mode 100644 index 0000000..93d7247 --- /dev/null +++ b/web/api/queries/des/des.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <web/api/queries/rrdr.h> +#include "des.h" + + +// ---------------------------------------------------------------------------- +// single exponential smoothing + +struct grouping_des { + calculated_number alpha; + calculated_number alpha_other; + calculated_number beta; + calculated_number beta_other; + + calculated_number level; + calculated_number trend; + + size_t count; +}; + +static size_t max_window_size = 15; + +void grouping_init_des(void) { + long long ret = config_get_number(CONFIG_SECTION_WEB, "des max window", (long long)max_window_size); + if(ret <= 1) { + config_set_number(CONFIG_SECTION_WEB, "des max window", (long long)max_window_size); + } + else { + max_window_size = (size_t) ret; + } +} + +static inline calculated_number window(RRDR *r, struct grouping_des *g) { + (void)g; + + calculated_number points; + if(r->group == 1) { + // provide a running DES + points = r->internal.points_wanted; + } + else { + // provide a SES with flush points + points = r->group; + } + + // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + // A commonly used value for alpha is 2 / (N + 1) + return (points > max_window_size) ? max_window_size : points; +} + +static inline void set_alpha(RRDR *r, struct grouping_des *g) { + // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + // A commonly used value for alpha is 2 / (N + 1) + + g->alpha = 2.0 / (window(r, g) + 1.0); + g->alpha_other = 1.0 - g->alpha; + + //info("alpha for chart '%s' is " CALCULATED_NUMBER_FORMAT, r->st->name, g->alpha); +} + +static inline void set_beta(RRDR *r, struct grouping_des *g) { + // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + // A commonly used value for alpha is 2 / (N + 1) + + g->beta = 2.0 / (window(r, g) + 1.0); + g->beta_other = 1.0 - g->beta; + + //info("beta for chart '%s' is " CALCULATED_NUMBER_FORMAT, r->st->name, g->beta); +} + +void *grouping_create_des(RRDR *r) { + struct grouping_des *g = (struct grouping_des *)malloc(sizeof(struct grouping_des)); + set_alpha(r, g); + set_beta(r, g); + g->level = 0.0; + g->trend = 0.0; + g->count = 0; + return g; +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_des(RRDR *r) { + struct grouping_des *g = (struct grouping_des *)r->internal.grouping_data; + g->level = 0.0; + g->trend = 0.0; + g->count = 0; + + // fprintf(stderr, "\nDES: "); + +} + +void grouping_free_des(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_des(RRDR *r, calculated_number value) { + struct grouping_des *g = (struct grouping_des *)r->internal.grouping_data; + + if(isnormal(value)) { + if(likely(g->count > 0)) { + // we have at least a number so far + + if(unlikely(g->count == 1)) { + // the second value we got + g->trend = value - g->trend; + g->level = value; + } + + // for the values, except the first + calculated_number last_level = g->level; + g->level = (g->alpha * value) + (g->alpha_other * (g->level + g->trend)); + g->trend = (g->beta * (g->level - last_level)) + (g->beta_other * g->trend); + } + else { + // the first value we got + g->level = g->trend = value; + } + + g->count++; + } + + //fprintf(stderr, "value: " CALCULATED_NUMBER_FORMAT ", level: " CALCULATED_NUMBER_FORMAT ", trend: " CALCULATED_NUMBER_FORMAT "\n", value, g->level, g->trend); +} + +calculated_number grouping_flush_des(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_des *g = (struct grouping_des *)r->internal.grouping_data; + + if(unlikely(!g->count || !isnormal(g->level))) { + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + return 0.0; + } + + //fprintf(stderr, " RESULT for %zu values = " CALCULATED_NUMBER_FORMAT " \n", g->count, g->level); + + return g->level; +} diff --git a/web/api/queries/des/des.h b/web/api/queries/des/des.h new file mode 100644 index 0000000..360513e --- /dev/null +++ b/web/api/queries/des/des.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERIES_DES_H +#define NETDATA_API_QUERIES_DES_H + +#include "../query.h" +#include "../rrdr.h" + +extern void grouping_init_des(void); + +extern void *grouping_create_des(RRDR *r); +extern void grouping_reset_des(RRDR *r); +extern void grouping_free_des(RRDR *r); +extern void grouping_add_des(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_des(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERIES_DES_H diff --git a/web/api/queries/incremental_sum/Makefile.am b/web/api/queries/incremental_sum/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/incremental_sum/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/incremental_sum/README.md b/web/api/queries/incremental_sum/README.md new file mode 100644 index 0000000..47f833f --- /dev/null +++ b/web/api/queries/incremental_sum/README.md @@ -0,0 +1,36 @@ +# Incremental Sum (`incremental_sum`) + +This modules finds the incremental sum of a period, which `last value - first value`. + +The result may be positive (rising) or negative (falling) depending on the first and last values. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: incremental_sum -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`incremental_sum` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=incremental_sum` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=incremental_sum&after=-60&label=incremental+sum&value_color=orange) + +## References + +- none + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fincremental_sum%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/incremental_sum/incremental_sum.c b/web/api/queries/incremental_sum/incremental_sum.c new file mode 100644 index 0000000..131d85d --- /dev/null +++ b/web/api/queries/incremental_sum/incremental_sum.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "incremental_sum.h" + +// ---------------------------------------------------------------------------- +// incremental sum + +struct grouping_incremental_sum { + calculated_number first; + calculated_number last; + size_t count; +}; + +void *grouping_create_incremental_sum(RRDR *r) { + (void)r; + return callocz(1, sizeof(struct grouping_incremental_sum)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_incremental_sum(RRDR *r) { + struct grouping_incremental_sum *g = (struct grouping_incremental_sum *)r->internal.grouping_data; + g->first = 0; + g->last = 0; + g->count = 0; +} + +void grouping_free_incremental_sum(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_incremental_sum(RRDR *r, calculated_number value) { + if(!isnan(value)) { + struct grouping_incremental_sum *g = (struct grouping_incremental_sum *)r->internal.grouping_data; + + if(unlikely(!g->count)) { + g->first = value; + g->count++; + } + else { + g->last = value; + g->count++; + } + } +} + +calculated_number grouping_flush_incremental_sum(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_incremental_sum *g = (struct grouping_incremental_sum *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else if(unlikely(g->count == 1)) { + value = 0.0; + } + else { + value = g->last - g->first; + } + + g->first = 0.0; + g->last = 0.0; + g->count = 0; + + return value; +} diff --git a/web/api/queries/incremental_sum/incremental_sum.h b/web/api/queries/incremental_sum/incremental_sum.h new file mode 100644 index 0000000..990a2ac --- /dev/null +++ b/web/api/queries/incremental_sum/incremental_sum.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERY_INCREMENTAL_SUM_H +#define NETDATA_API_QUERY_INCREMENTAL_SUM_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_incremental_sum(RRDR *r); +extern void grouping_reset_incremental_sum(RRDR *r); +extern void grouping_free_incremental_sum(RRDR *r); +extern void grouping_add_incremental_sum(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_incremental_sum(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERY_INCREMENTAL_SUM_H diff --git a/web/api/queries/max/Makefile.am b/web/api/queries/max/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/max/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/max/README.md b/web/api/queries/max/README.md new file mode 100644 index 0000000..34dff02 --- /dev/null +++ b/web/api/queries/max/README.md @@ -0,0 +1,33 @@ +# Max + +This module finds the max value in the time-frame given. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: max -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`max` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=max` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max&value_color=orange) + +## References + +- [https://en.wikipedia.org/wiki/Sample_maximum_and_minimum](https://en.wikipedia.org/wiki/Sample_maximum_and_minimum). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fmax%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/max/max.c b/web/api/queries/max/max.c new file mode 100644 index 0000000..a4be36a --- /dev/null +++ b/web/api/queries/max/max.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "max.h" + +// ---------------------------------------------------------------------------- +// max + +struct grouping_max { + calculated_number max; + size_t count; +}; + +void *grouping_create_max(RRDR *r) { + (void)r; + return callocz(1, sizeof(struct grouping_max)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_max(RRDR *r) { + struct grouping_max *g = (struct grouping_max *)r->internal.grouping_data; + g->max = 0; + g->count = 0; +} + +void grouping_free_max(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_max(RRDR *r, calculated_number value) { + if(!isnan(value)) { + struct grouping_max *g = (struct grouping_max *)r->internal.grouping_data; + + if(!g->count || calculated_number_fabs(value) > calculated_number_fabs(g->max)) { + g->max = value; + g->count++; + } + } +} + +calculated_number grouping_flush_max(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_max *g = (struct grouping_max *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + value = g->max; + } + + g->max = 0.0; + g->count = 0; + + return value; +} + diff --git a/web/api/queries/max/max.h b/web/api/queries/max/max.h new file mode 100644 index 0000000..d839fe3 --- /dev/null +++ b/web/api/queries/max/max.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERY_MAX_H +#define NETDATA_API_QUERY_MAX_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_max(RRDR *r); +extern void grouping_reset_max(RRDR *r); +extern void grouping_free_max(RRDR *r); +extern void grouping_add_max(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_max(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERY_MAX_H diff --git a/web/api/queries/median/Makefile.am b/web/api/queries/median/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/median/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/median/README.md b/web/api/queries/median/README.md new file mode 100644 index 0000000..72f51a2 --- /dev/null +++ b/web/api/queries/median/README.md @@ -0,0 +1,39 @@ +# Median + +The median is the value separating the higher half from the lower half of a data sample +(a population or a probability distribution). For a data set, it may be thought of as the +"middle" value. + +`median` is not an accurate average. However, it eliminates all spikes, by sorting +all the values in a period, and selecting the value in the middle of the sorted array. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: median -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`median` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=median` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=median&after=-60&label=median&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) + +## References + +- [https://en.wikipedia.org/wiki/Median](https://en.wikipedia.org/wiki/Median). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fmedian%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/median/median.c b/web/api/queries/median/median.c new file mode 100644 index 0000000..5a13b2e --- /dev/null +++ b/web/api/queries/median/median.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "median.h" + + +// ---------------------------------------------------------------------------- +// median + +struct grouping_median { + size_t series_size; + size_t next_pos; + + LONG_DOUBLE series[]; +}; + +void *grouping_create_median(RRDR *r) { + long entries = r->group; + if(entries < 0) entries = 0; + + struct grouping_median *g = (struct grouping_median *)callocz(1, sizeof(struct grouping_median) + entries * sizeof(LONG_DOUBLE)); + g->series_size = (size_t)entries; + + return g; +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_median(RRDR *r) { + struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data; + g->next_pos = 0; +} + +void grouping_free_median(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_median(RRDR *r, calculated_number value) { + struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data; + + if(unlikely(g->next_pos >= g->series_size)) { + error("INTERNAL ERROR: median buffer overflow on chart '%s' - next_pos = %zu, series_size = %zu, r->group = %ld.", r->st->name, g->next_pos, g->series_size, r->group); + } + else { + if(isnormal(value)) + g->series[g->next_pos++] = (LONG_DOUBLE)value; + } +} + +calculated_number grouping_flush_median(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_median *g = (struct grouping_median *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->next_pos)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + if(g->next_pos > 1) { + sort_series(g->series, g->next_pos); + value = (calculated_number)median_on_sorted_series(g->series, g->next_pos); + } + else + value = (calculated_number)g->series[0]; + + if(!isnormal(value)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + + //log_series_to_stderr(g->series, g->next_pos, value, "median"); + } + + g->next_pos = 0; + + return value; +} + diff --git a/web/api/queries/median/median.h b/web/api/queries/median/median.h new file mode 100644 index 0000000..dd2c1ff --- /dev/null +++ b/web/api/queries/median/median.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERIES_MEDIAN_H +#define NETDATA_API_QUERIES_MEDIAN_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_median(RRDR *r); +extern void grouping_reset_median(RRDR *r); +extern void grouping_free_median(RRDR *r); +extern void grouping_add_median(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_median(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERIES_MEDIAN_H diff --git a/web/api/queries/min/Makefile.am b/web/api/queries/min/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/min/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/min/README.md b/web/api/queries/min/README.md new file mode 100644 index 0000000..28f6dbf --- /dev/null +++ b/web/api/queries/min/README.md @@ -0,0 +1,33 @@ +# Min + +This module finds the min value in the time-frame given. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: min -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`min` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=min` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) + +## References + +- [https://en.wikipedia.org/wiki/Sample_maximum_and_minimum](https://en.wikipedia.org/wiki/Sample_maximum_and_minimum). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fmin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/min/min.c b/web/api/queries/min/min.c new file mode 100644 index 0000000..9bd7460 --- /dev/null +++ b/web/api/queries/min/min.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "min.h" + +// ---------------------------------------------------------------------------- +// min + +struct grouping_min { + calculated_number min; + size_t count; +}; + +void *grouping_create_min(RRDR *r) { + (void)r; + return callocz(1, sizeof(struct grouping_min)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_min(RRDR *r) { + struct grouping_min *g = (struct grouping_min *)r->internal.grouping_data; + g->min = 0; + g->count = 0; +} + +void grouping_free_min(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_min(RRDR *r, calculated_number value) { + if(!isnan(value)) { + struct grouping_min *g = (struct grouping_min *)r->internal.grouping_data; + + if(!g->count || calculated_number_fabs(value) < calculated_number_fabs(g->min)) { + g->min = value; + g->count++; + } + } +} + +calculated_number grouping_flush_min(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_min *g = (struct grouping_min *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + value = g->min; + } + + g->min = 0.0; + g->count = 0; + + return value; +} + diff --git a/web/api/queries/min/min.h b/web/api/queries/min/min.h new file mode 100644 index 0000000..7470360 --- /dev/null +++ b/web/api/queries/min/min.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERY_MIN_H +#define NETDATA_API_QUERY_MIN_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_min(RRDR *r); +extern void grouping_reset_min(RRDR *r); +extern void grouping_free_min(RRDR *r); +extern void grouping_add_min(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_min(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERY_MIN_H diff --git a/web/api/queries/query.c b/web/api/queries/query.c new file mode 100644 index 0000000..f841b65 --- /dev/null +++ b/web/api/queries/query.c @@ -0,0 +1,989 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "query.h" +#include "web/api/formatters/rrd2json.h" +#include "rrdr.h" + +#include "average/average.h" +#include "incremental_sum/incremental_sum.h" +#include "max/max.h" +#include "median/median.h" +#include "min/min.h" +#include "sum/sum.h" +#include "stddev/stddev.h" +#include "ses/ses.h" +#include "des/des.h" + +// ---------------------------------------------------------------------------- + +static struct { + const char *name; + uint32_t hash; + RRDR_GROUPING value; + + // One time initialization for the module. + // This is called once, when netdata starts. + void (*init)(void); + + // Allocate all required structures for a query. + // This is called once for each netdata query. + void *(*create)(struct rrdresult *r); + + // Cleanup collected values, but don't destroy the structures. + // This is called when the query engine switches dimensions, + // as part of the same query (so same chart, switching metric). + void (*reset)(struct rrdresult *r); + + // Free all resources allocated for the query. + void (*free)(struct rrdresult *r); + + // Add a single value into the calculation. + // The module may decide to cache it, or use it in the fly. + void (*add)(struct rrdresult *r, calculated_number value); + + // Generate a single result for the values added so far. + // More values and points may be requested later. + // It is up to the module to reset its internal structures + // when flushing it (so for a few modules it may be better to + // continue after a flush as if nothing changed, for others a + // cleanup of the internal structures may be required). + calculated_number (*flush)(struct rrdresult *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); +} api_v1_data_groups[] = { + {.name = "average", + .hash = 0, + .value = RRDR_GROUPING_AVERAGE, + .init = NULL, + .create= grouping_create_average, + .reset = grouping_reset_average, + .free = grouping_free_average, + .add = grouping_add_average, + .flush = grouping_flush_average + }, + {.name = "mean", // alias on 'average' + .hash = 0, + .value = RRDR_GROUPING_AVERAGE, + .init = NULL, + .create= grouping_create_average, + .reset = grouping_reset_average, + .free = grouping_free_average, + .add = grouping_add_average, + .flush = grouping_flush_average + }, + {.name = "incremental_sum", + .hash = 0, + .value = RRDR_GROUPING_INCREMENTAL_SUM, + .init = NULL, + .create= grouping_create_incremental_sum, + .reset = grouping_reset_incremental_sum, + .free = grouping_free_incremental_sum, + .add = grouping_add_incremental_sum, + .flush = grouping_flush_incremental_sum + }, + {.name = "incremental-sum", + .hash = 0, + .value = RRDR_GROUPING_INCREMENTAL_SUM, + .init = NULL, + .create= grouping_create_incremental_sum, + .reset = grouping_reset_incremental_sum, + .free = grouping_free_incremental_sum, + .add = grouping_add_incremental_sum, + .flush = grouping_flush_incremental_sum + }, + {.name = "median", + .hash = 0, + .value = RRDR_GROUPING_MEDIAN, + .init = NULL, + .create= grouping_create_median, + .reset = grouping_reset_median, + .free = grouping_free_median, + .add = grouping_add_median, + .flush = grouping_flush_median + }, + {.name = "min", + .hash = 0, + .value = RRDR_GROUPING_MIN, + .init = NULL, + .create= grouping_create_min, + .reset = grouping_reset_min, + .free = grouping_free_min, + .add = grouping_add_min, + .flush = grouping_flush_min + }, + {.name = "max", + .hash = 0, + .value = RRDR_GROUPING_MAX, + .init = NULL, + .create= grouping_create_max, + .reset = grouping_reset_max, + .free = grouping_free_max, + .add = grouping_add_max, + .flush = grouping_flush_max + }, + {.name = "sum", + .hash = 0, + .value = RRDR_GROUPING_SUM, + .init = NULL, + .create= grouping_create_sum, + .reset = grouping_reset_sum, + .free = grouping_free_sum, + .add = grouping_add_sum, + .flush = grouping_flush_sum + }, + + // standard deviation + {.name = "stddev", + .hash = 0, + .value = RRDR_GROUPING_STDDEV, + .init = NULL, + .create= grouping_create_stddev, + .reset = grouping_reset_stddev, + .free = grouping_free_stddev, + .add = grouping_add_stddev, + .flush = grouping_flush_stddev + }, + {.name = "cv", // coefficient variation is calculated by stddev + .hash = 0, + .value = RRDR_GROUPING_CV, + .init = NULL, + .create= grouping_create_stddev, // not an error, stddev calculates this too + .reset = grouping_reset_stddev, // not an error, stddev calculates this too + .free = grouping_free_stddev, // not an error, stddev calculates this too + .add = grouping_add_stddev, // not an error, stddev calculates this too + .flush = grouping_flush_coefficient_of_variation + }, + {.name = "rsd", // alias of 'cv' + .hash = 0, + .value = RRDR_GROUPING_CV, + .init = NULL, + .create= grouping_create_stddev, // not an error, stddev calculates this too + .reset = grouping_reset_stddev, // not an error, stddev calculates this too + .free = grouping_free_stddev, // not an error, stddev calculates this too + .add = grouping_add_stddev, // not an error, stddev calculates this too + .flush = grouping_flush_coefficient_of_variation + }, + + /* + {.name = "mean", // same as average, no need to define it again + .hash = 0, + .value = RRDR_GROUPING_MEAN, + .setup = NULL, + .create= grouping_create_stddev, + .reset = grouping_reset_stddev, + .free = grouping_free_stddev, + .add = grouping_add_stddev, + .flush = grouping_flush_mean + }, + */ + + /* + {.name = "variance", // meaningless to offer + .hash = 0, + .value = RRDR_GROUPING_VARIANCE, + .setup = NULL, + .create= grouping_create_stddev, + .reset = grouping_reset_stddev, + .free = grouping_free_stddev, + .add = grouping_add_stddev, + .flush = grouping_flush_variance + }, + */ + + // single exponential smoothing + {.name = "ses", + .hash = 0, + .value = RRDR_GROUPING_SES, + .init = grouping_init_ses, + .create= grouping_create_ses, + .reset = grouping_reset_ses, + .free = grouping_free_ses, + .add = grouping_add_ses, + .flush = grouping_flush_ses + }, + {.name = "ema", // alias for 'ses' + .hash = 0, + .value = RRDR_GROUPING_SES, + .init = NULL, + .create= grouping_create_ses, + .reset = grouping_reset_ses, + .free = grouping_free_ses, + .add = grouping_add_ses, + .flush = grouping_flush_ses + }, + {.name = "ewma", // alias for ses + .hash = 0, + .value = RRDR_GROUPING_SES, + .init = NULL, + .create= grouping_create_ses, + .reset = grouping_reset_ses, + .free = grouping_free_ses, + .add = grouping_add_ses, + .flush = grouping_flush_ses + }, + + // double exponential smoothing + {.name = "des", + .hash = 0, + .value = RRDR_GROUPING_DES, + .init = grouping_init_des, + .create= grouping_create_des, + .reset = grouping_reset_des, + .free = grouping_free_des, + .add = grouping_add_des, + .flush = grouping_flush_des + }, + + // terminator + {.name = NULL, + .hash = 0, + .value = RRDR_GROUPING_UNDEFINED, + .init = NULL, + .create= grouping_create_average, + .reset = grouping_reset_average, + .free = grouping_free_average, + .add = grouping_add_average, + .flush = grouping_flush_average + } +}; + +void web_client_api_v1_init_grouping(void) { + int i; + + for(i = 0; api_v1_data_groups[i].name ; i++) { + api_v1_data_groups[i].hash = simple_hash(api_v1_data_groups[i].name); + + if(api_v1_data_groups[i].init) + api_v1_data_groups[i].init(); + } +} + +const char *group_method2string(RRDR_GROUPING group) { + int i; + + for(i = 0; api_v1_data_groups[i].name ; i++) { + if(api_v1_data_groups[i].value == group) { + return api_v1_data_groups[i].name; + } + } + + return "unknown-group-method"; +} + +RRDR_GROUPING web_client_api_request_v1_data_group(const char *name, RRDR_GROUPING def) { + int i; + + uint32_t hash = simple_hash(name); + for(i = 0; api_v1_data_groups[i].name ; i++) + if(unlikely(hash == api_v1_data_groups[i].hash && !strcmp(name, api_v1_data_groups[i].name))) + return api_v1_data_groups[i].value; + + return def; +} + +// ---------------------------------------------------------------------------- + +static void rrdr_disable_not_selected_dimensions(RRDR *r, RRDR_OPTIONS options, const char *dims) { + rrdset_check_rdlock(r->st); + + if(unlikely(!dims || !*dims || (dims[0] == '*' && dims[1] == '\0'))) return; + + int match_ids = 0, match_names = 0; + + if(unlikely(options & RRDR_OPTION_MATCH_IDS)) + match_ids = 1; + if(unlikely(options & RRDR_OPTION_MATCH_NAMES)) + match_names = 1; + + if(likely(!match_ids && !match_names)) + match_ids = match_names = 1; + + SIMPLE_PATTERN *pattern = simple_pattern_create(dims, ",|\t\r\n\f\v", SIMPLE_PATTERN_EXACT); + + RRDDIM *d; + long c, dims_selected = 0, dims_not_hidden_not_zero = 0; + for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { + if( (match_ids && simple_pattern_matches(pattern, d->id)) + || (match_names && simple_pattern_matches(pattern, d->name)) + ) { + r->od[c] |= RRDR_DIMENSION_SELECTED; + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) r->od[c] &= ~RRDR_DIMENSION_HIDDEN; + dims_selected++; + + // since the user needs this dimension + // make it appear as NONZERO, to return it + // even if the dimension has only zeros + // unless option non_zero is set + if(unlikely(!(options & RRDR_OPTION_NONZERO))) + r->od[c] |= RRDR_DIMENSION_NONZERO; + + // count the visible dimensions + if(likely(r->od[c] & RRDR_DIMENSION_NONZERO)) + dims_not_hidden_not_zero++; + } + else { + r->od[c] |= RRDR_DIMENSION_HIDDEN; + if(unlikely(r->od[c] & RRDR_DIMENSION_SELECTED)) r->od[c] &= ~RRDR_DIMENSION_SELECTED; + } + } + simple_pattern_free(pattern); + + // check if all dimensions are hidden + if(unlikely(!dims_not_hidden_not_zero && dims_selected)) { + // there are a few selected dimensions + // but they are all zero + // enable the selected ones + // to avoid returning an empty chart + for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) + if(unlikely(r->od[c] & RRDR_DIMENSION_SELECTED)) + r->od[c] |= RRDR_DIMENSION_NONZERO; + } +} + +// ---------------------------------------------------------------------------- +// helpers to find our way in RRDR + +static inline RRDR_VALUE_FLAGS *rrdr_line_options(RRDR *r, long rrdr_line) { + return &r->o[ rrdr_line * r->d ]; +} + +static inline calculated_number *rrdr_line_values(RRDR *r, long rrdr_line) { + return &r->v[ rrdr_line * r->d ]; +} + +static inline long rrdr_line_init(RRDR *r, time_t t, long rrdr_line) { + rrdr_line++; + + #ifdef NETDATA_INTERNAL_CHECKS + + if(unlikely(rrdr_line >= r->n)) + error("INTERNAL ERROR: requested to step above RRDR size for chart '%s'", r->st->name); + + if(unlikely(r->t[rrdr_line] != 0 && r->t[rrdr_line] != t)) + error("INTERNAL ERROR: overwriting the timestamp of RRDR line %zu from %zu to %zu, of chart '%s'", (size_t)rrdr_line, (size_t)r->t[rrdr_line], (size_t)t, r->st->name); + + #endif + + // save the time + r->t[rrdr_line] = t; + + return rrdr_line; +} + +static inline void rrdr_done(RRDR *r, long rrdr_line) { + r->rows = rrdr_line + 1; +} + + +// ---------------------------------------------------------------------------- +// fill RRDR for a single dimension + +static inline void do_dimension( + RRDR *r + , long points_wanted + , RRDDIM *rd + , long dim_id_in_rrdr + , long after_slot + , long before_slot + , time_t after_wanted + , time_t before_wanted +){ + (void) before_slot; + + RRDSET *st = r->st; + + time_t + now = after_wanted, + dt = st->update_every, + max_date = 0, + min_date = 0; + + long + slot = after_slot, + group_size = r->group, + points_added = 0, + values_in_group = 0, + values_in_group_non_zero = 0, + rrdr_line = -1, + entries = st->entries; + + RRDR_VALUE_FLAGS + group_value_flags = RRDR_VALUE_NOTHING; + + calculated_number min = r->min, max = r->max; + size_t db_points_read = 0; + for( ; points_added < points_wanted ; now += dt, slot++ ) { + if(unlikely(slot >= entries)) slot = 0; + + // make sure we return data in the proper time range + if(unlikely(now > before_wanted)) { + #ifdef NETDATA_INTERNAL_CHECKS + r->internal.log = "stopped, because attempted to access the db after 'wanted before'"; + #endif + break; + } + if(unlikely(now < after_wanted)) { + #ifdef NETDATA_INTERNAL_CHECKS + r->internal.log = "skipped, because attempted to access the db before 'wanted after'"; + #endif + continue; + } + + // read the value from the database + storage_number n = rd->values[slot]; + calculated_number value = NAN; + if(likely(does_storage_number_exist(n))) { + + value = unpack_storage_number(n); + if(likely(value != 0.0)) + values_in_group_non_zero++; + + if(unlikely(did_storage_number_reset(n))) + group_value_flags |= RRDR_VALUE_RESET; + + } + + // add this value for grouping + r->internal.grouping_add(r, value); + values_in_group++; + db_points_read++; + + if(unlikely(values_in_group == group_size)) { + rrdr_line = rrdr_line_init(r, now, rrdr_line); + + if(unlikely(!min_date)) min_date = now; + max_date = now; + + // find the place to store our values + RRDR_VALUE_FLAGS *rrdr_value_options_ptr = &r->o[rrdr_line * r->d + dim_id_in_rrdr]; + + // update the dimension options + if(likely(values_in_group_non_zero)) + r->od[dim_id_in_rrdr] |= RRDR_DIMENSION_NONZERO; + + // store the specific point options + *rrdr_value_options_ptr = group_value_flags; + + // store the value + calculated_number value = r->internal.grouping_flush(r, rrdr_value_options_ptr); + r->v[rrdr_line * r->d + dim_id_in_rrdr] = value; + + if(likely(points_added || dim_id_in_rrdr)) { + // find the min/max across all dimensions + + if(unlikely(value < min)) min = value; + if(unlikely(value > max)) max = value; + + } + else { + // runs only when dim_id_in_rrdr == 0 && points_added == 0 + // so, on the first point added for the query. + min = max = value; + } + + points_added++; + values_in_group = 0; + group_value_flags = RRDR_VALUE_NOTHING; + values_in_group_non_zero = 0; + } + } + + r->internal.db_points_read += db_points_read; + r->internal.result_points_generated += points_added; + + r->min = min; + r->max = max; + r->before = max_date; + r->after = min_date - (r->group - 1) * r->st->update_every; + rrdr_done(r, rrdr_line); + + #ifdef NETDATA_INTERNAL_CHECKS + if(unlikely(r->rows != points_added)) + error("INTERNAL ERROR: %s.%s added %zu rows, but RRDR says I added %zu.", r->st->name, rd->name, (size_t)points_added, (size_t)r->rows); + #endif +} + +// ---------------------------------------------------------------------------- +// fill RRDR for the whole chart + +#ifdef NETDATA_INTERNAL_CHECKS +static void rrd2rrdr_log_request_response_metdata(RRDR *r + , RRDR_GROUPING group_method + , int aligned + , long group + , long resampling_time + , long resampling_group + , time_t after_wanted + , time_t after_requested + , time_t before_wanted + , time_t before_requested + , long points_requested + , long points_wanted + , size_t after_slot + , size_t before_slot + , const char *msg + ) { + info("INTERNAL ERROR: rrd2rrdr() on %s update every %d with %s grouping %s (group: %ld, resampling_time: %ld, resampling_group: %ld), " + "after (got: %zu, want: %zu, req: %zu, db: %zu), " + "before (got: %zu, want: %zu, req: %zu, db: %zu), " + "duration (got: %zu, want: %zu, req: %zu, db: %zu), " + "slot (after: %zu, before: %zu, delta: %zu), " + "points (got: %ld, want: %ld, req: %ld, db: %ld), " + "%s" + , r->st->name + , r->st->update_every + + // grouping + , (aligned) ? "aligned" : "unaligned" + , group_method2string(group_method) + , group + , resampling_time + , resampling_group + + // after + , (size_t)r->after + , (size_t)after_wanted + , (size_t)after_requested + , (size_t)rrdset_first_entry_t(r->st) + + // before + , (size_t)r->before + , (size_t)before_wanted + , (size_t)before_requested + , (size_t)rrdset_last_entry_t(r->st) + + // duration + , (size_t)(r->before - r->after + r->st->update_every) + , (size_t)(before_wanted - after_wanted + r->st->update_every) + , (size_t)(before_requested - after_requested) + , (size_t)((rrdset_last_entry_t(r->st) - rrdset_first_entry_t(r->st)) + r->st->update_every) + + // slot + , after_slot + , before_slot + , (after_slot > before_slot) ? (r->st->entries - after_slot + before_slot) : (before_slot - after_slot) + + // points + , r->rows + , points_wanted + , points_requested + , r->st->entries + + // message + , msg + ); +} +#endif // NETDATA_INTERNAL_CHECKS + +RRDR *rrd2rrdr( + RRDSET *st + , long points_requested + , long long after_requested + , long long before_requested + , RRDR_GROUPING group_method + , long resampling_time_requested + , RRDR_OPTIONS options + , const char *dimensions +) { + int aligned = !(options & RRDR_OPTION_NOT_ALIGNED); + + int absolute_period_requested = -1; + + time_t first_entry_t = rrdset_first_entry_t(st); + time_t last_entry_t = rrdset_last_entry_t(st); + + if(before_requested == 0 && after_requested == 0) { + // dump the all the data + before_requested = last_entry_t; + after_requested = first_entry_t; + absolute_period_requested = 0; + } + + // allow relative for before (smaller than API_RELATIVE_TIME_MAX) + if(((before_requested < 0)?-before_requested:before_requested) <= API_RELATIVE_TIME_MAX) { + if(abs(before_requested) % st->update_every) { + // make sure it is multiple of st->update_every + if(before_requested < 0) before_requested = before_requested - st->update_every - before_requested % st->update_every; + else before_requested = before_requested + st->update_every - before_requested % st->update_every; + } + if(before_requested > 0) before_requested = first_entry_t + before_requested; + else before_requested = last_entry_t + before_requested; + absolute_period_requested = 0; + } + + // allow relative for after (smaller than API_RELATIVE_TIME_MAX) + if(((after_requested < 0)?-after_requested:after_requested) <= API_RELATIVE_TIME_MAX) { + if(after_requested == 0) after_requested = -st->update_every; + if(abs(after_requested) % st->update_every) { + // make sure it is multiple of st->update_every + if(after_requested < 0) after_requested = after_requested - st->update_every - after_requested % st->update_every; + else after_requested = after_requested + st->update_every - after_requested % st->update_every; + } + after_requested = before_requested + after_requested; + absolute_period_requested = 0; + } + + if(absolute_period_requested == -1) + absolute_period_requested = 1; + + // make sure they are within our timeframe + if(before_requested > last_entry_t) before_requested = last_entry_t; + if(before_requested < first_entry_t) before_requested = first_entry_t; + + if(after_requested > last_entry_t) after_requested = last_entry_t; + if(after_requested < first_entry_t) after_requested = first_entry_t; + + // check if they are reversed + if(after_requested > before_requested) { + time_t tmp = before_requested; + before_requested = after_requested; + after_requested = tmp; + } + + // the duration of the chart + time_t duration = before_requested - after_requested; + long available_points = duration / st->update_every; + + if(duration <= 0 || available_points <= 0) + return rrdr_create(st, 1); + + // check the number of wanted points in the result + if(unlikely(points_requested < 0)) points_requested = -points_requested; + if(unlikely(points_requested > available_points)) points_requested = available_points; + if(unlikely(points_requested == 0)) points_requested = available_points; + + // calculate the desired grouping of source data points + long group = available_points / points_requested; + if(unlikely(group <= 0)) group = 1; + if(unlikely(available_points % points_requested > points_requested / 2)) group++; // rounding to the closest integer + + // resampling_time_requested enforces a certain grouping multiple + calculated_number resampling_divisor = 1.0; + long resampling_group = 1; + if(unlikely(resampling_time_requested > st->update_every)) { + if (unlikely(resampling_time_requested > duration)) { + // group_time is above the available duration + + #ifdef NETDATA_INTERNAL_CHECKS + info("INTERNAL CHECK: %s: requested gtime %ld secs, is greater than the desired duration %ld secs", st->id, resampling_time_requested, duration); + #endif + + after_requested = before_requested - resampling_time_requested; + duration = before_requested - after_requested; + available_points = duration / st->update_every; + group = available_points / points_requested; + } + + // if the duration is not aligned to resampling time + // extend the duration to the past, to avoid a gap at the chart + // only when the missing duration is above 1/10th of a point + if(duration % resampling_time_requested) { + time_t delta = duration % resampling_time_requested; + if(delta > resampling_time_requested / 10) { + after_requested -= resampling_time_requested - delta; + duration = before_requested - after_requested; + available_points = duration / st->update_every; + group = available_points / points_requested; + } + } + + // the points we should group to satisfy gtime + resampling_group = resampling_time_requested / st->update_every; + if(unlikely(resampling_time_requested % st->update_every)) { + #ifdef NETDATA_INTERNAL_CHECKS + info("INTERNAL CHECK: %s: requested gtime %ld secs, is not a multiple of the chart's data collection frequency %d secs", st->id, resampling_time_requested, st->update_every); + #endif + + resampling_group++; + } + + // adapt group according to resampling_group + if(unlikely(group < resampling_group)) group = resampling_group; // do not allow grouping below the desired one + if(unlikely(group % resampling_group)) group += resampling_group - (group % resampling_group); // make sure group is multiple of resampling_group + + //resampling_divisor = group / resampling_group; + resampling_divisor = (calculated_number)(group * st->update_every) / (calculated_number)resampling_time_requested; + } + + // now that we have group, + // align the requested timeframe to fit it. + + if(aligned) { + // alignement has been requested, so align the values + before_requested -= (before_requested % group); + after_requested -= (after_requested % group); + } + + // we align the request on requested_before + time_t before_wanted = before_requested; + if(likely(before_wanted > last_entry_t)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: rrd2rrdr() on %s, before_wanted is after db max", st->name); + #endif + + before_wanted = last_entry_t - (last_entry_t % ( ((aligned)?group:1) * st->update_every )); + } + size_t before_slot = rrdset_time2slot(st, before_wanted); + + // we need to estimate the number of points, for having + // an integer number of values per point + long points_wanted = (before_wanted - after_requested) / (st->update_every * group); + + time_t after_wanted = before_wanted - (points_wanted * group * st->update_every) + st->update_every; + if(unlikely(after_wanted < first_entry_t)) { + // hm... we go to the past, calculate again points_wanted using all the db from before_wanted to the beginning + points_wanted = (before_wanted - first_entry_t) / group; + + // recalculate after wanted with the new number of points + after_wanted = before_wanted - (points_wanted * group * st->update_every) + st->update_every; + + if(unlikely(after_wanted < first_entry_t)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: rrd2rrdr() on %s, after_wanted is before db min", st->name); + #endif + + after_wanted = first_entry_t - (first_entry_t % ( ((aligned)?group:1) * st->update_every )) + ( ((aligned)?group:1) * st->update_every ); + } + } + size_t after_slot = rrdset_time2slot(st, after_wanted); + + // check if they are reversed + if(unlikely(after_wanted > before_wanted)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: rrd2rrdr() on %s, reversed wanted after/before", st->name); + #endif + time_t tmp = before_wanted; + before_wanted = after_wanted; + after_wanted = tmp; + } + + // recalculate points_wanted using the final time-frame + points_wanted = (before_wanted - after_wanted) / st->update_every / group + 1; + if(unlikely(points_wanted < 0)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: rrd2rrdr() on %s, points_wanted is %ld", st->name, points_wanted); + #endif + points_wanted = 0; + } + +#ifdef NETDATA_INTERNAL_CHECKS + duration = before_wanted - after_wanted; + + if(after_wanted < first_entry_t) + error("INTERNAL CHECK: after_wanted %u is too small, minimum %u", (uint32_t)after_wanted, (uint32_t)first_entry_t); + + if(after_wanted > last_entry_t) + error("INTERNAL CHECK: after_wanted %u is too big, maximum %u", (uint32_t)after_wanted, (uint32_t)last_entry_t); + + if(before_wanted < first_entry_t) + error("INTERNAL CHECK: before_wanted %u is too small, minimum %u", (uint32_t)before_wanted, (uint32_t)first_entry_t); + + if(before_wanted > last_entry_t) + error("INTERNAL CHECK: before_wanted %u is too big, maximum %u", (uint32_t)before_wanted, (uint32_t)last_entry_t); + + if(before_slot >= (size_t)st->entries) + error("INTERNAL CHECK: before_slot is invalid %zu, expected 0 to %ld", before_slot, st->entries - 1); + + if(after_slot >= (size_t)st->entries) + error("INTERNAL CHECK: after_slot is invalid %zu, expected 0 to %ld", after_slot, st->entries - 1); + + if(points_wanted > (before_wanted - after_wanted) / group / st->update_every + 1) + error("INTERNAL CHECK: points_wanted %ld is more than points %ld", points_wanted, (before_wanted - after_wanted) / group / st->update_every + 1); + + if(group < resampling_group) + error("INTERNAL CHECK: group %ld is less than the desired group points %ld", group, resampling_group); + + if(group > resampling_group && group % resampling_group) + error("INTERNAL CHECK: group %ld is not a multiple of the desired group points %ld", group, resampling_group); +#endif + + // ------------------------------------------------------------------------- + // initialize our result set + // this also locks the chart for us + + RRDR *r = rrdr_create(st, points_wanted); + if(unlikely(!r)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL CHECK: Cannot create RRDR for %s, after=%u, before=%u, duration=%u, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (uint32_t)duration, points_wanted); + #endif + return NULL; + } + + if(unlikely(!r->d || !points_wanted)) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL CHECK: Returning empty RRDR (no dimensions in RRDSET) for %s, after=%u, before=%u, duration=%zu, points=%ld", st->id, (uint32_t)after_wanted, (uint32_t)before_wanted, (size_t)duration, points_wanted); + #endif + return r; + } + + if(unlikely(absolute_period_requested == 1)) + r->result_options |= RRDR_RESULT_OPTION_ABSOLUTE; + else + r->result_options |= RRDR_RESULT_OPTION_RELATIVE; + + // find how many dimensions we have + long dimensions_count = r->d; + + // ------------------------------------------------------------------------- + // initialize RRDR + + r->group = group; + r->update_every = (int)group * st->update_every; + r->before = before_wanted; + r->after = after_wanted; + r->internal.points_wanted = points_wanted; + r->internal.resampling_group = resampling_group; + r->internal.resampling_divisor = resampling_divisor; + + + // ------------------------------------------------------------------------- + // assign the processor functions + + { + int i, found = 0; + for(i = 0; !found && api_v1_data_groups[i].name ;i++) { + if(api_v1_data_groups[i].value == group_method) { + r->internal.grouping_create= api_v1_data_groups[i].create; + r->internal.grouping_reset = api_v1_data_groups[i].reset; + r->internal.grouping_free = api_v1_data_groups[i].free; + r->internal.grouping_add = api_v1_data_groups[i].add; + r->internal.grouping_flush = api_v1_data_groups[i].flush; + found = 1; + } + } + if(!found) { + errno = 0; + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: grouping method %u not found for chart '%s'. Using 'average'", (unsigned int)group_method, r->st->name); + #endif + r->internal.grouping_create= grouping_create_average; + r->internal.grouping_reset = grouping_reset_average; + r->internal.grouping_free = grouping_free_average; + r->internal.grouping_add = grouping_add_average; + r->internal.grouping_flush = grouping_flush_average; + } + } + + // allocate any memory required by the grouping method + r->internal.grouping_data = r->internal.grouping_create(r); + + + // ------------------------------------------------------------------------- + // disable the not-wanted dimensions + + rrdset_check_rdlock(st); + + if(dimensions) + rrdr_disable_not_selected_dimensions(r, options, dimensions); + + + // ------------------------------------------------------------------------- + // do the work for each dimension + + time_t max_after = 0, min_before = 0; + long max_rows = 0; + + RRDDIM *rd; + long c, dimensions_used = 0, dimensions_nonzero = 0; + for(rd = st->dimensions, c = 0 ; rd && c < dimensions_count ; rd = rd->next, c++) { + + // if we need a percentage, we need to calculate all dimensions + if(unlikely(!(options & RRDR_OPTION_PERCENTAGE) && (r->od[c] & RRDR_DIMENSION_HIDDEN))) { + if(unlikely(r->od[c] & RRDR_DIMENSION_SELECTED)) r->od[c] &= ~RRDR_DIMENSION_SELECTED; + continue; + } + r->od[c] |= RRDR_DIMENSION_SELECTED; + + // reset the grouping for the new dimension + r->internal.grouping_reset(r); + + do_dimension( + r + , points_wanted + , rd + , c + , after_slot + , before_slot + , after_wanted + , before_wanted + ); + + if(r->od[c] & RRDR_DIMENSION_NONZERO) + dimensions_nonzero++; + + // verify all dimensions are aligned + if(unlikely(!dimensions_used)) { + min_before = r->before; + max_after = r->after; + max_rows = r->rows; + } + else { + if(r->after != max_after) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: 'after' mismatch between dimensions for chart '%s': max is %zu, dimension '%s' has %zu", + st->name, (size_t)max_after, rd->name, (size_t)r->after); + #endif + r->after = (r->after > max_after) ? r->after : max_after; + } + + if(r->before != min_before) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: 'before' mismatch between dimensions for chart '%s': max is %zu, dimension '%s' has %zu", + st->name, (size_t)min_before, rd->name, (size_t)r->before); + #endif + r->before = (r->before < min_before) ? r->before : min_before; + } + + if(r->rows != max_rows) { + #ifdef NETDATA_INTERNAL_CHECKS + error("INTERNAL ERROR: 'rows' mismatch between dimensions for chart '%s': max is %zu, dimension '%s' has %zu", + st->name, (size_t)max_rows, rd->name, (size_t)r->rows); + #endif + r->rows = (r->rows > max_rows) ? r->rows : max_rows; + } + } + + dimensions_used++; + } + + #ifdef NETDATA_INTERNAL_CHECKS + + if(r->internal.log) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, r->internal.log); + + if(r->rows != points_wanted) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "got 'points' is not wanted 'points'"); + + if(aligned && (r->before % group) != 0) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "'before' is not aligned but alignment is required"); + + // 'after' should not be aligned, since we start inside the first group + //if(aligned && (r->after % group) != 0) + // rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "'after' is not aligned but alignment is required"); + + if(r->before != before_requested) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "chart is not aligned to requested 'before'"); + + if(r->before != before_wanted) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "got 'before' is not wanted 'before'"); + + // reported 'after' varies, depending on group + if(r->after != after_wanted) + rrd2rrdr_log_request_response_metdata(r, group_method, aligned, group, resampling_time_requested, resampling_group, after_wanted, after_requested, before_wanted, before_requested, points_requested, points_wanted, after_slot, before_slot, "got 'after' is not wanted 'after'"); + + #endif + + // free all resources used by the grouping method + r->internal.grouping_free(r); + + // when all the dimensions are zero, we should return all of them + if(unlikely(options & RRDR_OPTION_NONZERO && !dimensions_nonzero)) { + // all the dimensions are zero + // mark them as NONZERO to send them all + for(rd = st->dimensions, c = 0 ; rd && c < dimensions_count ; rd = rd->next, c++) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + r->od[c] |= RRDR_DIMENSION_NONZERO; + } + } + + rrdr_query_completed(r->internal.db_points_read, r->internal.result_points_generated); + return r; +} diff --git a/web/api/queries/query.h b/web/api/queries/query.h new file mode 100644 index 0000000..6b8a51c --- /dev/null +++ b/web/api/queries/query.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_DATA_QUERY_H +#define NETDATA_API_DATA_QUERY_H + +typedef enum rrdr_grouping { + RRDR_GROUPING_UNDEFINED = 0, + RRDR_GROUPING_AVERAGE, + RRDR_GROUPING_MIN, + RRDR_GROUPING_MAX, + RRDR_GROUPING_SUM, + RRDR_GROUPING_INCREMENTAL_SUM, + RRDR_GROUPING_MEDIAN, + RRDR_GROUPING_STDDEV, + RRDR_GROUPING_CV, + RRDR_GROUPING_SES, + RRDR_GROUPING_DES, +} RRDR_GROUPING; + +extern const char *group_method2string(RRDR_GROUPING group); +extern void web_client_api_v1_init_grouping(void); +extern RRDR_GROUPING web_client_api_request_v1_data_group(const char *name, RRDR_GROUPING def); + +#endif //NETDATA_API_DATA_QUERY_H diff --git a/web/api/queries/rrdr.c b/web/api/queries/rrdr.c new file mode 100644 index 0000000..e727e60 --- /dev/null +++ b/web/api/queries/rrdr.c @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rrdr.h" + +/* +static void rrdr_dump(RRDR *r) +{ + long c, i; + RRDDIM *d; + + fprintf(stderr, "\nCHART %s (%s)\n", r->st->id, r->st->name); + + for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { + fprintf(stderr, "DIMENSION %s (%s), %s%s%s%s\n" + , d->id + , d->name + , (r->od[c] & RRDR_EMPTY)?"EMPTY ":"" + , (r->od[c] & RRDR_RESET)?"RESET ":"" + , (r->od[c] & RRDR_DIMENSION_HIDDEN)?"HIDDEN ":"" + , (r->od[c] & RRDR_DIMENSION_NONZERO)?"NONZERO ":"" + ); + } + + if(r->rows <= 0) { + fprintf(stderr, "RRDR does not have any values in it.\n"); + return; + } + + fprintf(stderr, "RRDR includes %d values in it:\n", r->rows); + + // for each line in the array + for(i = 0; i < r->rows ;i++) { + calculated_number *cn = &r->v[ i * r->d ]; + RRDR_DIMENSION_FLAGS *co = &r->o[ i * r->d ]; + + // print the id and the timestamp of the line + fprintf(stderr, "%ld %ld ", i + 1, r->t[i]); + + // for each dimension + for(c = 0, d = r->st->dimensions; d ;c++, d = d->next) { + if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; + if(unlikely(!(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; + + if(co[c] & RRDR_EMPTY) + fprintf(stderr, "null "); + else + fprintf(stderr, CALCULATED_NUMBER_FORMAT " %s%s%s%s " + , cn[c] + , (co[c] & RRDR_EMPTY)?"E":" " + , (co[c] & RRDR_RESET)?"R":" " + , (co[c] & RRDR_DIMENSION_HIDDEN)?"H":" " + , (co[c] & RRDR_DIMENSION_NONZERO)?"N":" " + ); + } + + fprintf(stderr, "\n"); + } +} +*/ + + + + +inline static void rrdr_lock_rrdset(RRDR *r) { + if(unlikely(!r)) { + error("NULL value given!"); + return; + } + + rrdset_rdlock(r->st); + r->has_st_lock = 1; +} + +inline static void rrdr_unlock_rrdset(RRDR *r) { + if(unlikely(!r)) { + error("NULL value given!"); + return; + } + + if(likely(r->has_st_lock)) { + rrdset_unlock(r->st); + r->has_st_lock = 0; + } +} + +inline void rrdr_free(RRDR *r) +{ + if(unlikely(!r)) { + error("NULL value given!"); + return; + } + + rrdr_unlock_rrdset(r); + freez(r->t); + freez(r->v); + freez(r->o); + freez(r->od); + freez(r); +} + +RRDR *rrdr_create(RRDSET *st, long n) +{ + if(unlikely(!st)) { + error("NULL value given!"); + return NULL; + } + + RRDR *r = callocz(1, sizeof(RRDR)); + r->st = st; + + rrdr_lock_rrdset(r); + + RRDDIM *rd; + rrddim_foreach_read(rd, st) r->d++; + + r->n = n; + + r->t = callocz((size_t)n, sizeof(time_t)); + r->v = mallocz(n * r->d * sizeof(calculated_number)); + r->o = mallocz(n * r->d * sizeof(RRDR_VALUE_FLAGS)); + r->od = mallocz(r->d * sizeof(RRDR_DIMENSION_FLAGS)); + + // set the hidden flag on hidden dimensions + int c; + for(c = 0, rd = st->dimensions ; rd ; c++, rd = rd->next) { + if(unlikely(rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN))) + r->od[c] = RRDR_DIMENSION_HIDDEN; + else + r->od[c] = RRDR_DIMENSION_DEFAULT; + } + + r->group = 1; + r->update_every = 1; + + return r; +} diff --git a/web/api/queries/rrdr.h b/web/api/queries/rrdr.h new file mode 100644 index 0000000..4f63503 --- /dev/null +++ b/web/api/queries/rrdr.h @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_QUERIES_RRDR_H +#define NETDATA_QUERIES_RRDR_H + +#include "libnetdata/libnetdata.h" + +typedef enum rrdr_options { + RRDR_OPTION_NONZERO = 0x00000001, // don't output dimensions will just zero values + RRDR_OPTION_REVERSED = 0x00000002, // output the rows in reverse order (oldest to newest) + RRDR_OPTION_ABSOLUTE = 0x00000004, // values positive, for DATASOURCE_SSV before summing + RRDR_OPTION_MIN2MAX = 0x00000008, // when adding dimensions, use max - min, instead of sum + RRDR_OPTION_SECONDS = 0x00000010, // output seconds, instead of dates + RRDR_OPTION_MILLISECONDS = 0x00000020, // output milliseconds, instead of dates + RRDR_OPTION_NULL2ZERO = 0x00000040, // do not show nulls, convert them to zeros + RRDR_OPTION_OBJECTSROWS = 0x00000080, // each row of values should be an object, not an array + RRDR_OPTION_GOOGLE_JSON = 0x00000100, // comply with google JSON/JSONP specs + RRDR_OPTION_JSON_WRAP = 0x00000200, // wrap the response in a JSON header with info about the result + RRDR_OPTION_LABEL_QUOTES = 0x00000400, // in CSV output, wrap header labels in double quotes + RRDR_OPTION_PERCENTAGE = 0x00000800, // give values as percentage of total + RRDR_OPTION_NOT_ALIGNED = 0x00001000, // do not align charts for persistant timeframes + RRDR_OPTION_DISPLAY_ABS = 0x00002000, // for badges, display the absolute value, but calculate colors with sign + RRDR_OPTION_MATCH_IDS = 0x00004000, // when filtering dimensions, match only IDs + RRDR_OPTION_MATCH_NAMES = 0x00008000, // when filtering dimensions, match only names +} RRDR_OPTIONS; + +typedef enum rrdr_value_flag { + RRDR_VALUE_NOTHING = 0x00, // no flag set (a good default) + RRDR_VALUE_EMPTY = 0x01, // the database value is empty + RRDR_VALUE_RESET = 0x02, // the database value is marked as reset (overflown) +} RRDR_VALUE_FLAGS; + +typedef enum rrdr_dimension_flag { + RRDR_DIMENSION_DEFAULT = 0x00, + RRDR_DIMENSION_HIDDEN = 0x04, // the dimension is hidden (not to be presented to callers) + RRDR_DIMENSION_NONZERO = 0x08, // the dimension is non zero (contains non-zero values) + RRDR_DIMENSION_SELECTED = 0x10, // the dimension is selected for evaluation in this RRDR +} RRDR_DIMENSION_FLAGS; + +// RRDR result options +typedef enum rrdr_result_flags { + RRDR_RESULT_OPTION_ABSOLUTE = 0x00000001, // the query uses absolute time-frames (can be cached by browsers and proxies) + RRDR_RESULT_OPTION_RELATIVE = 0x00000002, // the query uses relative time-frames (should not to be cached by browsers and proxies) +} RRDR_RESULT_FLAGS; + +typedef struct rrdresult { + struct rrdset *st; // the chart this result refers to + + RRDR_RESULT_FLAGS result_options; // RRDR_RESULT_OPTION_* + + int d; // the number of dimensions + long n; // the number of values in the arrays + long rows; // the number of rows used + + RRDR_DIMENSION_FLAGS *od; // the options for the dimensions + + time_t *t; // array of n timestamps + calculated_number *v; // array n x d values + RRDR_VALUE_FLAGS *o; // array n x d options for each value returned + + long group; // how many collected values were grouped for each row + int update_every; // what is the suggested update frequency in seconds + + calculated_number min; + calculated_number max; + + time_t before; + time_t after; + + int has_st_lock; // if st is read locked by us + + // internal rrd2rrdr() members below this point + struct { + long points_wanted; + long resampling_group; + calculated_number resampling_divisor; + + void *(*grouping_create)(struct rrdresult *r); + void (*grouping_reset)(struct rrdresult *r); + void (*grouping_free)(struct rrdresult *r); + void (*grouping_add)(struct rrdresult *r, calculated_number value); + calculated_number (*grouping_flush)(struct rrdresult *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + void *grouping_data; + + #ifdef NETDATA_INTERNAL_CHECKS + const char *log; + #endif + + size_t db_points_read; + size_t result_points_generated; + } internal; +} RRDR; + +#define rrdr_rows(r) ((r)->rows) + +extern void rrdr_free(RRDR *r); +extern RRDR *rrdr_create(struct rrdset *st, long n); + +#include "../web_api_v1.h" +#include "web/api/queries/query.h" + +extern RRDR *rrd2rrdr(RRDSET *st, long points_requested, long long after_requested, long long before_requested, RRDR_GROUPING group_method, long resampling_time_requested, RRDR_OPTIONS options, const char *dimensions); + +#include "query.h" + +#endif //NETDATA_QUERIES_RRDR_H diff --git a/web/api/queries/ses/Makefile.am b/web/api/queries/ses/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/ses/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/ses/README.md b/web/api/queries/ses/README.md new file mode 100644 index 0000000..16b153a --- /dev/null +++ b/web/api/queries/ses/README.md @@ -0,0 +1,56 @@ +# Single (or Simple) Exponential Smoothing (`ses`) + +> This query is also available as `ema` and `ewma`. + +An exponential moving average (`ema`), also known as an exponentially weighted moving average (`ewma`) +is a first-order infinite impulse response filter that applies weighting factors which decrease +exponentially. The weighting for each older datum decreases exponentially, never reaching zero. + +In simple terms, this is like an average value, but more recent values are given more weight. + +Netdata automatically adjusts the weight (`alpha`) based on the number of values processed, +using the formula: + +``` +window = max(number of values, 15) +alpha = 2 / (window + 1) +``` + +You can change the fixed value `15` by setting in `netdata.conf`: + +``` +[web] + ses max window = 15 +``` + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: ses -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`ses` does not change the units. For example, if the chart units is `requests/sec`, the exponential +moving average will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=ses` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average&value_color=yellow) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=ses&after=-60&label=single+exponential+smoothing&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) + +## References + +- [https://en.wikipedia.org/wiki/Moving_average#exponential-moving-average](https://en.wikipedia.org/wiki/Moving_average#exponential-moving-average) +- [https://en.wikipedia.org/wiki/Exponential_smoothing](https://en.wikipedia.org/wiki/Exponential_smoothing). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fses%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/ses/ses.c b/web/api/queries/ses/ses.c new file mode 100644 index 0000000..6ea40df --- /dev/null +++ b/web/api/queries/ses/ses.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "ses.h" + + +// ---------------------------------------------------------------------------- +// single exponential smoothing + +struct grouping_ses { + calculated_number alpha; + calculated_number alpha_other; + calculated_number level; + size_t count; +}; + +static size_t max_window_size = 15; + +void grouping_init_ses(void) { + long long ret = config_get_number(CONFIG_SECTION_WEB, "ses max window", (long long)max_window_size); + if(ret <= 1) { + config_set_number(CONFIG_SECTION_WEB, "ses max window", (long long)max_window_size); + } + else { + max_window_size = (size_t) ret; + } +} + +static inline calculated_number window(RRDR *r, struct grouping_ses *g) { + (void)g; + + calculated_number points; + if(r->group == 1) { + // provide a running DES + points = r->internal.points_wanted; + } + else { + // provide a SES with flush points + points = r->group; + } + + return (points > max_window_size) ? max_window_size : points; +} + +static inline void set_alpha(RRDR *r, struct grouping_ses *g) { + // https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average + // A commonly used value for alpha is 2 / (N + 1) + g->alpha = 2.0 / (window(r, g) + 1.0); + g->alpha_other = 1.0 - g->alpha; +} + +void *grouping_create_ses(RRDR *r) { + struct grouping_ses *g = (struct grouping_ses *)callocz(1, sizeof(struct grouping_ses)); + set_alpha(r, g); + g->level = 0.0; + return g; +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_ses(RRDR *r) { + struct grouping_ses *g = (struct grouping_ses *)r->internal.grouping_data; + g->level = 0.0; + g->count = 0; +} + +void grouping_free_ses(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_ses(RRDR *r, calculated_number value) { + struct grouping_ses *g = (struct grouping_ses *)r->internal.grouping_data; + + if(isnormal(value)) { + if(unlikely(!g->count)) + g->level = value; + + g->level = g->alpha * value + g->alpha_other * g->level; + g->count++; + } +} + +calculated_number grouping_flush_ses(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_ses *g = (struct grouping_ses *)r->internal.grouping_data; + + if(unlikely(!g->count || !isnormal(g->level))) { + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + return 0.0; + } + + return g->level; +} diff --git a/web/api/queries/ses/ses.h b/web/api/queries/ses/ses.h new file mode 100644 index 0000000..603fdb5 --- /dev/null +++ b/web/api/queries/ses/ses.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERIES_SES_H +#define NETDATA_API_QUERIES_SES_H + +#include "../query.h" +#include "../rrdr.h" + +extern void grouping_init_ses(void); + +extern void *grouping_create_ses(RRDR *r); +extern void grouping_reset_ses(RRDR *r); +extern void grouping_free_ses(RRDR *r); +extern void grouping_add_ses(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_ses(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERIES_SES_H diff --git a/web/api/queries/stddev/Makefile.am b/web/api/queries/stddev/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/stddev/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/stddev/README.md b/web/api/queries/stddev/README.md new file mode 100644 index 0000000..2ef5a2e --- /dev/null +++ b/web/api/queries/stddev/README.md @@ -0,0 +1,89 @@ + +# standard deviation (`stddev`) + +The standard deviation is a measure that is used to quantify the amount of variation or dispersion +of a set of data values. + +A low standard deviation indicates that the data points tend to be close to the mean (also called the +expected value) of the set, while a high standard deviation indicates that the data points are spread +out over a wider range of values. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: stddev -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`stdev` does not change the units. For example, if the chart units is `requests/sec`, the standard +deviation will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=stddev` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=average&after=-60&label=average&value_color=yellow) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=stddev&after=-60&label=standard+deviation&value_color=orange) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=max&after=-60&label=max) + +## References + +Check [https://en.wikipedia.org/wiki/Standard_deviation](https://en.wikipedia.org/wiki/Standard_deviation). + +--- + +# Coefficient of variation (`cv`) + +> This query is also available as `rsd`. + +The coefficient of variation (`cv`), also known as relative standard deviation (`rsd`), +is a standardized measure of dispersion of a probability distribution or frequency distribution. + +It is defined as the ratio of the **standard deviation** to the **mean**. + +In simple terms, it gives the percentage of change. So, if the average value of a metric is 1000 +and its standard deviation is 100 (meaning that it variates from 900 to 1100), then `cv` is 10%. + +This is an easy way to check the % variation, without using absolute values. + +For example, you may trigger an alarm if your web server requests/sec `cv` is above 20 (`%`) +over the last minute. So if your web server was serving 1000 reqs/sec over the last minute, +it will trigger the alarm if had spikes below 800/sec or above 1200/sec. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: cv -1m unaligned of my_dimension + units: % + warn: $this > 20 +``` + +The units reported by `cv` is always `%`. + +It can also be used in APIs and badges as `&group=cv` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=average&after=-60&label=average&value_color=yellow) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=cv&after=-60&label=coefficient+of+variation&value_color=orange&units=pcent) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&dimensions=success&group=max&after=-60&label=max) + +## References + +Check [https://en.wikipedia.org/wiki/Coefficient_of_variation](https://en.wikipedia.org/wiki/Coefficient_of_variation). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fstddev%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/stddev/stddev.c b/web/api/queries/stddev/stddev.c new file mode 100644 index 0000000..3858003 --- /dev/null +++ b/web/api/queries/stddev/stddev.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "stddev.h" + + +// ---------------------------------------------------------------------------- +// stddev + +// this implementation comes from: +// https://www.johndcook.com/blog/standard_deviation/ + +struct grouping_stddev { + long count; + calculated_number m_oldM, m_newM, m_oldS, m_newS; +}; + +void *grouping_create_stddev(RRDR *r) { + long entries = r->group; + if(entries < 0) entries = 0; + + return callocz(1, sizeof(struct grouping_stddev) + entries * sizeof(LONG_DOUBLE)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_stddev(RRDR *r) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + g->count = 0; +} + +void grouping_free_stddev(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_stddev(RRDR *r, calculated_number value) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + + if(isnormal(value)) { + g->count++; + + // See Knuth TAOCP vol 2, 3rd edition, page 232 + if (g->count == 1) { + g->m_oldM = g->m_newM = value; + g->m_oldS = 0.0; + } + else { + g->m_newM = g->m_oldM + (value - g->m_oldM) / g->count; + g->m_newS = g->m_oldS + (value - g->m_oldM) * (value - g->m_newM); + + // set up for next iteration + g->m_oldM = g->m_newM; + g->m_oldS = g->m_newS; + } + } +} + +static inline calculated_number mean(struct grouping_stddev *g) { + return (g->count > 0) ? g->m_newM : 0.0; +} + +static inline calculated_number variance(struct grouping_stddev *g) { + return ( (g->count > 1) ? g->m_newS/(g->count - 1) : 0.0 ); +} +static inline calculated_number stddev(struct grouping_stddev *g) { + return sqrtl(variance(g)); +} + +calculated_number grouping_flush_stddev(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + + calculated_number value; + + if(likely(g->count > 1)) { + value = stddev(g); + + if(!isnormal(value)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + } + else if(g->count == 1) { + value = 0.0; + } + else { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + + grouping_reset_stddev(r); + + return value; +} + +// https://en.wikipedia.org/wiki/Coefficient_of_variation +calculated_number grouping_flush_coefficient_of_variation(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + + calculated_number value; + + if(likely(g->count > 1)) { + calculated_number m = mean(g); + value = 100.0 * stddev(g) / ((m < 0)? -m : m); + + if(unlikely(!isnormal(value))) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + } + else if(g->count == 1) { + // one value collected + value = 0.0; + } + else { + // no values collected + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + + grouping_reset_stddev(r); + + return value; +} + + +/* + * Mean = average + * +calculated_number grouping_flush_mean(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + value = mean(g); + + if(!isnormal(value)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + } + + grouping_reset_stddev(r); + + return value; +} + */ + +/* + * It is not advised to use this version of variance directly + * +calculated_number grouping_flush_variance(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_stddev *g = (struct grouping_stddev *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + value = variance(g); + + if(!isnormal(value)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + } + + grouping_reset_stddev(r); + + return value; +} +*/
\ No newline at end of file diff --git a/web/api/queries/stddev/stddev.h b/web/api/queries/stddev/stddev.h new file mode 100644 index 0000000..7a46975 --- /dev/null +++ b/web/api/queries/stddev/stddev.h @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERIES_STDDEV_H +#define NETDATA_API_QUERIES_STDDEV_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_stddev(RRDR *r); +extern void grouping_reset_stddev(RRDR *r); +extern void grouping_free_stddev(RRDR *r); +extern void grouping_add_stddev(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_stddev(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); +extern calculated_number grouping_flush_coefficient_of_variation(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); +// extern calculated_number grouping_flush_mean(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); +// extern calculated_number grouping_flush_variance(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERIES_STDDEV_H diff --git a/web/api/queries/sum/Makefile.am b/web/api/queries/sum/Makefile.am new file mode 100644 index 0000000..19554be --- /dev/null +++ b/web/api/queries/sum/Makefile.am @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/api/queries/sum/README.md b/web/api/queries/sum/README.md new file mode 100644 index 0000000..a74ffff --- /dev/null +++ b/web/api/queries/sum/README.md @@ -0,0 +1,36 @@ +# Sum + +This module sums all the values in the time-frame requested. + +You can use `sum` to find the volume of something over a period. + +## how to use + +Use it in alarms like this: + +``` + alarm: my_alarm + on: my_chart +lookup: sum -1m unaligned of my_dimension + warn: $this > 1000 +``` + +`sum` does not change the units. For example, if the chart units is `requests/sec`, the result +will be again expressed in the same units. + +It can also be used in APIs and badges as `&group=sum` in the URL. + +## Examples + +Examining last 1 minute `successful` web server responses: + +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=min&after=-60&label=min) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=average&after=-60&label=average) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=max&after=-60&label=max) +- ![](https://registry.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx.response_statuses&options=unaligned&dimensions=success&group=sum&after=-60&label=1m+sum&value_color=orange&units=requests) + +## References + +- [https://en.wikipedia.org/wiki/Summation](https://en.wikipedia.org/wiki/Summation). + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fapi%2Fqueries%2Fsum%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/api/queries/sum/sum.c b/web/api/queries/sum/sum.c new file mode 100644 index 0000000..0da9937 --- /dev/null +++ b/web/api/queries/sum/sum.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "sum.h" + +// ---------------------------------------------------------------------------- +// sum + +struct grouping_sum { + calculated_number sum; + size_t count; +}; + +void *grouping_create_sum(RRDR *r) { + (void)r; + return callocz(1, sizeof(struct grouping_sum)); +} + +// resets when switches dimensions +// so, clear everything to restart +void grouping_reset_sum(RRDR *r) { + struct grouping_sum *g = (struct grouping_sum *)r->internal.grouping_data; + g->sum = 0; + g->count = 0; +} + +void grouping_free_sum(RRDR *r) { + freez(r->internal.grouping_data); + r->internal.grouping_data = NULL; +} + +void grouping_add_sum(RRDR *r, calculated_number value) { + if(!isnan(value)) { + struct grouping_sum *g = (struct grouping_sum *)r->internal.grouping_data; + g->sum += value; + g->count++; + } +} + +calculated_number grouping_flush_sum(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr) { + struct grouping_sum *g = (struct grouping_sum *)r->internal.grouping_data; + + calculated_number value; + + if(unlikely(!g->count)) { + value = 0.0; + *rrdr_value_options_ptr |= RRDR_VALUE_EMPTY; + } + else { + value = g->sum; + } + + g->sum = 0.0; + g->count = 0; + + return value; +} + + diff --git a/web/api/queries/sum/sum.h b/web/api/queries/sum/sum.h new file mode 100644 index 0000000..9dc8d20 --- /dev/null +++ b/web/api/queries/sum/sum.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_QUERY_SUM_H +#define NETDATA_API_QUERY_SUM_H + +#include "../query.h" +#include "../rrdr.h" + +extern void *grouping_create_sum(RRDR *r); +extern void grouping_reset_sum(RRDR *r); +extern void grouping_free_sum(RRDR *r); +extern void grouping_add_sum(RRDR *r, calculated_number value); +extern calculated_number grouping_flush_sum(RRDR *r, RRDR_VALUE_FLAGS *rrdr_value_options_ptr); + +#endif //NETDATA_API_QUERY_SUM_H diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c new file mode 100644 index 0000000..991a9ec --- /dev/null +++ b/web/api/web_api_v1.c @@ -0,0 +1,803 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web_api_v1.h" + +static struct { + const char *name; + uint32_t hash; + RRDR_OPTIONS value; +} api_v1_data_options[] = { + { "nonzero" , 0 , RRDR_OPTION_NONZERO} + , {"flip" , 0 , RRDR_OPTION_REVERSED} + , {"reversed" , 0 , RRDR_OPTION_REVERSED} + , {"reverse" , 0 , RRDR_OPTION_REVERSED} + , {"jsonwrap" , 0 , RRDR_OPTION_JSON_WRAP} + , {"min2max" , 0 , RRDR_OPTION_MIN2MAX} + , {"ms" , 0 , RRDR_OPTION_MILLISECONDS} + , {"milliseconds" , 0 , RRDR_OPTION_MILLISECONDS} + , {"abs" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute_sum" , 0 , RRDR_OPTION_ABSOLUTE} + , {"absolute-sum" , 0 , RRDR_OPTION_ABSOLUTE} + , {"display_absolute", 0 , RRDR_OPTION_DISPLAY_ABS} + , {"display-absolute", 0 , RRDR_OPTION_DISPLAY_ABS} + , {"seconds" , 0 , RRDR_OPTION_SECONDS} + , {"null2zero" , 0 , RRDR_OPTION_NULL2ZERO} + , {"objectrows" , 0 , RRDR_OPTION_OBJECTSROWS} + , {"google_json" , 0 , RRDR_OPTION_GOOGLE_JSON} + , {"google-json" , 0 , RRDR_OPTION_GOOGLE_JSON} + , {"percentage" , 0 , RRDR_OPTION_PERCENTAGE} + , {"unaligned" , 0 , RRDR_OPTION_NOT_ALIGNED} + , {"match_ids" , 0 , RRDR_OPTION_MATCH_IDS} + , {"match-ids" , 0 , RRDR_OPTION_MATCH_IDS} + , {"match_names" , 0 , RRDR_OPTION_MATCH_NAMES} + , {"match-names" , 0 , RRDR_OPTION_MATCH_NAMES} + , { NULL, 0, 0} +}; + +static struct { + const char *name; + uint32_t hash; + uint32_t value; +} api_v1_data_formats[] = { + { DATASOURCE_FORMAT_DATATABLE_JSON , 0 , DATASOURCE_DATATABLE_JSON} + , {DATASOURCE_FORMAT_DATATABLE_JSONP, 0 , DATASOURCE_DATATABLE_JSONP} + , {DATASOURCE_FORMAT_JSON , 0 , DATASOURCE_JSON} + , {DATASOURCE_FORMAT_JSONP , 0 , DATASOURCE_JSONP} + , {DATASOURCE_FORMAT_SSV , 0 , DATASOURCE_SSV} + , {DATASOURCE_FORMAT_CSV , 0 , DATASOURCE_CSV} + , {DATASOURCE_FORMAT_TSV , 0 , DATASOURCE_TSV} + , {"tsv-excel" , 0 , DATASOURCE_TSV} + , {DATASOURCE_FORMAT_HTML , 0 , DATASOURCE_HTML} + , {DATASOURCE_FORMAT_JS_ARRAY , 0 , DATASOURCE_JS_ARRAY} + , {DATASOURCE_FORMAT_SSV_COMMA , 0 , DATASOURCE_SSV_COMMA} + , {DATASOURCE_FORMAT_CSV_JSON_ARRAY , 0 , DATASOURCE_CSV_JSON_ARRAY} + , {DATASOURCE_FORMAT_CSV_MARKDOWN , 0 , DATASOURCE_CSV_MARKDOWN} + , { NULL, 0, 0} +}; + +static struct { + const char *name; + uint32_t hash; + uint32_t value; +} api_v1_data_google_formats[] = { + // this is not error - when google requests json, it expects javascript + // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source#responseformat + { "json" , 0 , DATASOURCE_DATATABLE_JSONP} + , {"html" , 0 , DATASOURCE_HTML} + , {"csv" , 0 , DATASOURCE_CSV} + , {"tsv-excel", 0 , DATASOURCE_TSV} + , { NULL, 0, 0} +}; + +void web_client_api_v1_init(void) { + int i; + + for(i = 0; api_v1_data_options[i].name ; i++) + api_v1_data_options[i].hash = simple_hash(api_v1_data_options[i].name); + + for(i = 0; api_v1_data_formats[i].name ; i++) + api_v1_data_formats[i].hash = simple_hash(api_v1_data_formats[i].name); + + for(i = 0; api_v1_data_google_formats[i].name ; i++) + api_v1_data_google_formats[i].hash = simple_hash(api_v1_data_google_formats[i].name); + + web_client_api_v1_init_grouping(); + + uuid_t uuid; + + // generate + uuid_generate(uuid); + + // unparse (to string) + char uuid_str[37]; + uuid_unparse_lower(uuid, uuid_str); +} + +char *get_mgmt_api_key(void) { + char filename[FILENAME_MAX + 1]; + snprintfz(filename, FILENAME_MAX, "%s/netdata.api.key", netdata_configured_varlib_dir); + char *api_key_filename=config_get(CONFIG_SECTION_REGISTRY, "netdata management api key file", filename); + static char guid[GUID_LEN + 1] = ""; + + if(likely(guid[0])) + return guid; + + // read it from disk + int fd = open(api_key_filename, O_RDONLY); + if(fd != -1) { + char buf[GUID_LEN + 1]; + if(read(fd, buf, GUID_LEN) != GUID_LEN) + error("Failed to read management API key from '%s'", api_key_filename); + else { + buf[GUID_LEN] = '\0'; + if(regenerate_guid(buf, guid) == -1) { + error("Failed to validate management API key '%s' from '%s'.", + buf, api_key_filename); + + guid[0] = '\0'; + } + } + close(fd); + } + + // generate a new one? + if(!guid[0]) { + uuid_t uuid; + + uuid_generate_time(uuid); + uuid_unparse_lower(uuid, guid); + guid[GUID_LEN] = '\0'; + + // save it + fd = open(api_key_filename, O_WRONLY|O_CREAT|O_TRUNC, 444); + if(fd == -1) + fatal("Cannot create unique management API key file '%s'. Please fix this.", api_key_filename); + + if(write(fd, guid, GUID_LEN) != GUID_LEN) + fatal("Cannot write the unique management API key file '%s'. Please fix this.", api_key_filename); + + close(fd); + } + + return guid; +} + +void web_client_api_v1_management_init(void) { + api_secret = get_mgmt_api_key(); +} + +inline uint32_t web_client_api_request_v1_data_options(char *o) { + uint32_t ret = 0x00000000; + char *tok; + + while(o && *o && (tok = mystrsep(&o, ", |"))) { + if(!*tok) continue; + + uint32_t hash = simple_hash(tok); + int i; + for(i = 0; api_v1_data_options[i].name ; i++) { + if (unlikely(hash == api_v1_data_options[i].hash && !strcmp(tok, api_v1_data_options[i].name))) { + ret |= api_v1_data_options[i].value; + break; + } + } + } + + return ret; +} + +inline uint32_t web_client_api_request_v1_data_format(char *name) { + uint32_t hash = simple_hash(name); + int i; + + for(i = 0; api_v1_data_formats[i].name ; i++) { + if (unlikely(hash == api_v1_data_formats[i].hash && !strcmp(name, api_v1_data_formats[i].name))) { + return api_v1_data_formats[i].value; + } + } + + return DATASOURCE_JSON; +} + +inline uint32_t web_client_api_request_v1_data_google_format(char *name) { + uint32_t hash = simple_hash(name); + int i; + + for(i = 0; api_v1_data_google_formats[i].name ; i++) { + if (unlikely(hash == api_v1_data_google_formats[i].hash && !strcmp(name, api_v1_data_google_formats[i].name))) { + return api_v1_data_google_formats[i].value; + } + } + + return DATASOURCE_JSON; +} + + +inline int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url) { + int all = 0; + + while(url) { + char *value = mystrsep(&url, "&"); + if (!value || !*value) continue; + + if(!strcmp(value, "all")) all = 1; + else if(!strcmp(value, "active")) all = 0; + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + health_alarms2json(host, w->response.data, all); + return 200; +} + +inline int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url) { + uint32_t after = 0; + + while(url) { + char *value = mystrsep(&url, "&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + if(!strcmp(name, "after")) after = (uint32_t)strtoul(value, NULL, 0); + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + health_alarm_log2json(host, w->response.data, after); + return 200; +} + +inline int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)) { + int ret = 400; + char *chart = NULL; + + buffer_flush(w->response.data); + + while(url) { + char *value = mystrsep(&url, "&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + //else { + /// buffer_sprintf(w->response.data, "Unknown parameter '%s' in request.", name); + // goto cleanup; + //} + } + + if(!chart || !*chart) { + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, chart); + ret = 404; + goto cleanup; + } + + w->response.data->contenttype = CT_APPLICATION_JSON; + st->last_accessed_time = now_realtime_sec(); + callback(st, w->response.data); + return 200; + + cleanup: + return ret; +} + +inline int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_request_single_chart(host, w, url, health_api_v1_chart_variables2json); +} + +inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_APPLICATION_JSON; + charts2json(host, w->response.data); + return 200; +} + +inline int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url) { + return web_client_api_request_single_chart(host, w, url, rrd_stats_api_v1_chart); +} + +void fix_google_param(char *s) { + if(unlikely(!s)) return; + + for( ; *s ;s++) { + if(!isalnum(*s) && *s != '.' && *s != '_' && *s != '-') + *s = '_'; + } +} + +// returns the HTTP code +inline int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url) { + debug(D_WEB_CLIENT, "%llu: API v1 data with URL '%s'", w->id, url); + + int ret = 400; + BUFFER *dimensions = NULL; + + buffer_flush(w->response.data); + + char *google_version = "0.6", + *google_reqId = "0", + *google_sig = "0", + *google_out = "json", + *responseHandler = NULL, + *outFileName = NULL; + + time_t last_timestamp_in_data = 0, google_timestamp = 0; + + char *chart = NULL + , *before_str = NULL + , *after_str = NULL + , *group_time_str = NULL + , *points_str = NULL; + + int group = RRDR_GROUPING_AVERAGE; + uint32_t format = DATASOURCE_JSON; + uint32_t options = 0x00000000; + + while(url) { + char *value = mystrsep(&url, "&"); + if(!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if(!name || !*name) continue; + if(!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 data query param '%s' with value '%s'", w->id, name, value); + + // name and value are now the parameters + // they are not null and not empty + + if(!strcmp(name, "chart")) chart = value; + else if(!strcmp(name, "dimension") || !strcmp(name, "dim") || !strcmp(name, "dimensions") || !strcmp(name, "dims")) { + if(!dimensions) dimensions = buffer_create(100); + buffer_strcat(dimensions, "|"); + buffer_strcat(dimensions, value); + } + else if(!strcmp(name, "after")) after_str = value; + else if(!strcmp(name, "before")) before_str = value; + else if(!strcmp(name, "points")) points_str = value; + else if(!strcmp(name, "gtime")) group_time_str = value; + else if(!strcmp(name, "group")) { + group = web_client_api_request_v1_data_group(value, RRDR_GROUPING_AVERAGE); + } + else if(!strcmp(name, "format")) { + format = web_client_api_request_v1_data_format(value); + } + else if(!strcmp(name, "options")) { + options |= web_client_api_request_v1_data_options(value); + } + else if(!strcmp(name, "callback")) { + responseHandler = value; + } + else if(!strcmp(name, "filename")) { + outFileName = value; + } + else if(!strcmp(name, "tqx")) { + // parse Google Visualization API options + // https://developers.google.com/chart/interactive/docs/dev/implementing_data_source + char *tqx_name, *tqx_value; + + while(value) { + tqx_value = mystrsep(&value, ";"); + if(!tqx_value || !*tqx_value) continue; + + tqx_name = mystrsep(&tqx_value, ":"); + if(!tqx_name || !*tqx_name) continue; + if(!tqx_value || !*tqx_value) continue; + + if(!strcmp(tqx_name, "version")) + google_version = tqx_value; + else if(!strcmp(tqx_name, "reqId")) + google_reqId = tqx_value; + else if(!strcmp(tqx_name, "sig")) { + google_sig = tqx_value; + google_timestamp = strtoul(google_sig, NULL, 0); + } + else if(!strcmp(tqx_name, "out")) { + google_out = tqx_value; + format = web_client_api_request_v1_data_google_format(google_out); + } + else if(!strcmp(tqx_name, "responseHandler")) + responseHandler = tqx_value; + else if(!strcmp(tqx_name, "outFileName")) + outFileName = tqx_value; + } + } + } + + // validate the google parameters given + fix_google_param(google_out); + fix_google_param(google_sig); + fix_google_param(google_reqId); + fix_google_param(google_version); + fix_google_param(responseHandler); + fix_google_param(outFileName); + + if(!chart || !*chart) { + buffer_sprintf(w->response.data, "No chart id is given at the request."); + goto cleanup; + } + + RRDSET *st = rrdset_find(host, chart); + if(!st) st = rrdset_find_byname(host, chart); + if(!st) { + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, chart); + ret = 404; + goto cleanup; + } + st->last_accessed_time = now_realtime_sec(); + + long long before = (before_str && *before_str)?str2l(before_str):0; + long long after = (after_str && *after_str) ?str2l(after_str):0; + int points = (points_str && *points_str)?str2i(points_str):0; + long group_time = (group_time_str && *group_time_str)?str2l(group_time_str):0; + + debug(D_WEB_CLIENT, "%llu: API command 'data' for chart '%s', dimensions '%s', after '%lld', before '%lld', points '%d', group '%d', format '%u', options '0x%08x'" + , w->id + , chart + , (dimensions)?buffer_tostring(dimensions):"" + , after + , before + , points + , group + , format + , options + ); + + if(outFileName && *outFileName) { + buffer_sprintf(w->response.header, "Content-Disposition: attachment; filename=\"%s\"\r\n", outFileName); + debug(D_WEB_CLIENT, "%llu: generating outfilename header: '%s'", w->id, outFileName); + } + + if(format == DATASOURCE_DATATABLE_JSONP) { + if(responseHandler == NULL) + responseHandler = "google.visualization.Query.setResponse"; + + debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSON/JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'", + w->id, google_version, google_reqId, google_sig, google_out, responseHandler, outFileName + ); + + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'ok',sig:'%ld',table:", + responseHandler, google_version, google_reqId, st->last_updated.tv_sec); + } + else if(format == DATASOURCE_JSONP) { + if(responseHandler == NULL) + responseHandler = "callback"; + + buffer_strcat(w->response.data, responseHandler); + buffer_strcat(w->response.data, "("); + } + + ret = rrdset2anything_api_v1(st, w->response.data, dimensions, format, points, after, before, group, group_time + , options, &last_timestamp_in_data); + + if(format == DATASOURCE_DATATABLE_JSONP) { + if(google_timestamp < last_timestamp_in_data) + buffer_strcat(w->response.data, "});"); + + else { + // the client already has the latest data + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, + "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});", + responseHandler, google_version, google_reqId); + } + } + else if(format == DATASOURCE_JSONP) + buffer_strcat(w->response.data, ");"); + + cleanup: + buffer_free(dimensions); + return ret; +} + +// Pings a netdata server: +// /api/v1/registry?action=hello +// +// Access to a netdata registry: +// /api/v1/registry?action=access&machine=${machine_guid}&name=${hostname}&url=${url} +// +// Delete from a netdata registry: +// /api/v1/registry?action=delete&machine=${machine_guid}&name=${hostname}&url=${url}&delete_url=${delete_url} +// +// Search for the URLs of a machine: +// /api/v1/registry?action=search&machine=${machine_guid}&name=${hostname}&url=${url}&for=${machine_guid} +// +// Impersonate: +// /api/v1/registry?action=switch&machine=${machine_guid}&name=${hostname}&url=${url}&to=${new_person_guid} +inline int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0, + hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0, + hash_to = 0 /*, hash_redirects = 0 */; + + if(unlikely(!hash_action)) { + hash_action = simple_hash("action"); + hash_access = simple_hash("access"); + hash_hello = simple_hash("hello"); + hash_delete = simple_hash("delete"); + hash_search = simple_hash("search"); + hash_switch = simple_hash("switch"); + hash_machine = simple_hash("machine"); + hash_url = simple_hash("url"); + hash_name = simple_hash("name"); + hash_delete_url = simple_hash("delete_url"); + hash_for = simple_hash("for"); + hash_to = simple_hash("to"); +/* + hash_redirects = simple_hash("redirects"); +*/ + } + + char person_guid[GUID_LEN + 1] = ""; + + debug(D_WEB_CLIENT, "%llu: API v1 registry with URL '%s'", w->id, url); + + // TODO + // The browser may send multiple cookies with our id + + char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "="); + if(cookie) + strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36); + + char action = '\0'; + char *machine_guid = NULL, + *machine_url = NULL, + *url_name = NULL, + *search_machine_guid = NULL, + *delete_url = NULL, + *to_person_guid = NULL; +/* + int redirects = 0; +*/ + + while(url) { + char *value = mystrsep(&url, "&"); + if (!value || !*value) continue; + + char *name = mystrsep(&value, "="); + if (!name || !*name) continue; + if (!value || !*value) continue; + + debug(D_WEB_CLIENT, "%llu: API v1 registry query param '%s' with value '%s'", w->id, name, value); + + uint32_t hash = simple_hash(name); + + if(hash == hash_action && !strcmp(name, "action")) { + uint32_t vhash = simple_hash(value); + + if(vhash == hash_access && !strcmp(value, "access")) action = 'A'; + else if(vhash == hash_hello && !strcmp(value, "hello")) action = 'H'; + else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D'; + else if(vhash == hash_search && !strcmp(value, "search")) action = 'S'; + else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W'; +#ifdef NETDATA_INTERNAL_CHECKS + else error("unknown registry action '%s'", value); +#endif /* NETDATA_INTERNAL_CHECKS */ + } +/* + else if(hash == hash_redirects && !strcmp(name, "redirects")) + redirects = atoi(value); +*/ + else if(hash == hash_machine && !strcmp(name, "machine")) + machine_guid = value; + + else if(hash == hash_url && !strcmp(name, "url")) + machine_url = value; + + else if(action == 'A') { + if(hash == hash_name && !strcmp(name, "name")) + url_name = value; + } + else if(action == 'D') { + if(hash == hash_delete_url && !strcmp(name, "delete_url")) + delete_url = value; + } + else if(action == 'S') { + if(hash == hash_for && !strcmp(name, "for")) + search_machine_guid = value; + } + else if(action == 'W') { + if(hash == hash_to && !strcmp(name, "to")) + to_person_guid = value; + } +#ifdef NETDATA_INTERNAL_CHECKS + else error("unused registry URL parameter '%s' with value '%s'", name, value); +#endif /* NETDATA_INTERNAL_CHECKS */ + } + + if(unlikely(respect_web_browser_do_not_track_policy && web_client_has_donottrack(w))) { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Your web browser is sending 'DNT: 1' (Do Not Track). The registry requires persistent cookies on your browser to work."); + return 400; + } + + if(unlikely(action == 'H')) { + // HELLO request, dashboard ACL + if(unlikely(!web_client_can_access_dashboard(w))) + return web_client_permission_denied(w); + } + else { + // everything else, registry ACL + if(unlikely(!web_client_can_access_registry(w))) + return web_client_permission_denied(w); + } + + switch(action) { + case 'A': + if(unlikely(!machine_guid || !machine_url || !url_name)) { + error("Invalid registry request - access requires these parameters: machine ('%s'), url ('%s'), name ('%s')", machine_guid ? machine_guid : "UNSET", machine_url ? machine_url : "UNSET", url_name ? url_name : "UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Access request."); + return 400; + } + + web_client_enable_tracking_required(w); + return registry_request_access_json(host, w, person_guid, machine_guid, machine_url, url_name, now_realtime_sec()); + + case 'D': + if(unlikely(!machine_guid || !machine_url || !delete_url)) { + error("Invalid registry request - delete requires these parameters: machine ('%s'), url ('%s'), delete_url ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", delete_url?delete_url:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Delete request."); + return 400; + } + + web_client_enable_tracking_required(w); + return registry_request_delete_json(host, w, person_guid, machine_guid, machine_url, delete_url, now_realtime_sec()); + + case 'S': + if(unlikely(!machine_guid || !machine_url || !search_machine_guid)) { + error("Invalid registry request - search requires these parameters: machine ('%s'), url ('%s'), for ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", search_machine_guid?search_machine_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Search request."); + return 400; + } + + web_client_enable_tracking_required(w); + return registry_request_search_json(host, w, person_guid, machine_guid, machine_url, search_machine_guid, now_realtime_sec()); + + case 'W': + if(unlikely(!machine_guid || !machine_url || !to_person_guid)) { + error("Invalid registry request - switching identity requires these parameters: machine ('%s'), url ('%s'), to ('%s')", machine_guid?machine_guid:"UNSET", machine_url?machine_url:"UNSET", to_person_guid?to_person_guid:"UNSET"); + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry Switch request."); + return 400; + } + + web_client_enable_tracking_required(w); + return registry_request_switch_json(host, w, person_guid, machine_guid, machine_url, to_person_guid, now_realtime_sec()); + + case 'H': + return registry_request_hello_json(host, w); + + default: + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Invalid registry request - you need to set an action: hello, access, delete, search"); + return 400; + } +} + +static inline void web_client_api_request_v1_info_summary_alarm_statuses(RRDHOST *host, BUFFER *wb) { + int alarm_normal = 0, alarm_warn = 0, alarm_crit = 0; + RRDCALC *rc; + rrdhost_rdlock(host); + for(rc = host->alarms; rc ; rc = rc->next) { + if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec)) + continue; + + switch(rc->status) { + case RRDCALC_STATUS_WARNING: + alarm_warn++; + break; + case RRDCALC_STATUS_CRITICAL: + alarm_crit++; + break; + default: + alarm_normal++; + } + } + rrdhost_unlock(host); + buffer_sprintf(wb, "\t\t\"normal\": %d,\n", alarm_normal); + buffer_sprintf(wb, "\t\t\"warning\": %d,\n", alarm_warn); + buffer_sprintf(wb, "\t\t\"critical\": %d\n", alarm_crit); +} + +static inline void web_client_api_request_v1_info_mirrored_hosts(BUFFER *wb) { + RRDHOST *rc; + int count = 0; + rrd_rdlock(); + rrdhost_foreach_read(rc) { + if(count > 0) buffer_strcat(wb, ",\n"); + buffer_sprintf(wb, "\t\t\"%s\"", rc->hostname); + count++; + } + buffer_strcat(wb, "\n"); + rrd_unlock(); +} + +inline int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url) { + (void)url; + + BUFFER *wb = w->response.data; + buffer_flush(wb); + wb->contenttype = CT_APPLICATION_JSON; + + buffer_strcat(wb, "{\n"); + buffer_sprintf(wb, "\t\"version\": \"%s\",\n", host->program_version); + buffer_sprintf(wb, "\t\"uid\": \"%s\",\n", host->machine_guid); + + buffer_strcat(wb, "\t\"mirrored_hosts\": [\n"); + web_client_api_request_v1_info_mirrored_hosts(wb); + buffer_strcat(wb, "\t],\n"); + + buffer_strcat(wb, "\t\"alarms\": {\n"); + web_client_api_request_v1_info_summary_alarm_statuses(host, wb); + buffer_strcat(wb, "\t}\n"); + + buffer_strcat(wb, "}"); + return 200; +} + +static struct api_command { + const char *command; + uint32_t hash; + WEB_CLIENT_ACL acl; + int (*callback)(RRDHOST *host, struct web_client *w, char *url); +} api_commands[] = { + { "info", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_info }, + { "data", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_data }, + { "chart", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_chart }, + { "charts", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_charts }, + + // registry checks the ACL by itself, so we allow everything + { "registry", 0, WEB_CLIENT_ACL_NOCHECK, web_client_api_request_v1_registry }, + + // badges can be fetched with both dashboard and badge permissions + { "badge.svg", 0, WEB_CLIENT_ACL_DASHBOARD|WEB_CLIENT_ACL_BADGE, web_client_api_request_v1_badge }, + + { "alarms", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarms }, + { "alarm_log", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_log }, + { "alarm_variables", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_alarm_variables }, + { "allmetrics", 0, WEB_CLIENT_ACL_DASHBOARD, web_client_api_request_v1_allmetrics }, + { "manage/health", 0, WEB_CLIENT_ACL_MGMT, web_client_api_request_v1_mgmt_health }, + // terminator + { NULL, 0, WEB_CLIENT_ACL_NONE, NULL }, +}; + +inline int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url) { + static int initialized = 0; + int i; + + if(unlikely(initialized == 0)) { + initialized = 1; + + for(i = 0; api_commands[i].command ; i++) + api_commands[i].hash = simple_hash(api_commands[i].command); + } + + // get the command + char *tok = mystrsep(&url, "?"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok); + uint32_t hash = simple_hash(tok); + + for(i = 0; api_commands[i].command ;i++) { + if(unlikely(hash == api_commands[i].hash && !strcmp(tok, api_commands[i].command))) { + if(unlikely(api_commands[i].acl != WEB_CLIENT_ACL_NOCHECK) && !(w->acl & api_commands[i].acl)) + return web_client_permission_denied(w); + + return api_commands[i].callback(host, w, url); + } + } + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Unsupported v1 API command: "); + buffer_strcat_htmlescape(w->response.data, tok); + return 404; + } + else { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Which API v1 command?"); + return 400; + } +} diff --git a/web/api/web_api_v1.h b/web/api/web_api_v1.h new file mode 100644 index 0000000..70b7817 --- /dev/null +++ b/web/api/web_api_v1.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_API_V1_H +#define NETDATA_WEB_API_V1_H 1 + +#include "daemon/common.h" +#include "web/api/badges/web_buffer_svg.h" +#include "web/api/formatters/rrd2json.h" +#include "web/api/health/health_cmdapi.h" + +extern uint32_t web_client_api_request_v1_data_options(char *o); +extern uint32_t web_client_api_request_v1_data_format(char *name); +extern uint32_t web_client_api_request_v1_data_google_format(char *name); + +extern int web_client_api_request_v1_alarms(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_alarm_log(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_single_chart(RRDHOST *host, struct web_client *w, char *url, void callback(RRDSET *st, BUFFER *buf)); +extern int web_client_api_request_v1_alarm_variables(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_chart(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_data(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_registry(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1_info(RRDHOST *host, struct web_client *w, char *url); +extern int web_client_api_request_v1(RRDHOST *host, struct web_client *w, char *url); + +extern void web_client_api_v1_init(void); +extern void web_client_api_v1_management_init(void); + +char *api_secret; + +#endif //NETDATA_WEB_API_V1_H diff --git a/web/gui/.well-known/dnt/cookies b/web/gui/.well-known/dnt/cookies new file mode 100644 index 0000000..b7c70e5 --- /dev/null +++ b/web/gui/.well-known/dnt/cookies @@ -0,0 +1,14 @@ +{
+ "tracking": "T",
+ "compliance": ["https://github.com/netdata/netdata/wiki/cookies#compliance"],
+ "qualifiers": "afc",
+ "controller": ["https://github.com/netdata/netdata/wiki/cookies#controller"],
+ "same-party": [
+ "my-netdata.io",
+ "mynetdata.io",
+ "netdata.online",
+ "netdata.rocks",
+ "registry.my-netdata.io"
+ ],
+ "policy": "https://github.com/netdata/netdata/wiki/cookies#policy",
+}
diff --git a/web/gui/Makefile.am b/web/gui/Makefile.am new file mode 100644 index 0000000..ae8b49f --- /dev/null +++ b/web/gui/Makefile.am @@ -0,0 +1,177 @@ +# +# Copyright (C) 2015 Alon Bar-Lev <alon.barlev@gmail.com> +# SPDX-License-Identifier: GPL-3.0-or-later +# +MAINTAINERCLEANFILES= $(srcdir)/Makefile.in +CLEANFILES = \ + dashboard.js \ + version.txt \ + $(NULL) + +DASHBOARD_JS_FILES = \ + src/dashboard.js/prologue.js.inc \ + src/dashboard.js/utils.js \ + src/dashboard.js/server-detection.js \ + src/dashboard.js/dependencies.js \ + src/dashboard.js/error-handling.js \ + src/dashboard.js/compatibility.js \ + src/dashboard.js/xss.js \ + src/dashboard.js/colors.js \ + src/dashboard.js/units-conversion.js \ + src/dashboard.js/options.js \ + src/dashboard.js/localstorage.js \ + src/dashboard.js/timeout.js \ + src/dashboard.js/themes.js \ + src/dashboard.js/charting/dygraph.js \ + src/dashboard.js/charting/sparkline.js \ + src/dashboard.js/charting/google-charts.js \ + src/dashboard.js/charting/gauge.js \ + src/dashboard.js/charting/easy-pie-chart.js \ + src/dashboard.js/charting/d3pie.js \ + src/dashboard.js/charting/d3.js \ + src/dashboard.js/charting/peity.js \ + src/dashboard.js/charting.js \ + src/dashboard.js/chart-registry.js \ + src/dashboard.js/common.js \ + src/dashboard.js/main.js \ + src/dashboard.js/alarms.js \ + src/dashboard.js/registry.js \ + src/dashboard.js/boot.js \ + src/dashboard.js/epilogue.js.inc \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(DASHBOARD_JS_FILES) \ + $(NULL) + +dist_web_DATA = \ + demo.html \ + demo2.html \ + demosites.html \ + demosites2.html \ + dashboard.html \ + dashboard.js \ + dashboard_info.js \ + dashboard_info_custom_example.js \ + dashboard.css \ + dashboard.slate.css \ + favicon.ico \ + goto-host-from-alarm.html \ + index.html \ + main.css \ + main.js \ + infographic.html \ + robots.txt \ + refresh-badges.js \ + sitemap.xml \ + tv.html \ + version.txt \ + $(NULL) + +weblibdir=$(webdir)/lib +dist_weblib_DATA = \ + lib/bootstrap-3.3.7.min.js \ + lib/bootstrap-slider-10.0.0.min.js \ + lib/bootstrap-table-1.11.0.min.js \ + lib/bootstrap-table-export-1.11.0.min.js \ + lib/bootstrap-toggle-2.2.2.min.js \ + lib/clipboard-polyfill-be05dad.js \ + lib/d3-4.12.2.min.js \ + lib/d3pie-0.2.1-netdata-3.js \ + lib/dygraph-c91c859.min.js \ + lib/dygraph-smooth-plotter-c91c859.js \ + lib/fontawesome-all-5.0.1.min.js \ + lib/gauge-1.3.2.min.js \ + lib/jquery-2.2.4.min.js \ + lib/jquery.easypiechart-97b5824.min.js \ + lib/jquery.peity-3.2.0.min.js \ + lib/jquery.sparkline-2.1.2.min.js \ + lib/lz-string-1.4.4.min.js \ + lib/pako-1.0.6.min.js \ + lib/perfect-scrollbar-0.6.15.min.js \ + lib/tableExport-1.6.0.min.js \ + $(NULL) + +webcssdir=$(webdir)/css +dist_webcss_DATA = \ + css/morris-0.5.1.css \ + css/bootstrap-3.3.7.css \ + css/bootstrap-theme-3.3.7.min.css \ + css/bootstrap-slate-flat-3.3.7.css \ + css/bootstrap-slider-10.0.0.min.css \ + css/bootstrap-toggle-2.2.2.min.css \ + css/c3-0.4.18.min.css \ + $(NULL) + +webfontsdir=$(webdir)/fonts +dist_webfonts_DATA = \ + fonts/glyphicons-halflings-regular.eot \ + fonts/glyphicons-halflings-regular.svg \ + fonts/glyphicons-halflings-regular.ttf \ + fonts/glyphicons-halflings-regular.woff \ + fonts/glyphicons-halflings-regular.woff2 \ + $(NULL) + +webimagesdir=$(webdir)/images +dist_webimages_DATA = \ + images/netdata-logomark.svg \ + images/alert-128-orange.png \ + images/alert-128-red.png \ + images/alert-multi-size-orange.ico \ + images/alert-multi-size-red.ico \ + images/animated.gif \ + images/check-mark-2-128-green.png \ + images/check-mark-2-multi-size-green.ico \ + images/netdata.svg \ + images/post.png \ + images/android-icon-36x36.png \ + images/android-icon-48x48.png \ + images/android-icon-72x72.png \ + images/android-icon-96x96.png \ + images/android-icon-144x144.png \ + images/android-icon-192x192.png \ + images/apple-icon-57x57.png \ + images/apple-icon-60x60.png \ + images/apple-icon-72x72.png \ + images/apple-icon-76x76.png \ + images/apple-icon-114x114.png \ + images/apple-icon-120x120.png \ + images/apple-icon-144x144.png \ + images/apple-icon-152x152.png \ + images/apple-icon-180x180.png \ + images/apple-icon-precomposed.png \ + images/apple-icon.png \ + images/favicon-16x16.png \ + images/favicon-32x32.png \ + images/favicon-96x96.png \ + images/favicon.ico \ + images/ms-icon-70x70.png \ + images/ms-icon-144x144.png \ + images/ms-icon-150x150.png \ + images/ms-icon-310x310.png \ + images/banner-icon-144x144.png \ + $(NULL) + +dashboard.js: $(DASHBOARD_JS_FILES) + if test -f $@; then rm -f $@; fi + cat $(DASHBOARD_JS_FILES) > $@.tmp && mv $@.tmp $@ + +webwellknowndir=$(webdir)/.well-known +dist_webwellknown_DATA = \ + $(NULL) + +webdntdir=$(webdir)/.well-known/dnt +dist_webdnt_DATA = \ + .well-known/dnt/cookies \ + $(NULL) + +version.txt: + if test -d "$(top_srcdir)/.git"; then \ + git --git-dir="$(top_srcdir)/.git" log -n 1 --format=%H; \ + fi > $@.tmp + test -s $@.tmp || echo 0 > $@.tmp + mv $@.tmp $@ + +# regenerate these files, even if they are up to date +.PHONY: version.txt dashboard.js diff --git a/web/gui/README.md b/web/gui/README.md new file mode 100644 index 0000000..9be9ffc --- /dev/null +++ b/web/gui/README.md @@ -0,0 +1,108 @@ +# Netdata agent web GUI + +## Generating dashboard.js + +The monolithic `dashboards.js` file is automatically generated by concatenating the source files located in the `web/gui/src/dashboard.js/` directory by running the build script: + +```sh +cd web/gui +make +``` + +After every change in the `src` directory, the `dashboard.js` file should be regenerated and commited to the repository. + +## Custom Dashboards + +For information on creating custom dashboards, see **[Custom Dashboards](custom/)** and **[Atlassian Confluence Dashboards](confluence/)** + +## Supported chart libraries + +- Dygraph +- jQuery Sparkline +- Peity +- Google Charts +- Morris +- EasyPieChart +- Gauge.js +- D3 +- C3 + +### Dygraph + +#### Settings + +[Example settings here](https://github.com/netdata/netdata/blob/e91f00d99f4965e985981b93fa46ef33f94dd726/web/dashboard.js#L3793) + +#### Value Range + +You can set the min and max values of the y-axis using `data-dygraph-valuerange="[MIN, MAX]"` + +### EasyPieChart + +#### Settings + +TBD + +#### Value Range + +You can set the max value of the chart using the following snippet: +```html +<div data-netdata="unique.id" + data-chart-library="easypiechart" + data-easypiechart-max-value="40" + ></div> +``` +Be aware that values that exceed the max value will get expanded (e.g. "41" is still 100%). Similar for the minimum: +```html +<div data-netdata="unique.id" + data-chart-library="easypiechart" + data-easypiechart-min-value="20" + ></div> +``` +If you specify both minimum and maximum, the rendering behavior changes. Instead of displaying the `value` based from zero, it is now based on the range that is provided by the snippet: +```html +<div data-netdata="unique.id" + data-chart-library="easypiechart" + data-easypiechart-min-value="20" + data-easypiechart-max-value="40" + ></div> +``` +In the first example, a value of `30`, without specifying the minimum, fills the chart bar to `75%` (100% / 40 * 30). However, in this example the range is now `20` (40 - 20 = 20). The value `30` will fill the chart to **`50%`**, since it's in the middle between 20 and 40. + +This szenario is useful if you have metrics that change only within a specific range, e.g. temperatures that are very unlikely to fall out of range. In these cases it is more useful to have the chart render the values between the given min and max, to better highlight the changes within them. + +#### Negative Values + +EasyPieCharts can render negative values with the following flag: +```html +<div data-netdata="unique.id" + data-chart-library="easypiechart" + data-override-options="signed" + ></div> +``` +Negative values are rendered counter-clockwise. + +#### Full example + +This is a chart that displays the hotwater temperature in the given range of 40 to 50. +```html +<div data-netdata="stiebeleltron_system.hotwater.hotwatertemp" + data-title="Hot Water Temperature" + data-decimal-digits="1" + data-chart-library="easypiechart" + data-colors="#FE3912" + data-width="55%" + data-height="50%" + data-points="1200" + data-after="-1200" + data-dimensions="actual" + data-units="°C" + data-easypiechart-max-value="50" + data-easypiechart-min-value="40" + data-common-max="netdata-hotwater-max" + data-common-min="netdata-hotwater-min" +></div> +``` +![hot water chart](https://user-images.githubusercontent.com/12159026/28666665-a7d68ad2-72c8-11e7-9a96-f6bf9691b471.png) + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fgui%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/gui/browserconfig.xml b/web/gui/browserconfig.xml new file mode 100644 index 0000000..32f4759 --- /dev/null +++ b/web/gui/browserconfig.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?> +<browserconfig><msapplication><tile><square70x70logo src="images/ms-icon-70x70.png"/><square150x150logo src="images/ms-icon-150x150.png"/><square310x310logo src="images/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig> diff --git a/web/gui/confluence/README.md b/web/gui/confluence/README.md new file mode 100644 index 0000000..3d7eda6 --- /dev/null +++ b/web/gui/confluence/README.md @@ -0,0 +1,1014 @@ +# Atlassian Confluence dashboards + +With netdata you can build **live, interactive, monitoring dashboards** directly on Atlassian's **Confluence** pages. + +I see you already asking "why should I do this?" + +Well... think a bit of it.... confluence is the perfect place for something like that: + +1. All the employees of your company already have access to it. + +2. Most probably you have already several spaces on confluence, one for each project or service. Adding live monitoring information there is ideal: everything in one place. Your users will just click on the page and instantly the monitoring page they need will appear with only the information they need to know. + +3. You can create monitoring pages for very specific purposes, hiding all the information that is too detailed for most users, or explaining in detail things that are difficult for them to understand. + +So, what can we expect? What can netdata do on confluence? + +You will be surprised! **Everything a netdata dashboard does!**. Example: + +![final-confluence4](https://user-images.githubusercontent.com/2662304/34366214-767fa4b8-eaa1-11e7-83af-0b9b9b72aa73.gif) + +Let me show you how. + +> Let's assume we have 2 web servers we want to monitor. We will create a simple dashboard with key information about them, directly on confluence. + +### Before you begin + +Most likely your confluence is accessible via HTTPS. So, you need to proxy your netdata servers via an apache or nginx to make them HTTPS too. If your Confluence is HTTPS but your netdata are not, you will not be able to fetch the netdata content from the confluence page. The netdata wiki has many examples for proxying netdata through another web server. + +> So, make sure netdata and confluence can be accessed with the same protocol (**http**, or **https**). + +For our example, I will use these 2 servers: + +server|url +----|---- +Server 1 | https://london.my-netdata.io +Server 2 | https://frankfurt.my-netdata.io + +I will use the first server for the static dashboard javascript files. + +--- + +Then, you need to enable the `html` plugin of confluence. We will add some plain html content on that page, and this plugin is required. + +### Create a new page + +Create a new confluence page and paste this into an `html` box: + +```html +<script> +// don't load bootstrap - confluence does not need this +var netdataNoBootstrap = true; + +// select the web notifications to show on this dashboard +// var netdataShowAlarms = true; +// var netdataAlarmsRecipients = [ 'sysadmin', 'webmaster' ]; +</script> + +<script src="https://london.my-netdata.io/dashboard.js"></script> +``` + +like this (type `{html` for the html box to appear - you need the confluence html plugin enabled): + +![screenshot from 2017-12-25 00-46-20](https://user-images.githubusercontent.com/2662304/34329541-1dd9077c-e90d-11e7-988d-6820be31ff3f.png) + +### Add a few badges + +Then, go to your netdata and copy an alarm badge (the `<embed>` version of it): + +![copy-embed-badge](https://user-images.githubusercontent.com/2662304/34329562-dddea37e-e90d-11e7-9830-041a9f6a5984.gif) + +Then add another HTML box on the page, and paste it, like this: + +![screenshot from 2017-12-25 00-55-18](https://user-images.githubusercontent.com/2662304/34329569-4fc3d07c-e90e-11e7-8127-3127a21e1657.png) + +Hit **update** and you will get this: + +![screenshot from 2017-12-25 00-56-58](https://user-images.githubusercontent.com/2662304/34329573-8d4237cc-e90e-11e7-80bf-6c260456c690.png) + +This badge is now auto-refreshing. It will update itself based on the update frequency of the alarm. + +> Keep in mind you can add badges with custom netdata queries too. netdata automatically creates badges for all the alarms, but every chart, every dimension on every chart, can be used for a badge. And netdata badges are quite powerful! Check [Creating Badges](../../api/badges/) for more information on badges. + +So, let's create a table and add this badge for both our web servers: + +![screenshot from 2017-12-25 01-06-10](https://user-images.githubusercontent.com/2662304/34329609-d3e9ab00-e90f-11e7-99df-884196347538.png) + +Now we get this: + +![screenshot from 2017-12-25 01-07-10](https://user-images.githubusercontent.com/2662304/34329615-f7dea286-e90f-11e7-9b6f-600215494f96.png) + +### Add a netdata chart + +The simplest form of a chart is this (it adds the chart `web_log_nginx_netdata.response_statuses`, using 100% of the width, 150px height, and the last 10 minutes of data): + +```html +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-width="100%" + data-height="150px" + data-before="0" + data-after="-600" +></div> +``` + +Add this to `html` block on confluence: + +![screenshot from 2017-12-25 01-13-15](https://user-images.githubusercontent.com/2662304/34329635-cf83ab0a-e910-11e7-85a3-b72ccc2d54e4.png) + +And you will get this: + +![screenshot from 2017-12-25 01-14-09](https://user-images.githubusercontent.com/2662304/34329640-efd15574-e910-11e7-9004-94487dcde154.png) + +> This chart is **alive**, fully interactive. You can drag it, pan it, zoom it, etc like you do on netdata dashboards! + +Of course this too big. We need something smaller to add inside the table. Let's try this: + +```html +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +></div> +``` + +The chart name is shown on all netdata charts, so just copy it from a netdata dashboard. + +We will fetch the same chart from both servers. To define the server we also added `data-host=` with the URL of each server, like this (we also added `<br/>` for a newline between the badge and the chart): + +![screenshot from 2017-12-25 01-25-05](https://user-images.githubusercontent.com/2662304/34329695-76fd2680-e912-11e7-9969-87f8d5b36145.png) + +Which gives us this: + +![screenshot from 2017-12-25 01-26-04](https://user-images.githubusercontent.com/2662304/34329700-989f0f2e-e912-11e7-8ac9-c78f82cfbdb0.png) + +Note the color difference. This is because netdata automatically hides dimensions that are just zero (the frankfurt server has only successful requests). To instruct netdata to disable this feature, we need to add another html fragment at the bottom of the page (make sure this is added after loading `dashboard.js`). So we edit the first block we added, and append a new `<script>` section to it: + + +```html +<script> +// don't load bootstrap - confluence does not need this +var netdataNoBootstrap = true; + +// select the web notifications to show on this dashboard +// var netdataShowAlarms = true; +// var netdataAlarmsRecipients = [ 'sysadmin', 'webmaster' ]; +</script> + +<script src="https://london.my-netdata.io/dashboard.js"></script> + +<script> +// do not hide dimensions with just zeros +NETDATA.options.current.eliminate_zero_dimensions = false; +</script> +``` + +Now they match: + +![screenshot from 2017-12-25 01-30-14](https://user-images.githubusercontent.com/2662304/34329716-2ea83680-e913-11e7-847e-52b3f402aeb0.png) + +#### more options + +If you want to change the colors append `data-colors="#001122 #334455 #667788"`. The colors will be used for the dimensions top to bottom, as shown on a netdata dashboard. Keep in mind the default netdata dashboards hide by default all dimensions that are just zero, so enable them at the dashboard settings to see them all. + +You can get a percentage chart, by adding these on these charts: + +```html + data-append-options="percentage" + data-decimal-digits="0" + data-dygraph-valuerange="[0, 100]" + data-dygraph-includezero="true" + data-units="%" +``` + +The first line instructs netdata to calculate the percentage of each dimension, the second strips any fractional digits, the third instructs the charting library to size the chart from 0 to 100, the next one instructs it to include 0 in the chart and the last changes the units of the chart to `%`. This is how it will look: + +![screenshot from 2017-12-25 01-45-39](https://user-images.githubusercontent.com/2662304/34329774-570ef990-e915-11e7-899f-eee939564aaf.png) + +You can make any number of charts have common min and max on the y-range by adding `common-min="NAME"` and `common-max="NAME"`, where `NAME` is anything you like. Keep in mind for best results all the charts with the same `NAME` should be visible at once, otherwise a not-visible chart will influence the range and until it is updated the range will not adapt. + +### Add gauges + +Let's now add a few gauges. The chart we added has several dimensions: `success`, `error`, `redirect`, `bad` and `other`. + +Let's say we want to add 2 gauges: + +1. `success` and `redirect` together, in blue +2. `error`, `bad` and `other` together, in orange + +We will add the following for each server. We have enclosed them in another a `<div>` because Confluence will wrap them if the page width is not enough to fit them. With that additional `<div>` they will always be next to each other. + +```html +<div style="width: 300px; text-align: center;"> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-dimensions="success,redirect" + data-chart-library="gauge" + data-title="Good" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-600" + data-points="600" + data-common-max="response_statuses" + data-colors="#007ec6" + data-decimal-digits="0" + ></div><div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-dimensions="error,bad,other" + data-chart-library="gauge" + data-title="Bad" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-600" + data-points="600" + data-common-max="response_statuses" + data-colors="#97CA00" + data-decimal-digits="0" + ></div> +</div> +``` + +Adding the above will give you this: + +![final-confluence](https://user-images.githubusercontent.com/2662304/34329813-636bb8de-e917-11e7-8cc7-19e197859008.gif) + + +### Final source - for the confluence source editor + +If you enable the source editor of Confluence, you can paste the whole example (implementing the first image on this post and demonstrating everything discussed on this page): + +```html +<p class="auto-cursor-target">Monitoring the health of the web servers, by analyzing the response codes they send.</p> +<table> + <colgroup> + <col/> + <col/> + <col/> + <col/> + <col/> + </colgroup> + <tbody> + <tr> + <th style="text-align: center;"> + <br/> + </th> + <th style="text-align: center;">London</th> + <th style="text-align: center;">Frankfurt</th> + <th colspan="1" style="text-align: center;">San Francisco</th> + <th colspan="1" style="text-align: center;">Toronto</th> + </tr> + <tr> + <td colspan="1" style="text-align: right;"> + <strong>last hour</strong> + <br/> + <strong>requests</strong> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="5771a1db-b461-478f-a820-edcb67809eb1" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-chart-library="easypiechart" + data-after="-14400" + data-before="0" + data-points="4" + data-title="london" + data-method="sum" + data-append-options="unaligned" + data-update-every="60" + data-width="120px" + data-common-max="1h_requests_pie" + data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="aff4446a-1432-407b-beb0-488c33eced18" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://frankfurt.my-netdata.io" + data-chart-library="easypiechart" + data-after="-14400" + data-before="0" + data-points="4" + data-title="frankfurt" + data-method="sum" + data-append-options="unaligned" + data-update-every="60" + data-width="120px" + data-common-max="1h_requests_pie" + data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="fd310534-627c-47bd-a184-361eb3f00489" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://sanfrancisco.my-netdata.io" + data-chart-library="easypiechart" + data-after="-14400" + data-before="0" + data-points="4" + data-title="sanfrancisco" + data-method="sum" + data-append-options="unaligned" + data-update-every="60" + data-width="120px" + data-common-max="1h_requests_pie" + data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="eb1261d5-8ff2-4a5c-8945-701bf04fb75b" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://toronto.my-netdata.io" + data-chart-library="easypiechart" + data-after="-14400" + data-before="0" + data-points="4" + data-title="toronto" + data-method="sum" + data-append-options="unaligned" + data-update-every="60" + data-width="120px" + data-common-max="1h_requests_pie" + data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + </tr> + <tr> + <td colspan="1" style="text-align: right;"> + <strong>last<br/>1 hour</strong> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="d2ee8425-2c6c-4e26-8c5a-17f6153fdce1" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://london.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" +data-dygraph-xpixelsperlabel="30" +data-dygraph-xaxislabelwidth="26" + data-after="-3600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="1h_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="b3fb482a-4e9e-4b69-bb0b-9885d1687334" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://frankfurt.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" +data-dygraph-xpixelsperlabel="30" +data-dygraph-xaxislabelwidth="26" + data-after="-3600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="1h_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="199b1618-64be-4614-9662-f84cd01c6d8d" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://sanfrancisco.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" +data-dygraph-xpixelsperlabel="30" +data-dygraph-xaxislabelwidth="26" + data-after="-3600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="1h_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="61b2d444-fb2b-42e0-b4eb-611fb37dcb66" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://toronto.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" +data-dygraph-xpixelsperlabel="30" +data-dygraph-xaxislabelwidth="26" + data-after="-3600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="1h_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + </tr> + <tr> + <td colspan="1" style="text-align: right;"> + <strong>last 10<br/>minutes</strong> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="f29e7663-f2e6-4e1d-a090-38704e0f2bd3" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://london.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="10m_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="245ccc90-1505-430b-ba13-15e6a9793c11" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://frankfurt.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="10m_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="864ff17f-f372-47e4-9d57-54e44b142240" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://sanfrancisco.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="10m_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="e0072f2b-0169-4ecf-8ddf-724270d185b8" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://toronto.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-600" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" +data-common-max="10m_requests" +data-decimal-digits="0" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + </tr> + <tr> + <td style="text-align: right;"> + <strong>last 1<br/>minute</strong> + </td> + <td style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="8c041cfb-a5a0-425c-afe6-207f4986cb26" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<embed src="https://london.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx_netdata.response_statuses&alarm=1m_successful&refresh=auto&label=1m%20london%20successful%20requests" type="image/svg+xml" height="20"/> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://london.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-60" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" + data-append-options="percentage" + data-decimal-digits="0" + data-dygraph-valuerange="[0, 100]" + data-dygraph-includezero="true" + data-units="%" +data-dimensions="success" +data-colors="#009900" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="a3777583-9919-4997-891c-94a8cec60604" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<embed src="https://frankfurt.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx_netdata.response_statuses&alarm=1m_successful&refresh=auto&label=1m%20frankfurt%20successful%20requests" type="image/svg+xml" height="20"/> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://frankfurt.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-60" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" + data-append-options="percentage" + data-decimal-digits="0" + data-dygraph-valuerange="[0, 100]" + data-dygraph-includezero="true" + data-units="%" +data-dimensions="success" +data-colors="#009900" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="e003deba-82fa-4aec-8264-6cb7d814a299" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<embed src="https://sanfrancisco.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx_netdata.response_statuses&alarm=1m_successful&refresh=auto&label=1m%20sanfrancisco%20successful%20requests" type="image/svg+xml" height="20"/> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://sanfrancisco.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-60" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" + data-append-options="percentage" + data-decimal-digits="0" + data-dygraph-valuerange="[0, 100]" + data-dygraph-includezero="true" + data-units="%" +data-dimensions="success" +data-colors="#009900" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: center;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="046fcda5-98db-4776-8c51-3981d0e68f38" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<embed src="https://toronto.my-netdata.io/api/v1/badge.svg?chart=web_log_nginx_netdata.response_statuses&alarm=1m_successful&refresh=auto&label=1m%20toronto%20successful%20requests" type="image/svg+xml" height="20"/> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" +data-host="https://toronto.my-netdata.io" + data-legend="false" + data-dygraph-yaxislabelwidth="35" + data-dygraph-ypixelsperlabel="8" + data-after="-60" + data-before="0" + data-title="" + data-height="100px" + data-width="300px" + data-append-options="percentage" + data-decimal-digits="0" + data-dygraph-valuerange="[0, 100]" + data-dygraph-includezero="true" + data-units="%" +data-dimensions="success" +data-colors="#009900" +></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + </tr> + <tr> + <td colspan="1" style="text-align: right;"> + <strong>now</strong> + </td> + <td colspan="1" style="text-align: left;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="4aef31d3-9439-439b-838d-7350a26bde5f" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div style="width: 300px; text-align: center;"> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-dimensions="success" + data-chart-library="gauge" + data-title="Success" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#009900" + data-decimal-digits="0" + ></div><div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-dimensions="redirect,error,bad,other" + data-chart-library="gauge" + data-title="All Others" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#fe7d37" + data-decimal-digits="0" + ></div> +</div> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://london.my-netdata.io" + data-dygraph-theme="sparkline" + data-width="300" + data-height="20" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="1m_requests_sparkline" + ></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1" style="text-align: left;"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="bf9fb1c4-ceaf-4ad8-972e-a64d23eb48f8" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div style="width: 300px; text-align: center;"> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://frankfurt.my-netdata.io" + data-dimensions="success" + data-chart-library="gauge" + data-title="Success" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#009900" + data-decimal-digits="0" + ></div><div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://frankfurt.my-netdata.io" + data-dimensions="redirect,error,bad,other" + data-chart-library="gauge" + data-title="All Others" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#fe7d37" + data-decimal-digits="0" + ></div> +</div> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://frankfurt.my-netdata.io" + data-dygraph-theme="sparkline" + data-width="300" + data-height="20" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="1m_requests_sparkline" + ></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="60b4c9bc-353a-4e64-b7c8-365ae74156c4" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div style="width: 300px; text-align: center;"> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://sanfrancisco.my-netdata.io" + data-dimensions="success" + data-chart-library="gauge" + data-title="Success" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#009900" + data-decimal-digits="0" + ></div><div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://sanfrancisco.my-netdata.io" + data-dimensions="redirect,error,bad,other" + data-chart-library="gauge" + data-title="All Others" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#fe7d37" + data-decimal-digits="0" + ></div> +</div> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://sanfrancisco.my-netdata.io" + data-dygraph-theme="sparkline" + data-width="300" + data-height="20" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="1m_requests_sparkline" + ></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + <td colspan="1"> + <div class="content-wrapper"> + <p class="auto-cursor-target"> + <br/> + </p> + <ac:structured-macro ac:macro-id="75e03235-9681-4aaf-bd85-b0ffbb9e3602" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<div style="width: 300px; text-align: center;"> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://toronto.my-netdata.io" + data-dimensions="success" + data-chart-library="gauge" + data-title="Success" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#009900" + data-decimal-digits="0" + ></div><div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://toronto.my-netdata.io" + data-dimensions="redirect,error,bad,other" + data-chart-library="gauge" + data-title="All Others" + data-units="requests/s" + data-gauge-adjust="width" + data-width="120" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="response_statuses" + data-colors="#fe7d37" + data-decimal-digits="0" + ></div> +</div> +<br/> +<div + data-netdata="web_log_nginx_netdata.response_statuses" + data-host="https://toronto.my-netdata.io" + data-dygraph-theme="sparkline" + data-width="300" + data-height="20" + data-before="0" + data-after="-60" + data-points="60" + data-common-max="1m_requests_sparkline" + ></div>]]></ac:plain-text-body> + </ac:structured-macro> + <p class="auto-cursor-target"> + <br/> + </p> + </div> + </td> + </tr> + </tbody> +</table> +<p class="auto-cursor-target"> + <br/> +</p> +<p> + <br/> +</p> +<ac:structured-macro ac:macro-id="10bbb1a6-cd65-4a27-9b3a-cb86a5a0ebe1" ac:name="html" ac:schema-version="1"> + <ac:plain-text-body><![CDATA[<script> +// don't load bootstrap - confluence does not need this +var netdataNoBootstrap = true; + +// select the web notifications to show on this dashboard +// var netdataShowAlarms = true; +// var netdataAlarmsRecipients = [ 'sysadmin', 'webmaster' ]; +</script> + +<script src="https://london.my-netdata.io/dashboard.js"></script> + + +<script> +// do not hide dimensions with just zeros +NETDATA.options.current.eliminate_zero_dimensions = false; +</script>]]></ac:plain-text-body> +</ac:structured-macro> +<p class="auto-cursor-target"> + <br/> +</p> +<div> + <span style="color: rgb(52,52,52);font-family: "Source Code Pro" , monospace;font-size: 16.2px;white-space: pre-wrap;background-color: rgb(252,252,252);"> + <br/> + </span> +</div> +<div> + <span style="color: rgb(52,52,52);font-family: "Source Code Pro" , monospace;font-size: 16.2px;white-space: pre-wrap;background-color: rgb(252,252,252);"> + <br/> + </span> +</div> +``` + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fgui%2Fconfluence%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/gui/css/bootstrap-3.3.7.css b/web/gui/css/bootstrap-3.3.7.css new file mode 100644 index 0000000..8c4db1f --- /dev/null +++ b/web/gui/css/bootstrap-3.3.7.css @@ -0,0 +1,6758 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * SPDX-License-Identifier: MIT + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover, +a.text-primary:focus { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover, +a.text-success:focus { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover, +a.text-info:focus { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover, +a.text-warning:focus { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover, +a.text-danger:focus { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 46px; + line-height: 46px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:focus, +.btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; +} +.btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:focus, +.btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; +} +.btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:focus, +.btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; +} +.btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #fff; + background-color: #398439; + border-color: #255625; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:focus, +.btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; +} +.btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:focus, +.btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; +} +.btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:focus, +.btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; +} +.btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: middle; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + padding-right: 15px; + padding-left: 15px; + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success, +button.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info, +button.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + filter: alpha(opacity=0); + opacity: 0; + + line-break: auto; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-style: normal; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + + line-break: auto; +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + background-color: rgba(0, 0, 0, 0); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; + margin-top: -10px; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +/*# sourceMappingURL=bootstrap.css.map */ diff --git a/web/gui/css/bootstrap-slate-flat-3.3.7.css b/web/gui/css/bootstrap-slate-flat-3.3.7.css new file mode 100644 index 0000000..7ce384f --- /dev/null +++ b/web/gui/css/bootstrap-slate-flat-3.3.7.css @@ -0,0 +1,7101 @@ +/*! + * bootswatch v3.3.7 + * Homepage: http://bootswatch.com + * Copyright 2012-2016 Thomas Park + * Licensed under MIT + * SPDX-License-Identifier: MIT + * Based on Bootstrap +*/ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ +html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + font-size: 2em; + margin: 0.67em 0; +} +mark { + background: #ff0; + color: #000; +} +small { + font-size: 80%; +} +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sup { + top: -0.5em; +} +sub { + bottom: -0.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + color: inherit; + font: inherit; + margin: 0; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} +legend { + border: 0; + padding: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-collapse: collapse; + border-spacing: 0; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + text-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\002a"; +} +.glyphicon-plus:before { + content: "\002b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #c8c8c8; + background-color: #272b30; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #ffffff; + text-decoration: none; +} +a:hover, +a:focus { + color: #ffffff; + text-decoration: underline; +} +a:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + padding: 4px; + line-height: 1.42857143; + background-color: #1c1e22; + border: 1px solid #0c0d0e; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #1c1e22; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #7a8288; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + background-color: #f89406; + padding: .2em; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #7a8288; +} +.text-primary { + color: #7a8288; +} +a.text-primary:hover, +a.text-primary:focus { + color: #62686d; +} +.text-success { + color: #ffffff; +} +a.text-success:hover, +a.text-success:focus { + color: #e6e6e6; +} +.text-info { + color: #ffffff; +} +a.text-info:hover, +a.text-info:focus { + color: #e6e6e6; +} +.text-warning { + color: #ffffff; +} +a.text-warning:hover, +a.text-warning:focus { + color: #e6e6e6; +} +.text-danger { + color: #ffffff; +} +a.text-danger:hover, +a.text-danger:focus { + color: #e6e6e6; +} +.bg-primary { + color: #fff; + background-color: #7a8288; +} +a.bg-primary:hover, +a.bg-primary:focus { + background-color: #62686d; +} +.bg-success { + background-color: #62c462; +} +a.bg-success:hover, +a.bg-success:focus { + background-color: #42b142; +} +.bg-info { + background-color: #5bc0de; +} +a.bg-info:hover, +a.bg-info:focus { + background-color: #31b0d5; +} +.bg-warning { + background-color: #f89406; +} +a.bg-warning:hover, +a.bg-warning:focus { + background-color: #c67605; +} +.bg-danger { + background-color: #ee5f5b; +} +a.bg-danger:hover, +a.bg-danger:focus { + background-color: #e9322d; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #1c1e22; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; +} +.list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #7a8288; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #7a8288; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #7a8288; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #7a8288; + border-left: 0; + text-align: right; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #ffffff; + background-color: #333333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + word-break: break-all; + word-wrap: break-word; + color: #3a3f44; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; +} +.row { + margin-left: -15px; + margin-right: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0%; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0%; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0%; + } +} +table { + background-color: #2e3338; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #7a8288; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #1c1e22; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #1c1e22; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #1c1e22; +} +.table .table { + background-color: #272b30; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #1c1e22; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #1c1e22; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #353a41; +} +.table-hover > tbody > tr:hover { + background-color: #49515a; +} +table col[class*="col-"] { + position: static; + float: none; + display: table-column; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + float: none; + display: table-cell; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #49515a; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #3e444c; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #62c462; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #4fbd4f; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #5bc0de; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #46b8da; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #f89406; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #df8505; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #ee5f5b; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ec4844; +} +.table-responsive { + overflow-x: auto; + min-height: 0.01%; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #1c1e22; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #c8c8c8; + border: 0; + border-bottom: 1px solid #1c1e22; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 9px; + font-size: 14px; + line-height: 1.42857143; + color: #272b30; +} +.form-control { + display: block; + width: 100%; + height: 38px; + padding: 8px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #272b30; + background-color: #ffffff; + background-image: none; + border: 1px solid #000000; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6); +} +.form-control::-moz-placeholder { + color: #7a8288; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #7a8288; +} +.form-control::-webkit-input-placeholder { + color: #7a8288; +} +.form-control::-ms-expand { + border: 0; + background-color: transparent; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #999999; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"].form-control, + input[type="time"].form-control, + input[type="datetime-local"].form-control, + input[type="month"].form-control { + line-height: 38px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 54px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + padding-top: 9px; + padding-bottom: 9px; + margin-bottom: 0; + min-height: 34px; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-left: 0; + padding-right: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.form-group-sm select.form-control { + height: 30px; + line-height: 30px; +} +.form-group-sm textarea.form-control, +.form-group-sm select[multiple].form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 54px; + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 54px; + line-height: 54px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 54px; + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.form-group-lg select.form-control { + height: 54px; + line-height: 54px; +} +.form-group-lg textarea.form-control, +.form-group-lg select[multiple].form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 54px; + min-height: 38px; + padding: 15px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 47.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 38px; + height: 38px; + line-height: 38px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { + width: 54px; + height: 54px; + line-height: 54px; +} +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #ffffff; +} +.has-success .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-success .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-success .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #62c462; +} +.has-success .form-control-feedback { + color: #ffffff; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #ffffff; +} +.has-warning .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-warning .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-warning .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #f89406; +} +.has-warning .form-control-feedback { + color: #ffffff; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #ffffff; +} +.has-error .form-control { + border-color: #ffffff; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} +.has-error .form-control:focus { + border-color: #e6e6e6; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ffffff; +} +.has-error .input-group-addon { + color: #ffffff; + border-color: #ffffff; + background-color: #ee5f5b; +} +.has-error .form-control-feedback { + color: #ffffff; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #ffffff; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 9px; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 29px; +} +.form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 9px; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 15px; + font-size: 18px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; + } +} +.btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 0px solid transparent; + white-space: nowrap; + padding: 8px 12px; + font-size: 14px; + line-height: 1.42857143; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #ffffff; + text-decoration: none; +} +.btn:active, +.btn.active { + outline: 0; + background-image: none; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} +a.btn.disabled, +fieldset[disabled] a.btn { + pointer-events: none; +} +.btn-default { + color: #ffffff; + background-color: #3a3f44; + border-color: #3a3f44; +} +.btn-default:focus, +.btn-default.focus { + color: #ffffff; + background-color: #232628; + border-color: #000000; +} +.btn-default:hover { + color: #ffffff; + background-color: #232628; + border-color: #1e2023; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #ffffff; + background-color: #232628; + border-color: #1e2023; +} +.btn-default:active:hover, +.btn-default.active:hover, +.open > .dropdown-toggle.btn-default:hover, +.btn-default:active:focus, +.btn-default.active:focus, +.open > .dropdown-toggle.btn-default:focus, +.btn-default:active.focus, +.btn-default.active.focus, +.open > .dropdown-toggle.btn-default.focus { + color: #ffffff; + background-color: #121415; + border-color: #000000; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus { + background-color: #3a3f44; + border-color: #3a3f44; +} +.btn-default .badge { + color: #3a3f44; + background-color: #ffffff; +} +.btn-primary { + color: #ffffff; + background-color: #7a8288; + border-color: #7a8288; +} +.btn-primary:focus, +.btn-primary.focus { + color: #ffffff; + background-color: #62686d; + border-color: #3e4245; +} +.btn-primary:hover { + color: #ffffff; + background-color: #62686d; + border-color: #5d6368; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #62686d; + border-color: #5d6368; +} +.btn-primary:active:hover, +.btn-primary.active:hover, +.open > .dropdown-toggle.btn-primary:hover, +.btn-primary:active:focus, +.btn-primary.active:focus, +.open > .dropdown-toggle.btn-primary:focus, +.btn-primary:active.focus, +.btn-primary.active.focus, +.open > .dropdown-toggle.btn-primary.focus { + color: #ffffff; + background-color: #51565a; + border-color: #3e4245; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus { + background-color: #7a8288; + border-color: #7a8288; +} +.btn-primary .badge { + color: #7a8288; + background-color: #ffffff; +} +.btn-success { + color: #ffffff; + background-color: #62c462; + border-color: #62c462; +} +.btn-success:focus, +.btn-success.focus { + color: #ffffff; + background-color: #42b142; + border-color: #2d792d; +} +.btn-success:hover { + color: #ffffff; + background-color: #42b142; + border-color: #40a940; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #42b142; + border-color: #40a940; +} +.btn-success:active:hover, +.btn-success.active:hover, +.open > .dropdown-toggle.btn-success:hover, +.btn-success:active:focus, +.btn-success.active:focus, +.open > .dropdown-toggle.btn-success:focus, +.btn-success:active.focus, +.btn-success.active.focus, +.open > .dropdown-toggle.btn-success.focus { + color: #ffffff; + background-color: #399739; + border-color: #2d792d; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus { + background-color: #62c462; + border-color: #62c462; +} +.btn-success .badge { + color: #62c462; + background-color: #ffffff; +} +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #5bc0de; +} +.btn-info:focus, +.btn-info.focus { + color: #ffffff; + background-color: #31b0d5; + border-color: #1f7e9a; +} +.btn-info:hover { + color: #ffffff; + background-color: #31b0d5; + border-color: #2aabd2; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #31b0d5; + border-color: #2aabd2; +} +.btn-info:active:hover, +.btn-info.active:hover, +.open > .dropdown-toggle.btn-info:hover, +.btn-info:active:focus, +.btn-info.active:focus, +.open > .dropdown-toggle.btn-info:focus, +.btn-info:active.focus, +.btn-info.active.focus, +.open > .dropdown-toggle.btn-info.focus { + color: #ffffff; + background-color: #269abc; + border-color: #1f7e9a; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus { + background-color: #5bc0de; + border-color: #5bc0de; +} +.btn-info .badge { + color: #5bc0de; + background-color: #ffffff; +} +.btn-warning { + color: #ffffff; + background-color: #f89406; + border-color: #f89406; +} +.btn-warning:focus, +.btn-warning.focus { + color: #ffffff; + background-color: #c67605; + border-color: #7c4a03; +} +.btn-warning:hover { + color: #ffffff; + background-color: #c67605; + border-color: #bc7005; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #c67605; + border-color: #bc7005; +} +.btn-warning:active:hover, +.btn-warning.active:hover, +.open > .dropdown-toggle.btn-warning:hover, +.btn-warning:active:focus, +.btn-warning.active:focus, +.open > .dropdown-toggle.btn-warning:focus, +.btn-warning:active.focus, +.btn-warning.active.focus, +.open > .dropdown-toggle.btn-warning.focus { + color: #ffffff; + background-color: #a36104; + border-color: #7c4a03; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus { + background-color: #f89406; + border-color: #f89406; +} +.btn-warning .badge { + color: #f89406; + background-color: #ffffff; +} +.btn-danger { + color: #ffffff; + background-color: #ee5f5b; + border-color: #ee5f5b; +} +.btn-danger:focus, +.btn-danger.focus { + color: #ffffff; + background-color: #e9322d; + border-color: #b71713; +} +.btn-danger:hover { + color: #ffffff; + background-color: #e9322d; + border-color: #e82924; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #e9322d; + border-color: #e82924; +} +.btn-danger:active:hover, +.btn-danger.active:hover, +.open > .dropdown-toggle.btn-danger:hover, +.btn-danger:active:focus, +.btn-danger.active:focus, +.open > .dropdown-toggle.btn-danger:focus, +.btn-danger:active.focus, +.btn-danger.active.focus, +.open > .dropdown-toggle.btn-danger.focus { + color: #ffffff; + background-color: #dc1c17; + border-color: #b71713; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus { + background-color: #ee5f5b; + border-color: #ee5f5b; +} +.btn-danger .badge { + color: #ee5f5b; + background-color: #ffffff; +} +.btn-link { + color: #ffffff; + font-weight: normal; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #ffffff; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #7a8288; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + -o-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-top: 4px solid \9; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + list-style: none; + font-size: 14px; + text-align: left; + background-color: #3a3f44; + border: 1px solid #272b30; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + -webkit-background-clip: padding-box; + background-clip: padding-box; +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #272b30; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #c8c8c8; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + text-decoration: none; + color: #ffffff; + background-color: #272b30; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + outline: 0; + background-color: #272b30; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #7a8288; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + left: auto; + right: 0; +} +.dropdown-menu-left { + left: 0; + right: auto; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #7a8288; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + left: auto; + right: 0; + } + .navbar-right .dropdown-menu-left { + left: 0; + right: auto; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn, +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-top-left-radius: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group .form-control:focus { + z-index: 3; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 54px; + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 54px; + line-height: 54px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 8px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #272b30; + text-align: center; + background-color: #3a3f44; + border: 1px solid rgba(0, 0, 0, 0.6); + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 14px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; +} +.nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #3e444c; +} +.nav > li.disabled > a { + color: #7a8288; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #7a8288; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #3e444c; + border-color: #ffffff; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #1c1e22; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #1c1e22 #1c1e22 #1c1e22; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #ffffff; + background-color: #3e444c; + border: 1px solid #1c1e22; + border-bottom-color: transparent; + cursor: default; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #1c1e22; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #1c1e22; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #272b30; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: transparent; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + text-align: center; + margin-bottom: 5px; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #1c1e22; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #1c1e22; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #272b30; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-left: 0; + padding-right: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + margin-right: 15px; + padding: 9px 10px; + margin-top: 8px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + margin-left: -15px; + margin-right: -15px; + padding: 10px 15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + margin-top: 6px; + margin-bottom: 6px; +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + border: 0; + margin-left: 0; + margin-right: 0; + padding-top: 0; + padding-bottom: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 6px; + margin-bottom: 6px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #3a3f44; + border-color: #2b2e32; +} +.navbar-default .navbar-brand { + color: #c8c8c8; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #ffffff; + background-color: none; +} +.navbar-default .navbar-text { + color: #c8c8c8; +} +.navbar-default .navbar-nav > li > a { + color: #c8c8c8; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #ffffff; + background-color: #272b2e; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #272b2e; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #272b2e; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #272b2e; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #c8c8c8; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #2b2e32; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + background-color: #272b2e; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #c8c8c8; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: #272b2e; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #272b2e; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #c8c8c8; +} +.navbar-default .navbar-link:hover { + color: #ffffff; +} +.navbar-default .btn-link { + color: #c8c8c8; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #ffffff; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #cccccc; +} +.navbar-inverse { + background-color: #7a8288; + border-color: #62686d; +} +.navbar-inverse .navbar-brand { + color: #cccccc; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: none; +} +.navbar-inverse .navbar-text { + color: #cccccc; +} +.navbar-inverse .navbar-nav > li > a { + color: #cccccc; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: #5d6368; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #5d6368; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #5d6368; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #5d6368; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #697075; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + background-color: #5d6368; + color: #ffffff; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #62686d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #62686d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #cccccc; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: #5d6368; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #5d6368; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #cccccc; +} +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} +.navbar-inverse .btn-link { + color: #cccccc; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #ffffff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #cccccc; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: transparent; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + content: "/\00a0"; + padding: 0 5px; + color: #cccccc; +} +.breadcrumb > .active { + color: #7a8288; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 8px 12px; + line-height: 1.42857143; + text-decoration: none; + color: #ffffff; + background-color: #3a3f44; + border: 1px solid rgba(0, 0, 0, 0.6); + margin-left: -1px; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + z-index: 2; + color: #ffffff; + background-color: transparent; + border-color: rgba(0, 0, 0, 0.6); +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 3; + color: #ffffff; + background-color: #232628; + border-color: rgba(0, 0, 0, 0.6); + cursor: default; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #7a8288; + background-color: #ffffff; + border-color: rgba(0, 0, 0, 0.6); + cursor: not-allowed; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 14px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #3a3f44; + border: 1px solid rgba(0, 0, 0, 0.6); + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: transparent; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #7a8288; + background-color: #3a3f44; + cursor: not-allowed; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #3a3f44; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #232628; +} +.label-primary { + background-color: #7a8288; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #62686d; +} +.label-success { + background-color: #62c462; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #42b142; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f89406; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #c67605; +} +.label-danger { + background-color: #ee5f5b; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #e9322d; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #ffffff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #7a8288; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #ffffff; + background-color: #7a8288; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #1c1e22; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #050506; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; + padding-left: 15px; + padding-right: 15px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-left: 60px; + padding-right: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #1c1e22; + border: 1px solid #0c0d0e; + border-radius: 4px; + -webkit-transition: border 0.2s ease-in-out; + -o-transition: border 0.2s ease-in-out; + transition: border 0.2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-left: auto; + margin-right: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #ffffff; +} +.thumbnail .caption { + padding: 9px; + color: #c8c8c8; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + background-color: #62c462; + border-color: #62bd4f; + color: #ffffff; +} +.alert-success hr { + border-top-color: #55b142; +} +.alert-success .alert-link { + color: #e6e6e6; +} +.alert-info { + background-color: #5bc0de; + border-color: #3dced8; + color: #ffffff; +} +.alert-info hr { + border-top-color: #2ac7d2; +} +.alert-info .alert-link { + color: #e6e6e6; +} +.alert-warning { + background-color: #f89406; + border-color: #e96506; + color: #ffffff; +} +.alert-warning hr { + border-top-color: #d05a05; +} +.alert-warning .alert-link { + color: #e6e6e6; +} +.alert-danger { + background-color: #ee5f5b; + border-color: #ed4d63; + color: #ffffff; +} +.alert-danger hr { + border-top-color: #ea364f; +} +.alert-danger .alert-link { + color: #e6e6e6; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #1c1e22; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} +.progress-bar { + float: left; + width: 0%; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #ffffff; + text-align: center; + background-color: #7a8288; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + -o-transition: width 0.6s ease; + transition: width 0.6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #62c462; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f89406; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #ee5f5b; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + zoom: 1; + overflow: hidden; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-object.img-thumbnail { + max-width: none; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + margin-bottom: 20px; + padding-left: 0; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #32383e; + border: 1px solid rgba(0, 0, 0, 0.6); +} +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item, +button.list-group-item { + color: #c8c8c8; +} +a.list-group-item .list-group-item-heading, +button.list-group-item .list-group-item-heading { + color: #ffffff; +} +a.list-group-item:hover, +button.list-group-item:hover, +a.list-group-item:focus, +button.list-group-item:focus { + text-decoration: none; + color: #c8c8c8; + background-color: #3e444c; +} +button.list-group-item { + width: 100%; + text-align: left; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + background-color: #999999; + color: #7a8288; + cursor: not-allowed; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #7a8288; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #3e444c; + border-color: rgba(0, 0, 0, 0.6); +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #a2aab4; +} +.list-group-item-success { + color: #ffffff; + background-color: #62c462; +} +a.list-group-item-success, +button.list-group-item-success { + color: #ffffff; +} +a.list-group-item-success .list-group-item-heading, +button.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +button.list-group-item-success:hover, +a.list-group-item-success:focus, +button.list-group-item-success:focus { + color: #ffffff; + background-color: #4fbd4f; +} +a.list-group-item-success.active, +button.list-group-item-success.active, +a.list-group-item-success.active:hover, +button.list-group-item-success.active:hover, +a.list-group-item-success.active:focus, +button.list-group-item-success.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-info { + color: #ffffff; + background-color: #5bc0de; +} +a.list-group-item-info, +button.list-group-item-info { + color: #ffffff; +} +a.list-group-item-info .list-group-item-heading, +button.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +button.list-group-item-info:hover, +a.list-group-item-info:focus, +button.list-group-item-info:focus { + color: #ffffff; + background-color: #46b8da; +} +a.list-group-item-info.active, +button.list-group-item-info.active, +a.list-group-item-info.active:hover, +button.list-group-item-info.active:hover, +a.list-group-item-info.active:focus, +button.list-group-item-info.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-warning { + color: #ffffff; + background-color: #f89406; +} +a.list-group-item-warning, +button.list-group-item-warning { + color: #ffffff; +} +a.list-group-item-warning .list-group-item-heading, +button.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +button.list-group-item-warning:hover, +a.list-group-item-warning:focus, +button.list-group-item-warning:focus { + color: #ffffff; + background-color: #df8505; +} +a.list-group-item-warning.active, +button.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +button.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus, +button.list-group-item-warning.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-danger { + color: #ffffff; + background-color: #ee5f5b; +} +a.list-group-item-danger, +button.list-group-item-danger { + color: #ffffff; +} +a.list-group-item-danger .list-group-item-heading, +button.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +button.list-group-item-danger:hover, +a.list-group-item-danger:focus, +button.list-group-item-danger:focus { + color: #ffffff; + background-color: #ec4844; +} +a.list-group-item-danger.active, +button.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +button.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus, +button.list-group-item-danger.active:focus { + color: #fff; + background-color: #ffffff; + border-color: #ffffff; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #2e3338; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #3e444c; + border-top: 1px solid rgba(0, 0, 0, 0.6); + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #1c1e22; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + border: 0; + margin-bottom: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid rgba(0, 0, 0, 0.6); +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid rgba(0, 0, 0, 0.6); +} +.panel-default { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-default > .panel-heading { + color: #c8c8c8; + background-color: #3e444c; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-default > .panel-heading .badge { + color: #3e444c; + background-color: #c8c8c8; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.panel-primary { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #7a8288; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-primary > .panel-heading .badge { + color: #7a8288; + background-color: #ffffff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.panel-success { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-success > .panel-heading { + color: #ffffff; + background-color: #62c462; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-success > .panel-heading .badge { + color: #62c462; + background-color: #ffffff; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.panel-info { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-info > .panel-heading { + color: #ffffff; + background-color: #5bc0de; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-info > .panel-heading .badge { + color: #5bc0de; + background-color: #ffffff; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.panel-warning { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-warning > .panel-heading { + color: #ffffff; + background-color: #f89406; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-warning > .panel-heading .badge { + color: #f89406; + background-color: #ffffff; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.panel-danger { + border-color: rgba(0, 0, 0, 0.6); +} +.panel-danger > .panel-heading { + color: #ffffff; + background-color: #ee5f5b; + border-color: rgba(0, 0, 0, 0.6); +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: rgba(0, 0, 0, 0.6); +} +.panel-danger > .panel-heading .badge { + color: #ee5f5b; + background-color: #ffffff; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: rgba(0, 0, 0, 0.6); +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #1c1e22; + border: 1px solid #0c0d0e; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} +.modal-open { + overflow: hidden; +} +.modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #2e3338; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + -webkit-background-clip: padding-box; + background-clip: padding-box; + outline: 0; +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000000; +} +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} +.modal-header { + padding: 15px; + border-bottom: 1px solid #1c1e22; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 20px; +} +.modal-footer { + padding: 20px; + text-align: right; + border-top: 1px solid #1c1e22; +} +.modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 12px; + opacity: 0; + filter: alpha(opacity=0); +} +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} +.tooltip.top { + margin-top: -3px; + padding: 5px 0; +} +.tooltip.right { + margin-left: 3px; + padding: 0 5px; +} +.tooltip.bottom { + margin-top: 3px; + padding: 5px 0; +} +.tooltip.left { + margin-left: -3px; + padding: 0 5px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + background-color: #000000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: 1.42857143; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; + font-size: 14px; + background-color: #2e3338; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #2e3338; + border-bottom: 1px solid #22262a; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + border-width: 10px; + content: ""; +} +.popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #666666; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; +} +.popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #2e3338; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #666666; + border-right-color: rgba(0, 0, 0, 0.25); +} +.popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #2e3338; +} +.popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #666666; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; +} +.popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #2e3338; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #666666; + border-left-color: rgba(0, 0, 0, 0.25); +} +.popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #2e3338; + bottom: -10px; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + overflow: hidden; + width: 100%; +} +.carousel-inner > .item { + display: none; + position: relative; + -webkit-transition: 0.6s ease-in-out left; + -o-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -o-transition: -o-transform 0.6s ease-in-out; + transition: transform 0.6s ease-in-out; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + background-color: rgba(0, 0, 0, 0); +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} +.carousel-control.right { + left: auto; + right: 0; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} +.carousel-control:hover, +.carousel-control:focus { + outline: 0; + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + margin-left: -30%; + padding-left: 0; + list-style: none; + text-align: center; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #ffffff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); +} +.carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #ffffff; +} +.carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -10px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -10px; + } + .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-header:before, +.modal-header:after, +.modal-footer:before, +.modal-footer:after { + content: " "; + display: table; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-header:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-left: auto; + margin-right: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} +.navbar-default, +.navbar-inverse { + border: 1px solid rgba(0, 0, 0, 0.6); + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); +} +@media (min-width: 768px) { + .navbar-default .navbar-nav > li > a, + .navbar-inverse .navbar-nav > li > a { + border-right: 1px solid rgba(0, 0, 0, 0.2); + border-left: 1px solid rgba(255, 255, 255, 0.1); + } + .navbar-default .navbar-nav > li > a:hover, + .navbar-inverse .navbar-nav > li > a:hover { + border-left-color: transparent; + } + .navbar-default .nav .open > a, + .navbar-inverse .nav .open > a { + border-color: transparent; + } + .navbar-default .navbar-nav > li.active > a, + .navbar-inverse .navbar-nav > li.active > a { + border-left-color: transparent; + } + .navbar-default .navbar-form, + .navbar-inverse .navbar-form { + margin-left: 5px; + margin-right: 5px; + } +} +.navbar-default { + -webkit-filter: none; + filter: none; +} +.navbar-default .navbar-nav > li > a:hover { + -webkit-filter: none; + filter: none; +} +.navbar-inverse { + -webkit-filter: none; + filter: none; +} +.navbar-inverse .badge { + background-color: #5d6368; +} +.navbar-inverse .navbar-nav > li > a:hover { + -webkit-filter: none; + filter: none; +} +.btn, +.btn:hover { + border-color: rgba(0, 0, 0, 0.6); + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); +} +.btn-default { + -webkit-filter: none; + filter: none; +} +.btn-default:hover { + -webkit-filter: none; + filter: none; +} +.btn-primary { + -webkit-filter: none; + filter: none; +} +.btn-primary:hover { + -webkit-filter: none; + filter: none; +} +.btn-success { + -webkit-filter: none; + filter: none; +} +.btn-success:hover { + -webkit-filter: none; + filter: none; +} +.btn-info { + -webkit-filter: none; + filter: none; +} +.btn-info:hover { + -webkit-filter: none; + filter: none; +} +.btn-warning { + -webkit-filter: none; + filter: none; +} +.btn-warning:hover { + -webkit-filter: none; + filter: none; +} +.btn-danger { + -webkit-filter: none; + filter: none; +} +.btn-danger:hover { + -webkit-filter: none; + filter: none; +} +.btn-link, +.btn-link:hover { + border-color: transparent; +} +h1, +h2, +h3, +h4, +h5, +h6 { + text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.3); +} +.text-primary, +.text-primary:hover { + color: #7a8288; +} +.text-success, +.text-success:hover { + color: #62c462; +} +.text-danger, +.text-danger:hover { + color: #ee5f5b; +} +.text-warning, +.text-warning:hover { + color: #f89406; +} +.text-info, +.text-info:hover { + color: #5bc0de; +} +.table .success, +.table .warning, +.table .danger, +.table .info { + color: #fff; +} +.table-bordered tbody tr.success td, +.table-bordered tbody tr.warning td, +.table-bordered tbody tr.danger td, +.table-bordered tbody tr.success:hover td, +.table-bordered tbody tr.warning:hover td, +.table-bordered tbody tr.danger:hover td { + border-color: #1c1e22; +} +.table-responsive > .table { + background-color: #2e3338; +} +input, +textarea { + color: #272b30; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label, +.has-warning .form-control-feedback { + color: #f89406; +} +.has-warning .form-control, +.has-warning .form-control:focus { + border-color: #f89406; +} +.has-warning .input-group-addon { + border-color: rgba(0, 0, 0, 0.6); +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label, +.has-error .form-control-feedback { + color: #ee5f5b; +} +.has-error .form-control, +.has-error .form-control:focus { + border-color: #ee5f5b; +} +.has-error .input-group-addon { + border-color: rgba(0, 0, 0, 0.6); +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label, +.has-success .form-control-feedback { + color: #62c462; +} +.has-success .form-control, +.has-success .form-control:focus { + border-color: #62c462; +} +.has-success .input-group-addon { + border-color: rgba(0, 0, 0, 0.6); +} +legend { + color: #fff; +} +.input-group-addon { + -webkit-filter: none; + filter: none; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + color: #ffffff; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + border-color: rgba(0, 0, 0, 0.6); +} +.nav-pills > li > a { + -webkit-filter: none; + filter: none; + border: 1px solid rgba(0, 0, 0, 0.6); + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); +} +.nav-pills > li > a:hover { + -webkit-filter: none; + filter: none; + border: 1px solid rgba(0, 0, 0, 0.6); +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover { + background-color: none; + -webkit-filter: none; + filter: none; + border: 1px solid rgba(0, 0, 0, 0.6); +} +.nav-pills > li.disabled > a, +.nav-pills > li.disabled > a:hover { + -webkit-filter: none; + filter: none; +} +.pagination > li > a, +.pagination > li > span { + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + -webkit-filter: none; + filter: none; +} +.pagination > li > a:hover, +.pagination > li > span:hover { + -webkit-filter: none; + filter: none; +} +.pagination > li.active > a, +.pagination > li.active > span { + -webkit-filter: none; + filter: none; +} +.pagination > li.disabled > a, +.pagination > li.disabled > a:hover, +.pagination > li.disabled > span, +.pagination > li.disabled > span:hover { + -webkit-filter: none; + filter: none; +} +.pager > li > a { + -webkit-filter: none; + filter: none; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); +} +.pager > li > a:hover { + -webkit-filter: none; + filter: none; +} +.pager > li.disabled > a, +.pager > li.disabled > a:hover { + -webkit-filter: none; + filter: none; +} +.breadcrumb { + border: 1px solid rgba(0, 0, 0, 0.6); + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3); + -webkit-filter: none; + filter: none; +} +.alert .alert-link, +.alert a { + color: #fff; + text-decoration: underline; +} +.alert .close { + color: #000000; + text-decoration: none; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #0c0d0e; +} +a.list-group-item.active, +a.list-group-item.active:hover, +a.list-group-item.active:focus { + border-color: rgba(0, 0, 0, 0.6); +} +a.list-group-item-success.active { + background-color: #62c462; +} +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + background-color: #4fbd4f; +} +a.list-group-item-warning.active { + background-color: #f89406; +} +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + background-color: #df8505; +} +a.list-group-item-danger.active { + background-color: #ee5f5b; +} +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + background-color: #ec4844; +} +.jumbotron { + border: 1px solid rgba(0, 0, 0, 0.6); +} +.panel-primary .panel-heading, +.panel-success .panel-heading, +.panel-danger .panel-heading, +.panel-warning .panel-heading, +.panel-info .panel-heading { + border-color: #000; +} diff --git a/web/gui/css/bootstrap-slider-10.0.0.min.css b/web/gui/css/bootstrap-slider-10.0.0.min.css new file mode 100644 index 0000000..095be95 --- /dev/null +++ b/web/gui/css/bootstrap-slider-10.0.0.min.css @@ -0,0 +1,22 @@ +/*! ======================================================= + VERSION 10.0.0 +========================================================= */ +/*! ========================================================= + * bootstrap-slider.js + * + * Maintainers: + * Kyle Kemp + * - Twitter: @seiyria + * - Github: seiyria + * Rohit Kalkur + * - Twitter: @Rovolutionary + * - Github: rovolution + * + * ========================================================= + * + * bootstrap-slider is released under the MIT License + * Copyright (c) 2017 Kyle Kemp, Rohit Kalkur, and contributors + * + * SPDX-License-Identifier: MIT + * + * ========================================================= */.slider{display:inline-block;vertical-align:middle;position:relative}.slider.slider-horizontal{width:210px;height:20px}.slider.slider-horizontal .slider-track{height:10px;width:100%;margin-top:-5px;top:50%;left:0}.slider.slider-horizontal .slider-selection,.slider.slider-horizontal .slider-track-low,.slider.slider-horizontal .slider-track-high{height:100%;top:0;bottom:0}.slider.slider-horizontal .slider-tick,.slider.slider-horizontal .slider-handle{margin-left:-10px}.slider.slider-horizontal .slider-tick.triangle,.slider.slider-horizontal .slider-handle.triangle{position:relative;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);border-width:0 10px 10px 10px;width:0;height:0;border-bottom-color:#2e6da4;margin-top:0}.slider.slider-horizontal .slider-tick-container{white-space:nowrap;position:absolute;top:0;left:0;width:100%}.slider.slider-horizontal .slider-tick-label-container{white-space:nowrap;margin-top:20px}.slider.slider-horizontal .slider-tick-label-container .slider-tick-label{padding-top:4px;display:inline-block;text-align:center}.slider.slider-horizontal .tooltip{-ms-transform:translateX(-50%);transform:translateX(-50%)}.slider.slider-horizontal.slider-rtl .slider-track{left:initial;right:0}.slider.slider-horizontal.slider-rtl .slider-tick,.slider.slider-horizontal.slider-rtl .slider-handle{margin-left:initial;margin-right:-10px}.slider.slider-horizontal.slider-rtl .slider-tick-container{left:initial;right:0}.slider.slider-horizontal.slider-rtl .tooltip{-ms-transform:translateX(50%);transform:translateX(50%)}.slider.slider-vertical{height:210px;width:20px}.slider.slider-vertical .slider-track{width:10px;height:100%;left:25%;top:0}.slider.slider-vertical .slider-selection{width:100%;left:0;top:0;bottom:0}.slider.slider-vertical .slider-track-low,.slider.slider-vertical .slider-track-high{width:100%;left:0;right:0}.slider.slider-vertical .slider-tick,.slider.slider-vertical .slider-handle{margin-top:-10px}.slider.slider-vertical .slider-tick.triangle,.slider.slider-vertical .slider-handle.triangle{border-width:10px 0 10px 10px;width:1px;height:1px;border-left-color:#2e6da4;border-right-color:#2e6da4;margin-left:0;margin-right:0}.slider.slider-vertical .slider-tick-label-container{white-space:nowrap}.slider.slider-vertical .slider-tick-label-container .slider-tick-label{padding-left:4px}.slider.slider-vertical .tooltip{-ms-transform:translateY(-50%);transform:translateY(-50%)}.slider.slider-vertical.slider-rtl .slider-track{left:initial;right:25%}.slider.slider-vertical.slider-rtl .slider-selection{left:initial;right:0}.slider.slider-vertical.slider-rtl .slider-tick.triangle,.slider.slider-vertical.slider-rtl .slider-handle.triangle{border-width:10px 10px 10px 0}.slider.slider-vertical.slider-rtl .slider-tick-label-container .slider-tick-label{padding-left:initial;padding-right:4px}.slider.slider-disabled .slider-handle{background-image:-webkit-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:-o-linear-gradient(top,#dfdfdf 0,#bebebe 100%);background-image:linear-gradient(to bottom,#dfdfdf 0,#bebebe 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdfdfdf',endColorstr='#ffbebebe',GradientType=0)}.slider.slider-disabled .slider-track{background-image:-webkit-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:-o-linear-gradient(top,#e5e5e5 0,#e9e9e9 100%);background-image:linear-gradient(to bottom,#e5e5e5 0,#e9e9e9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe5e5e5',endColorstr='#ffe9e9e9',GradientType=0);cursor:not-allowed}.slider input{display:none}.slider .tooltip.top{margin-top:-36px}.slider .tooltip-inner{white-space:nowrap;max-width:none}.slider .hide{display:none}.slider-track{position:absolute;cursor:pointer;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#f9f9f9 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#f9f9f9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);border-radius:4px}.slider-selection{position:absolute;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-selection.tick-slider-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0)}.slider-track-low,.slider-track-high{position:absolute;background:transparent;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}.slider-handle{position:absolute;top:0;width:20px;height:20px;background-color:#337ab7;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7',endColorstr='#ff2e6da4',GradientType=0);filter:none;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05);border:0 solid transparent}.slider-handle.round{border-radius:50%}.slider-handle.triangle{background:transparent none}.slider-handle.custom{background:transparent none}.slider-handle.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick{position:absolute;width:20px;height:20px;background-image:-webkit-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#f9f9f9 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#f9f9f9 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;filter:none;opacity:.8;border:0 solid transparent}.slider-tick.round{border-radius:50%}.slider-tick.triangle{background:transparent none}.slider-tick.custom{background:transparent none}.slider-tick.custom::before{line-height:20px;font-size:20px;content:'\2605';color:#726204}.slider-tick.in-selection{background-image:-webkit-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:-o-linear-gradient(top,#8ac1ef 0,#82b3de 100%);background-image:linear-gradient(to bottom,#8ac1ef 0,#82b3de 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff8ac1ef',endColorstr='#ff82b3de',GradientType=0);opacity:1} diff --git a/web/gui/css/bootstrap-theme-3.3.7.min.css b/web/gui/css/bootstrap-theme-3.3.7.min.css new file mode 100644 index 0000000..ba77cff --- /dev/null +++ b/web/gui/css/bootstrap-theme-3.3.7.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * SPDX-License-Identifier: MIT + */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} +/*# sourceMappingURL=bootstrap-theme.min.css.map */ diff --git a/web/gui/css/bootstrap-toggle-2.2.2.min.css b/web/gui/css/bootstrap-toggle-2.2.2.min.css new file mode 100644 index 0000000..a3daa37 --- /dev/null +++ b/web/gui/css/bootstrap-toggle-2.2.2.min.css @@ -0,0 +1,29 @@ +/*! ======================================================================== + * Bootstrap Toggle: bootstrap-toggle.css v2.2.0 + * http://www.bootstraptoggle.com + * ======================================================================== + * Copyright 2014 Min Hur, The New York Times Company + * Licensed under MIT + * SPDX-License-Identifier: MIT + * ======================================================================== */ +.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px} +.toggle{position:relative;overflow:hidden} +.toggle input[type=checkbox]{display:none} +.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none} +.toggle.off .toggle-group{left:-100%} +.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0} +.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0} +.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px} +.toggle.btn{min-width:59px;min-height:34px} +.toggle-on.btn{padding-right:24px} +.toggle-off.btn{padding-left:24px} +.toggle.btn-lg{min-width:79px;min-height:45px} +.toggle-on.btn-lg{padding-right:31px} +.toggle-off.btn-lg{padding-left:31px} +.toggle-handle.btn-lg{width:40px} +.toggle.btn-sm{min-width:50px;min-height:30px} +.toggle-on.btn-sm{padding-right:20px} +.toggle-off.btn-sm{padding-left:20px} +.toggle.btn-xs{min-width:35px;min-height:22px} +.toggle-on.btn-xs{padding-right:12px} +.toggle-off.btn-xs{padding-left:12px} diff --git a/web/gui/css/c3-0.4.18.min.css b/web/gui/css/c3-0.4.18.min.css new file mode 100644 index 0000000..a033d72 --- /dev/null +++ b/web/gui/css/c3-0.4.18.min.css @@ -0,0 +1,2 @@ +/* SPDX-License-Identifier: MIT */ +.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:grey;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:1;fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #ccc}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#fff}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max{fill:#777}.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}.c3-chart-arc.c3-target g path{opacity:1}.c3-chart-arc.c3-target.c3-focused g path{opacity:1} diff --git a/web/gui/css/morris-0.5.1.css b/web/gui/css/morris-0.5.1.css new file mode 100644 index 0000000..39203d3 --- /dev/null +++ b/web/gui/css/morris-0.5.1.css @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +.morris-hover{position:absolute;z-index:1000}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255,255,255,0.8);border:solid 2px rgba(230,230,230,0.8);font-family:sans-serif;font-size:12px;text-align:center}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0} +.morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0} diff --git a/web/gui/custom/README.md b/web/gui/custom/README.md new file mode 100644 index 0000000..5ee7235 --- /dev/null +++ b/web/gui/custom/README.md @@ -0,0 +1,414 @@ +# Custom dashboards + +You can: + +- create your own dashboards using simple HTML (no javascript is required for basic dashboards) +- utilizing any or all of the available chart libraries, on the same dashboard +- using data from one or more netdata servers, on the same dashboard +- host your dashboard HTML page on any web server, anywhere + +netdata charts can also be added to existing web pages. + +Check this **[very simple working example of a custom dashboard](http://netdata.firehol.org/demo.html)**, and its **[html source](../demo.html)**. + +If you plan to put it on TV, check **[tv.html](../tv.html)**. This is a screenshot of it, monitoring 2 servers on the same page: + +![image](https://cloud.githubusercontent.com/assets/2662304/14252187/d8d5f78e-fa8e-11e5-990d-99821d38c874.png) +-- + +## Web directory + +The default web root directory is `/usr/share/netdata/web` where you will find examples such as tv.html, and demo.html as well as the main dashboard contained in index.html. +Note: index.html have a different syntax. Don't use it as a template for simple custom dashboards. + +## Example empty dashboard + +If you need to create a new dashboard on an empty page, we suggest the following header: + +```html +<!DOCTYPE html> +<html lang="en"> +<head> + <title>Your dashboard</title> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + + <!-- here we will add dashboard.js --> + +</head> +<body> + +<!-- here we will add charts --> + +</body> +</html> +``` + + +## dashboard.js + +To add netdata charts to any web page (dedicated to netdata or not), you need to include the `/dashboard.js` file of a netdata server. + +For example, if your netdata server listens at `http://box:19999/`, you will need to add the following to the `head` section of your web page: + +```html +<script type="text/javascript" src="http://box:19999/dashboard.js"></script> +``` + +### what dashboard.js does? + +`dashboard.js` will automatically load the following: + +1. `dashboard.css`, required for the netdata charts + +2. `jquery.min.js`, (only if jquery is not already loaded for this web page) + +3. `bootstrap.min.js` (only if bootstrap is not already loaded) and `bootstrap.min.css`. + + You can disable this by adding the following before loading `dashboard.js`: + +```html +<script>var netdataNoBootstrap = true;</script> +``` + +4. `jquery.nanoscroller.min.js`, required for the scrollbar of the chart legends. + +5. `bootstrap-toggle.min.js` and `bootstrap-toggle.min.css`, required for the settings toggle buttons. + +6. `font-awesome.min.css`, for icons. + +When `dashboard.js` loads will scan the page for elements that define charts (see below) and immediately start refreshing them. Keep in mind more javascript modules may be loaded (every chart library is a different javascript file, that is loaded on first use). + +### Prevent dashboard.js from starting chart refreshes + +If your web page is not static and you plan to add charts using javascript, you can tell `dashboard.js` not to start processing charts immediately after loaded, by adding this fragment before loading it: + +```html +<script>var netdataDontStart = true;</script> +``` + +The above, will inform the `dashboard.js` to load everything, but not process the web page until you tell it to. +You can tell it to start processing the page, by running this javascript code: + +```js +NETDATA.start(); +``` + +Be careful not to call the `NETDATA.start()` multiple times. Each call to this function will spawn a new thread that will start refreshing the charts. + +If, after calling `NETDATA.start()` you need to update the page (or even get your javascript code synchronized with `dashboard.js`), you can call (after you loaded `dashboard.js`): + +```js +NETDATA.pause(function() { + // ok, it is paused + + // update the DOM as you wish + + // and then call this to let the charts refresh: + NETDATA.unpause(); +}); +``` + +### The default netdata server + +`dashboard.js` will attempt to auto-detect the URL of the netdata server it is loaded from, and set this server as the default netdata server for all charts. + +If you need to set any other URL as the default netdata server for all charts that do not specify a netdata server, add this before loading `dashboard.js`: + +```html +<script type="text/javascript">var netdataServer = "http://your.netdata.server:19999";</script> +``` + +--- + +# Adding charts + +To add charts, you need to add a `div` for each of them. Each of these `div` elements accept a few `data-` attributes: + +### The chart unique ID + +The unique ID of a chart is shown at the title of the chart of the default netdata dashboard. You can also find all the charts available at your netdata server with this URL: `http://your.netdata.server:19999/api/v1/charts` ([example](http://netdata.firehol.org/api/v1/charts)). + +To specify the unique id, use this: + +```html +<div data-netdata="unique.id"></div> +``` + +The above is enough for adding a chart. It most probably have the wrong visual settings though. Keep reading... + +### The duration of the chart + +You can specify the duration of the chart (how much time of data it will show) using: + +```html +<div data-netdata="unique.id" + data-after="AFTER_SECONDS" + data-before="BEFORE_SECONDS" + ></div> +``` + +`AFTER_SECONDS` and `BEFORE_SECONDS` are numbers representing a time-frame in seconds. + +The can be either: + +- **absolute** unix timestamps (in javascript terms, they are `new Date().getTime() / 1000`. Using absolute timestamps you can have a chart showing always the same time-frame. + +- **relative** number of seconds to now. To show the last 10 minutes of data, `AFTER_SECONDS` must be `-600` (relative to now) and `BEFORE_SECONDS` must be `0` (meaning: now). If you want the chart to auto-refresh the current values, you need to specify **relative** values. + +### Chart sizes + +You can set the size of the chart using this: + +```html +<div data-netdata="unique.id" + data-width="WIDTH" + data-height="HEIGHT" + ></div> +``` + +`WIDTH` and `HEIGHT` can be anything CSS accepts for width and height (e.g. percentages, pixels, etc). +Keep in mind that for certain chart libraries, `dashboard.js` may apply an aspect ratio to these. + +If you want `dashboard.js` to remember permanently (browser local storage) the dimensions of the chart (the user may resize it), you can add: `data-id="SETTINGS_ID"`, where `SETTINGS_ID` is anything that will be common for this chart across user sessions. + +### Netdata server + +Each chart can get data from a different netdata server. You can give per chart the netdata server using: + +```html +<div data-netdata="unique.id" + data-host="http://another.netdata.server:19999/" + ></div> +``` + +If you have ephemeral monitoring setup ([More info here](../../../streaming/#monitoring-ephemeral-nodes)) and have no direct access to the nodes dashboards, you can use the following: + +```html +<div data-netdata="unique.id" + data-host="http://yournetdata.server:19999/host/reported-hostname" + ></div> +``` +### Chart library + +The default chart library is `dygraph`. You set a different chart library per chart using this: + +```html +<div data-netdata="unique.id" + data-chart-library="gauge" + ></div> +``` + +Each chart library may support more chart-library specific settings. Please refer to the documentation of the chart library you are interested, in this wiki or the source code: + +- options `data-dygraph-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L6251-L6361) +- options `data-easypiechart-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L7954-L7966) +- options `data-gauge-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L8182-L8189) +- options `data-d3pie-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L7394-L7561) +- options `data-sparkline-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L5940-L5985) +- options `data-peity-XXX` [here](https://github.com/netdata/netdata/blob/643cfe20a8d8beba0ed31ec6afaade80853fd310/web/dashboard.js#L5892) + + +### Data points + +For the time-frame requested, `dashboard.js` will use the chart dimensions and the settings of the chart library to find out how many data points it can show. + +For example, most line chart libraries are using 3 pixels per data point. If the chart shows 10 minutes of data (600 seconds), its update frequency is 1 second, and the chart width is 1800 pixels, then `dashboard.js` will request from the netdata server: 10 minutes of data, represented in 600 points, and the chart will be refreshed per second. If the user resizes the window so that the chart becomes 600 pixels wide, then `dashboard.js` will request the same 10 minutes of data, represented in 200 points and the chart will be refreshed once every 3 seconds. + +If you need to have a fixed number of points in the data source retrieved from the netdata server, you can set: + +```html +<div data-netdata="unique.id" + data-points="DATA_POINTS" + ></div> +``` + +Where `DATA_POINTS` is the number of points you need. + +You can also overwrite the pixels-per-point per chart using this: + +```html +<div data-netdata="unique.id" + data-pixels-per-point="PIXELS_PER_POINT" + ></div> +``` + +Where `PIXELS_PER_POINT` is the number of pixels each data point should occupy. + +### Data grouping method + +Netdata supports **average** (the default), **sum** and **max** grouping methods. The grouping method is used when the netdata server is requested to return fewer points for a time-frame, compared to the number of points available. + +You can give it per chart, using: + +```html +<div data-netdata="unique.id" + data-method="max" + ></div> +``` + +### Changing rates + +Netdata can change the rate of charts on the fly. So a charts that shows values **per second** can be turned to **per minute** (or any other, e.g. **per 10 seconds**), with this: + +```html +<div data-netdata="unique.id" + data-method="average" + data-gtime="60" + data-units="per minute" + ></div> +``` + +The above will provide the average rate per minute (60 seconds). +Use 60 for `/minute`, 3600 for `/hour`, 86400 for `/day` (provided you have that many data). + +- The `data-gtime` setting does not change the units of the chart. You have to change them yourself with `data-units`. +- This works only for `data-method="average"`. +- netdata may aggregate multiple points to satisfy the `data-points` setting. For example, you request `per minute` but the requested number of points to be returned are not enough to report every single minute. In this case netdata will sum the `per second` raw data of the database to find the `per minute` for every single minute and then **average** them to find the **average per minute rate of every X minutes**. So, it works as if the data collection frequency was per minute. + +### Selecting dimensions + +By default, `dashboard.js` will show all the dimensions of the chart. +You can select specific dimensions using this: + +```html +<div data-netdata="unique.id" + data-dimensions="dimension1,dimension2,dimension3,..." + ></div> +``` + +netdata supports coma (` , `) or pipe (` | `) separated [simple patterns](../../../libnetdata/simple_pattern/) for dimensions. By default it searches for both dimension IDs and dimension NAMEs. You can control the target of the match with: `data-append-options="match-ids"` or `data-append-options="match-names"`. Spaces in `data-dimensions=""` are matched in the dimension names and IDs. + +### Chart title + +You can overwrite the title of the chart using this: + +```html +<div data-netdata="unique.id" + data-title="my super chart" + ></div> +``` + +### Chart units + +You can overwrite the units of measurement of the dimensions of the chart, using this: + +```html +<div data-netdata="unique.id" + data-units="words/second" + ></div> +``` + +### Chart colors + +`dashboard.js` has an internal palette of colors for the dimensions of the charts. +You can prepend colors to it (so that your will be used first) using this: + +```html +<div data-netdata="unique.id" + data-colors="#AABBCC #DDEEFF ..." + ></div> +``` + +### Extracting dimension values + +`dashboard.js` can update the selected values of the chart at elements you specify. For example, let's assume we have a chart that measures the bandwidth of eth0, with 2 dimensions `in` and `out`. You can use this: + +```html +<div data-netdata="net.eth0" + data-show-value-of-in-at="eth0_in_value" + data-show-value-of-out-at="eth0_out_value" + ></div> + +My eth0 interface, is receiving <span id="eth0_in_value"></span> +and transmitting <span id="eth0_out_value"></span>. +``` + +### Hiding the legend of a chart + +On charts that by default have a legend managed by `dashboard.js` you can remove it, using this: + +```html +<div data-netdata="unique.id" + data-legend="no" + ></div> +``` + +### API options + +You can append netdata **[REST API v1](../../api)** data options, using this: + +```html +<div data-netdata="unique.id" + data-append-options="absolute,percentage" + ></div> +``` + +A few useful options are: + +- `absolute` to show all values are absolute (i.e. turn negative dimensions to positive) +- `percentage` to express the values as a percentage of the chart total (so, the values of the dimensions are added, and the sum of them if expressed as a percentage of the sum of all dimensions) +- `unaligned` to prevent netdata from aligning the charts (e.g. when requesting 60 seconds aggregation per point, netdata returns chart data aligned to XX:XX:00 to XX:XX:59 - similarly for hours, days, etc - the `unaligned` option disables this feature) +- `match-ids` or `match-names` is used to control what `data-dimensions=` will match. + +### Chart library performance + +`dashboard.js` measures the performance of the chart library when it renders the charts. You can specify an element ID you want this information to be visualized, using this: + +```html +<div data-netdata="unique.id" + data-dt-element-name="measurement1" + ></div> + +refreshed in <span id="measurement1"></span> milliseconds! +``` + +### Syncing charts y-range + +If you give the same `data-common-max="NAME"` to 2+ charts, then all of them will share the same max value of their y-range. If one spikes, all of them will be aligned to have the same scale. This is done for the cpu interrupts and and cpu softnet charts at the dashboard and also for the `gauge` and `easypiecharts` of the netdata home page. + +```html +<div data-netdata="chart1" + data-common-max="chart-group-1" + ></div> + +<div data-netdata="chart2" + data-common-max="chart-group-1" + ></div> +``` + +The same functionality exists for `data-common-min`. + +### Syncing chart units + +netdata dashboards support auto-scaling of units. So, `MB` can become `KB`, `GB`, etc dynamically, based on the value to be shown. + +Giving the same `NAME` with `data-common-units="NAME"`, 2+ charts can be forced to always have the same units. + +```html +<div data-netdata="chart1" + data-common-units="chart-group-1" + ></div> + +<div data-netdata="chart2" + data-common-units="chart-group-1" + ></div> +``` + +### Setting desired units + +Charts can be scaled to specific units with `data-desired-units="UNITS"`. If the dashboard can convert the units to the desired one, it will do. + +```html +<div data-netdata="chart1" + data-desired-units="GB" + ></div> +``` + + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fgui%2Fcustom%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/gui/dashboard.css b/web/gui/dashboard.css new file mode 100644 index 0000000..8062497 --- /dev/null +++ b/web/gui/dashboard.css @@ -0,0 +1,739 @@ +/* SPDX-License-Identfier: GPL-3.0-or-later */ +html, +body { + /*font-family: Calibri,"Segoe UI","Helvetica Neue",Helvetica,Arial,sans-serif;*/ + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-variant: normal; +} + +.morelink { + color: #765d9c; + text-decoration: none; +} + +.morelink:hover { + color: #563d7c; + text-decoration: none; +} + +.morelink:focus { + color: #765d9c; + text-decoration: none; +} + +.netdata-chart-alignment { + margin-left: 55px; +} + +.netdata-chart-row { + width: 100%; + text-align: center; + display: flex; + display: -webkit-flex; + display: -moz-flex; + align-items: baseline; + -moz-align-items: baseline; + -webkit-align-items: baseline; + justify-content: center; + -webkit-justify-content: center; + -moz-justify-content: center; + padding-top: 10px; +} + +.netdata-container { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-gauge { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-gauge:after { + padding-top: 60%; + display: block; + content: ''; +} + +.netdata-container-easypiechart { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-easypiechart:after { + padding-top: 100%; + display: block; + content: ''; +} + +.netdata-aspect { + position: relative; + width: 100%; + padding: 0px; + margin: 0px; +} + +.netdata-container-with-legend { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* fix minimum scrollbar issue in firefox */ + min-height: 99px; + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-legend-resize-handler { + display: block; + position: absolute; + bottom: 0px; + right: 0px; + height: 15px; + width: 20px; + background-color: White; + font-size: 15px; + vertical-align: middle; + line-height: 15px; + cursor: ns-resize; + color: #DDDDDD; + text-align: center; + overflow: hidden; + z-index: 20; + padding: 0px; + margin: 0px; +} + +.netdata-legend-toolbox { + display: block; + position: absolute; + bottom: 0px; + right: 30px; + height: 15px; + width: 110px; + background-color: White; + font-size: 12px; + vertical-align: middle; + line-height: 15px; + color: #DDDDDD; + text-align: center; + overflow: hidden; + z-index: 20; + padding: 0px; + margin: 0px; + + /* prevent text selection after double click */ + -webkit-user-select: none; /* webkit (safari, chrome) browsers */ + -moz-user-select: none; /* mozilla browsers */ + -khtml-user-select: none; /* webkit (konqueror) browsers */ + -ms-user-select: none; /* IE10+ */ +} + +.netdata-legend-toolbox-button { + display: inline-block; + position: relative; + height: 15px; + width: 18px; + background-color: White; + font-size: 12px; + vertical-align: middle; + line-height: 15px; + color: #CDCDCD; + text-align: center; + overflow: hidden; + z-index: 21; + padding: 0px; + margin: 0px; + cursor: pointer; + + /* prevent text selection after double click */ + -webkit-user-select: none; /* webkit (safari, chrome) browsers */ + -moz-user-select: none; /* mozilla browsers */ + -khtml-user-select: none; /* webkit (konqueror) browsers */ + -ms-user-select: none; /* IE10+ */ +} + +.netdata-message { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + text-align: left; + vertical-align: top; + font-weight: bold; + font-size: x-small; + overflow: hidden; + background: inherit; + z-index: 0; +} + +.netdata-message.hidden { + display: none; +} + +.netdata-message.icon { + color: #F8F8F8; + text-align: center; + vertical-align: middle; +} + +.netdata-chart-legend { + position: absolute; /* within .netdata-container */ + top: 0; + right: 0; + overflow: hidden; + text-overflow: ellipsis; + line-height: 14px; + display: block; + width: 140px; /* --legend-width */ + height: calc(100% - 15px); /* 10px for the resize handler and 5px for the top margin */ + font-size: 10px; + margin-top: 5px; + text-align: left; + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-legend-title-date { + font-size: 10px; + font-weight: normal; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-title-time { + font-size: 11px; + font-weight: bold; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-title-units { + position: absolute; + right: 10px; + float: right; + font-size: 11px; + vertical-align: top; + font-weight: normal; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-series { + position: absolute; + width: 140px; /* legend-width */ + height: calc(100% - 50px); + overflow: hidden; + text-overflow: ellipsis; + line-height: 14.5px; /* line spacing at the legend */ + display: block; + font-size: 10px; + margin-top: 0px; +} + +.netdata-legend-name-table-line { + display: inline-block; + width: 13px; + height: 4px; + border-width: 0px; + border-bottom-width: 2px; + border-bottom-style: solid; + border-bottom-color: white; +} + +.netdata-legend-name-table-area { + display: inline-block; + width: 13px; + height: 5px; + border-width: 1px; + border-top-width: 1px; + border-top-style: solid; + border-top-color: inherit; +} + +.netdata-legend-name-table-stacked { + display: inline-block; + width: 13px; + height: 5px; + border-width: 1px; + border-top-width: 1px; + border-top-style: solid; + border-top-color: inherit; +} + +.netdata-legend-name-tr { +} + +.netdata-legend-name-td { +} + +.netdata-legend-name { + text-align: left; + font-size: 11px; /* legend: dimension name size */ + font-weight: bold; + vertical-align: bottom; + margin-top: 0px; + z-index: 9; + padding: 0px; + width: 80px !important; + max-width: 80px !important; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + display: inline-block; + cursor: pointer; + -webkit-print-color-adjust: exact; +} + +.netdata-legend-value { + /*margin-left: 14px;*/ + position: absolute; + right: 10px; + float: right; + text-align: right; + font-size: 11px; /* legend: dimension value size */ + font-weight: bold; + vertical-align: bottom; + background-color: White; + margin-top: 0px; + z-index: 10; + padding: 0px; + padding-left: 15px; + cursor: pointer; + /* -webkit-font-smoothing: none; */ +} + +.netdata-legend-name.not-selected { + font-weight: normal; + opacity: 0.3; +} + +.netdata-chart { + position: absolute; /* within .netdata-container */ + top: 0; /* within .netdata-container */ + left: 0; /* within .netdata-container */ + display: inline-block; + overflow: hidden; + width: 100%; + height: 100%; + z-index: 5; + + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-chart-with-legend-right { + position: absolute; /* within .netdata-container */ + top: 0; /* within .netdata-container */ + left: 0; /* within .netdata-container */ + display: block; + overflow: hidden; + margin-right: 140px; /* --legend-width */ + width: calc(100% - 140px); /* --legend-width */ + height: 100%; + z-index: 5; + flex-grow: 1; + + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-peity-chart { + +} + +.netdata-sparkline-chart { + +} + +.netdata-dygraph-chart { + +} + +.netdata-morris-chart { + +} + +.netdata-google-chart { + +} + +.dygraph-ylabel { +} + +.dygraph-axis-label-x { + overflow-x: hidden; +} + +.dygraph-label-rotate-left { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(90deg); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -o-transform: rotate(90deg); + -ms-transform: rotate(90deg); +} + +/* For y2-axis label */ +.dygraph-label-rotate-right { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(-90deg); + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); +} + +.dygraph-title { + text-indent: 56px; + text-align: left; + position: absolute; + left: 0px; + top: 4px; + font-size: 11px; + font-weight: bold; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +/* fix for sparkline tooltip under bootstrap */ +.jqstooltip { + width: auto !important; + height: auto !important; +} + +.easyPieChart { + position: relative; + text-align: center; +} + +.easyPieChart canvas { + position: absolute; + top: 0; + left: 0; +} + +.easyPieChartLabel { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #666; + font-weight: normal; + text-shadow: #BBB 0px 0px 1px; + /* -webkit-font-smoothing: none; */ +} + +.easyPieChartTitle { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 64%; + margin-left: 18% !important; + text-align: center; + color: #999999; + font-weight: bold; +} + +.easyPieChartUnits { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 60%; + margin-left: 20% !important; + text-align: center; + color: #999999; + font-weight: normal; +} + +.gaugeChart { + position: relative; + text-align: center; +} + +.gaugeChart canvas { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 0; +} + +.gaugeChartLabel { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #FFFFFF; + font-weight: bold; + z-index: 1; + text-shadow: #777 0px 0px 1px; + /* text-shadow: #CCC 1px 1px 0px, #CCC -1px -1px 0px, #CCC 1px -1px 0px, #CCC -1px 1px 0px; */ + /* -webkit-text-stroke: 1px #777; */ + /* -webkit-font-smoothing: none; */ +} + +.gaugeChartTitle { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #999999; + font-weight: bold; +} + +.gaugeChartUnits { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 0; + width: 100%; + text-align: left; + margin-left: 5%; + color: #999999; + font-weight: normal; +} + +.gaugeChartMin { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 8%; + width: 92%; + margin-left: 8%; + text-align: left; + color: #999999; + font-weight: normal; +} + +.gaugeChartMax { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 8%; + width: 95%; + margin-right: 5%; + text-align: right; + color: #999999; + font-weight: normal; +} + +.popover-title { + font-weight: bold; + font-size: 12px; +} + +.popover-content { + font-size: 11px; +} + +/* ---------------------------------------------------------------------------- + perfect-scrollbar settings + */ + +.ps-container { + -ms-touch-action: auto; + touch-action: auto; + overflow: hidden !important; + -ms-overflow-style: none; +} + +@supports (-ms-overflow-style: none) { + .ps-container { + overflow: auto !important; + } +} + +@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + .ps-container { + overflow: auto !important; + } +} + +.ps-container.ps-active-x > .ps-scrollbar-x-rail, +.ps-container.ps-active-y > .ps-scrollbar-y-rail { + display: block; + background-color: transparent; +} + +.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { + background-color: transparent; /* background color when dragged away */ + opacity: 0.9; +} + +.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { + background-color: #aaa; /* scrollbar color when dragged away */ + height: 5px; +} + +.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { + background-color: transparent; /* background color when dragged away */ + opacity: 0.9; +} + +.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { + background-color: #aaa; /* scrollbar color when dragged away */ + width: 5px; +} + +.ps-container > .ps-scrollbar-x-rail { + display: none; + position: absolute; + /* please don't change 'position' */ + opacity: 0.2; /* the opacity when not on hover of the content */ + -webkit-transition: background-color .2s linear, opacity .2s linear; + -o-transition: background-color .2s linear, opacity .2s linear; + -moz-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + bottom: 0px; + /* there must be 'bottom' for ps-scrollbar-x-rail */ + height: 15px; +} + +.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x { + position: absolute; + /* please don't change 'position' */ + background-color: #666; /* #aaa; the color on content hover */ + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + bottom: 2px; + /* there must be 'bottom' for ps-scrollbar-x */ + height: 5px; /* the width of the scrollbar */ +} + +.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x { + height: 4px; +} + +.ps-container > .ps-scrollbar-y-rail { + display: none; + position: absolute; + /* please don't change 'position' */ + opacity: 0.2; /* the opacity when not on hover of the content */ + -webkit-transition: background-color .2s linear, opacity .2s linear; + -o-transition: background-color .2s linear, opacity .2s linear; + -moz-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + right: 0; + /* there must be 'right' for ps-scrollbar-y-rail */ + width: 15px; +} + +.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y { + position: absolute; + /* please don't change 'position' */ + background-color: #666; /* #aaa; the color on content hover */ + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + right: 2px; + /* there must be 'right' for ps-scrollbar-y */ + width: 5px; /* the width of the scrollbar */ +} + +.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y { + width: 5px; +} + +.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { + background-color: transparent; /* background color when dragged */ + opacity: 0.9; +} + +.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { + background-color: #bbb; /* scrollbar color when dragged */ + height: 5px; +} + +.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { + background-color: transparent; /* background color when dragged */ + opacity: 0.9; +} + +.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { + background-color: #bbb; /* scrollbar color when dragged */ + width: 5px; +} + +.ps-container:hover > .ps-scrollbar-x-rail, +.ps-container:hover > .ps-scrollbar-y-rail { + opacity: 0.6; +} + +.ps-container:hover > .ps-scrollbar-x-rail:hover { + background-color: transparent; /* the background color on hover of the scrollbar */ + opacity: 0.9; +} + +.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x { + background-color: #999; /* scrollbar color on hover */ +} + +.ps-container:hover > .ps-scrollbar-y-rail:hover { + background-color: transparent; /* the background color on hover of the scrollbar */ + opacity: 0.9; +} + +.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y { + background-color: #999; /* scrollbar color on hover */ +} diff --git a/web/gui/dashboard.html b/web/gui/dashboard.html new file mode 100644 index 0000000..d322248 --- /dev/null +++ b/web/gui/dashboard.html @@ -0,0 +1,699 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <title>NetData Dashboard</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + <meta name="author" content="costa@tsaousis.gr"> + + <meta property="og:locale" content="en_US" /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png"/> + <meta property="og:url" content="http://my-netdata.io/"/> + <meta property="og:type" content="website"/> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> + <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> +</head> +<body> + +<div class="container-fluid"> + +<h1>NetData Custom Dashboard <div data-netdata="system.cpu" data-chart-library="sparkline" data-height="30" data-after="-600" data-sparkline-linecolor="#888"></div></h1> + +This is a template for building custom dashboards. To build a dashboard you just do this: + +<pre> +<!DOCTYPE html> +<html lang="en"> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> +</head> +<body> + <div data-netdata="system.processes" + data-chart-library="dygraph" + data-width="600" + data-height="200" + data-after="-600" + ></div> +</body> +<script type="text/javascript" src="http://netdata.server:19999/dashboard.js"></script> +</html> +</pre> + +<ul> + <li>You can host your dashboard anywhere.</li> + <li>You can add as many charts as you like.</li> + <li>You can have charts from many different netdata servers (add <pre>data-host="http://another.netdata.server:19999/"</pre> to each chart).</li> + <li>You can use different chart libraries on the same page: <b>peity</b>, <b>sparkline</b>, <b>dygraph</b>, <b>google</b></li> + <li>You can customize each chart to your preferences. For each chart library most of their attributes can be given in <b>data-</b> attributes.</li> + <li>Each chart can have each own duration - it is controlled with the <b>data-after</b> attribute to give that many seconds of data.</li> + <li>Depending on the width of the chart and <b>data-after</b> attribute, netdata will automatically refresh the chart when it needs to be updated. For example giving 600 pixels for width for -600 seconds of data, using a chart library that needs 3 pixels per point, will yeld in a chart updated once every 3 seconds.</li> +</ul> + + +<hr> +<h1>Sparkline Charts</h1> +Sparkline charts support 'NULL' values, so the charts can indicate that values are missing. +Sparkline charts stretch the values to show the variations between values in more detail. +They also have mouse-hover support. +<br/> +<b>Sparklines are fantastic</b>. You can inline charts in text. For example this + <div data-netdata="system.cpu" + data-chart-library="sparkline" + data-width="5%" + data-height="20" + data-after="-30" + ></div> is my current cpu usage (last 30 seconds), + while this + <div data-netdata="netdata.net" + data-dimensions="out" + data-chart-library="sparkline" + data-width="10%" + data-height="20" + data-after="-60" + ></div> is the bandwidth my netdata server is currently transmitting (last minute) + and this + <div data-netdata="netdata.requests" + data-chart-library="sparkline" + data-width="20%" + data-height="20" + data-after="-180" + ></div> is the requests/sec it serves (last 3 minutes). + +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time101" + ></div> + <br/> + <small>rendered in <span id="time101">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time102" + ></div> + <br/> + <small>rendered in <span id="time102">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time103" + ></div> + <br/> + <small>rendered in <span id="time103">X</span> ms</small> +</div> + + + +<hr> +<h1>Peity Charts</h1> +Peity charts do not support 'NULL' values, so the charts cannot indicate that values are missing. +Peity charts cannot have multiple dimensions on the charts - so netdata will use 'min2max' to show +the total of all dimensions. +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="peity" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time001" + ></div> + <br/> + <small>rendered in <span id="time001">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="peity" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time002" + ></div> + <br/> + <small>rendered in <span id="time002">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="peity" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time003" + ></div> + <br/> + <small>rendered in <span id="time003">X</span> ms</small> +</div> + + + + +<hr> +<h1>Dygraph Charts</h1> +The fastest charting engine that can chart complete charts (not just sparklines). +The charts are zoomable (drag their contents to pan, shift with mouse wheel to zoom-in or zoom-out, double click to reset it). +<b>Netdata magic!</b> Realtime charts on your web page! +<br/> +Sparklines using dygraphs + <div data-netdata="system.processes" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-legend="no" + data-width="15%" + data-height="20" + data-after="-300" + ></div> + are also possible! This + <div data-netdata="system.net" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-legend="no" + data-width="15%" + data-height="20" + data-after="-300" + ></div> + is an area chart, while this + <div data-netdata="system.cpu" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-legend="no" + data-width="15%" + data-height="20" + data-after="-300" + ></div> is a stacked area chart! + + +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time501" + ></div> + <br/> + <small>rendered in <span id="time501">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time502" + ></div> + <br/> + <small>rendered in <span id="time502">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-width="100%" + data-height="30" + data-after="-300" + data-dt-element-name="time503" + ></div> + <br/> + <small>rendered in <span id="time503">X</span> ms</small> +</div> + + + +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time201" + ></div> + <br/> + <small>rendered in <span id="time201">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time202" + ></div> + <br/> + <small>rendered in <span id="time202">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time203" + ></div> + <br/> + <small>rendered in <span id="time203">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.io" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time204" + ></div> + <br/> + <small>rendered in <span id="time204">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="apps.cpu" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time205" + ></div> + <br/> + <small>rendered in <span id="time205">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="netdata.net" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time206" + ></div> + <br/> + <small>rendered in <span id="time206">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="netdata.server_cpu" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time207" + ></div> + <br/> + <small>rendered in <span id="time207">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="netdata.requests" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time208" + ></div> + <br/> + <small>rendered in <span id="time208">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="net.gstag0" + data-chart-library="dygraph" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time209" + ></div> + <br/> + <small>rendered in <span id="time209">X</span> ms</small> +</div> + + + +<hr> +<h1>EasyPieChart</h1> +<br/> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.processes" + data-chart-library="easypiechart" + data-width="200" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time601" + ></div> + <br/> + <small>rendered in <span id="time601">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.processes" + data-chart-library="easypiechart" + data-width="150" + data-height="150" + data-after="-300" + data-points="150" + data-dt-element-name="time601a" + ></div> + <br/> + <small>rendered in <span id="time601a">X</span> ms</small> + </div> +</div> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.net" + data-chart-library="easypiechart" + data-width="200" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time602" + ></div> + <br/> + <small>rendered in <span id="time602">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.net" + data-chart-library="easypiechart" + data-width="100" + data-height="100" + data-after="-300" + data-points="150" + data-dt-element-name="time602a" + ></div> + <br/> + <small>rendered in <span id="time602a">X</span> ms</small> + </div> +</div> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.cpu" + data-chart-library="easypiechart" + data-width="200" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time603" + ></div> + <br/> + <small>rendered in <span id="time603">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.cpu" + data-chart-library="easypiechart" + data-width="75" + data-height="75" + data-after="-300" + data-points="150" + data-dt-element-name="time603a" + ></div> + <br/> + <small>rendered in <span id="time603a">X</span> ms</small> + </div> +</div> + + +<hr> +<h1>Gauge.js</h1> +<br/> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.processes" + data-chart-library="gauge" + data-width="250" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time701" + ></div> + <br/> + <small>rendered in <span id="time701">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.processes" + data-chart-library="gauge" + data-width="125" + data-height="100" + data-after="-300" + data-points="150" + data-dt-element-name="time701a" + ></div> + <br/> + <small>rendered in <span id="time701a">X</span> ms</small> + </div> +</div> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.net" + data-chart-library="gauge" + data-width="250" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time702" + ></div> + <br/> + <small>rendered in <span id="time702">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.net" + data-chart-library="gauge" + data-width="125" + data-height="100" + data-after="-300" + data-points="150" + data-dt-element-name="time702a" + ></div> + <br/> + <small>rendered in <span id="time702a">X</span> ms</small> + </div> +</div> +<div style="width: 33%; display: inline-block;"> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.cpu" + data-chart-library="gauge" + data-width="250" + data-height="200" + data-after="-300" + data-points="300" + data-dt-element-name="time703" + ></div> + <br/> + <small>rendered in <span id="time703">X</span> ms</small> + </div> + <div style="display: inline-block; position: relative;"> + <div data-netdata="system.cpu" + data-chart-library="gauge" + data-width="125" + data-height="100" + data-after="-300" + data-points="150" + data-dt-element-name="time703a" + ></div> + <br/> + <small>rendered in <span id="time703a">X</span> ms</small> + </div> +</div> + + +<hr> +<h1>Google Charts</h1> +NetData was originaly developed with Google Charts. +NetData is a complete Google Visualization API provider. +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="google" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time301" + ></div> + <br/> + <small>rendered in <span id="time301">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="google" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time302" + ></div> + <br/> + <small>rendered in <span id="time302">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="google" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time303" + ></div> + <br/> + <small>rendered in <span id="time303">X</span> ms</small> +</div> + +<!-- + +<hr> +<h1>Morris Charts</h1> +Unfortunatelly, Morris Charts are very slow. Here we force them to lower their detail to get acceptable results. +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="morris" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time401" + ></div> + <br/> + <small>rendered in <span id="time401">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="morris" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time402" + ></div> + <br/> + <small>rendered in <span id="time402">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="morris" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time403" + ></div> + <br/> + <small>rendered in <span id="time403">X</span> ms</small> +</div> + + +<hr> +<h1>C3 Charts</h1> +C3 charts are not usable in large scale. They suffer from the following issues: +<ul> + <li>extreme use of transitions (implemented with D3 instead of CSS, meaning they are javascript rendered) that cannot be disabled - even opacity is hardcoded in the javascript library</li> + <li>rendering is done with <code>SVG</code> instead of <code>canvas</code>, so they use DOM elements for every point, becomimg useless if more than 500 points are drawn</li> + <li>lack of a <code>raw</code> data format, so every time a chart is updated, data convertion in javascript is required</li> + <li>lack of <code>stacked</code> charts support</li> +</ul> +So, to avoid flashing the charts, we destroy and re-create the charts on each update. Also, since they manipulate the data with javascript we were forced to lower the detail they render to get acceptable speeds. +<br/> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.processes" + data-chart-library="c3" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time801" + ></div> + <br/> + <small>rendered in <span id="time801">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.net" + data-chart-library="c3" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time802" + ></div> + <br/> + <small>rendered in <span id="time802">X</span> ms</small> +</div> +<div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="c3" + data-width="100%" + data-height="200" + data-after="-300" + data-dt-element-name="time803" + ></div> + <br/> + <small>rendered in <span id="time803">X</span> ms</small> +</div> + +--> + + <hr> + <h1>d3pie Charts</h1> + <div style="width: 33%; display: inline-block;"> + <div data-netdata="apps.cpu" + data-chart-library="d3pie" + data-d3pie-pieinnerradius="70%" + data-d3pie-pieouterradius="90%" + data-width="100%" + data-height="300px" + data-after="-60" + data-points="60" + data-dt-element-name="time901" + ></div> + <br/> + <small>rendered in <span id="time901">X</span> ms</small> + </div> + + <div style="width: 33%; display: inline-block;"> + <div data-netdata="system.cpu" + data-chart-library="d3pie" + data-width="100%" + data-height="300px" + data-after="-60" + data-points="60" + data-dt-element-name="time902" + ></div> + <br/> + <small>rendered in <span id="time902">X</span> ms</small> + </div> + + <div style="width: 33%; display: inline-block;"> + <div data-netdata="apps.cpu" + data-width="100%" + data-height="300px" + data-after="-60" + data-points="60" + data-debug="false" + data-decimal-digits="0" + data-dt-element-name="time903" + ></div> + <br/> + <small>rendered in <span id="time903">X</span> ms</small> + </div> +</div> <!-- 1st container --> +</body> +</html> + +<!-- you can set your netdata server globally, by ucommenting this --> +<!-- you can also give a different server per chart, with the attribute: data-host="http://netdata.server:19999" --> +<!-- <script> netdataServer = "http://box:19999"; </script> --> + +<!-- load the dashboard manager - it will do the rest --> +<!-- <script>var netdataTheme = 'slate';</script> --> +<script type="text/javascript" src="dashboard.js?v20180130-1"></script> diff --git a/web/gui/dashboard.js b/web/gui/dashboard.js new file mode 100644 index 0000000..8fea625 --- /dev/null +++ b/web/gui/dashboard.js @@ -0,0 +1,10129 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +// DO NOT EDIT: This file is automatically generated from the source files in src/ + +// ---------------------------------------------------------------------------- +// You can set the following variables before loading this script: + +// 'use strict'; + +/*global netdataNoDygraphs *//* boolean, disable dygraph charts + * (default: false) */ +/*global netdataNoSparklines *//* boolean, disable sparkline charts + * (default: false) */ +/*global netdataNoPeitys *//* boolean, disable peity charts + * (default: false) */ +/*global netdataNoGoogleCharts *//* boolean, disable google charts + * (default: false) */ +/*global netdataNoMorris *//* boolean, disable morris charts + * (default: false) */ +/*global netdataNoEasyPieChart *//* boolean, disable easypiechart charts + * (default: false) */ +/*global netdataNoGauge *//* boolean, disable gauge.js charts + * (default: false) */ +/*global netdataNoD3 *//* boolean, disable d3 charts + * (default: false) */ +/*global netdataNoC3 *//* boolean, disable c3 charts + * (default: false) */ +/*global netdataNoD3pie *//* boolean, disable d3pie charts + * (default: false) */ +/*global netdataNoBootstrap *//* boolean, disable bootstrap - disables help too + * (default: false) */ +/*global netdataNoFontAwesome *//* boolean, disable fontawesome (do not load it) + * (default: false) */ +/*global netdataIcons *//* object, overwrite netdata fontawesome icons + * (default: null) */ +/*global netdataDontStart *//* boolean, do not start the thread to process the charts + * (default: false) */ +/*global netdataErrorCallback *//* function, callback to be called when the dashboard encounters an error + * (default: null) */ +/*global netdataRegistry:true *//* boolean, use the netdata registry + * (default: false) */ +/*global netdataNoRegistry *//* boolean, included only for compatibility with existing custom dashboard + * (obsolete - do not use this any more) */ +/*global netdataRegistryCallback *//* function, callback that will be invoked with one param: the URLs from the registry + * (default: null) */ +/*global netdataShowHelp:true *//* boolean, disable charts help + * (default: true) */ +/*global netdataShowAlarms:true *//* boolean, enable alarms checks and notifications + * (default: false) */ +/*global netdataRegistryAfterMs:true *//* ms, delay registry use at started + * (default: 1500) */ +/*global netdataCallback *//* function, callback to be called when netdata is ready to start + * (default: null) + * netdata will be running while this is called + * (call NETDATA.pause to stop it) */ +/*global netdataPrepCallback *//* function, callback to be called before netdata does anything else + * (default: null) */ +/*global netdataServer *//* string, the URL of the netdata server to use + * (default: the URL the page is hosted at) */ +/*global netdataServerStatic *//* string, the URL of the netdata server to use for static files + * (default: netdataServer) */ +/*global netdataSnapshotData *//* object, a netdata snapshot loaded + * (default: null) */ +/*global netdataAlarmsRecipients *//* array, an array of alarm recipients to show notifications for + * (default: null) */ +/*global netdataAlarmsRemember *//* boolen, keep our position in the alarm log at browser local storage + * (default: true) */ +/*global netdataAlarmsActiveCallback *//* function, a hook for the alarm logs + * (default: undefined) */ +/*global netdataAlarmsNotifCallback *//* function, a hook for alarm notifications + * (default: undefined) */ +/*global netdataIntersectionObserver *//* boolean, enable or disable the use of intersection observer + * (default: true) */ +/*global netdataCheckXSS *//* boolean, enable or disable checking for XSS issues + * (default: false) */ + +// ---------------------------------------------------------------------------- +// global namespace + +// Should stay var! +var NETDATA = window.NETDATA || {}; + +(function(window, document, $, undefined) { + +// *** src/dashboard.js/utils.js + +NETDATA.name2id = function (s) { + return s + .replace(/ /g, '_') + .replace(/:/g, '_') + .replace(/\(/g, '_') + .replace(/\)/g, '_') + .replace(/\./g, '_') + .replace(/\//g, '_'); +}; + +NETDATA.encodeURIComponent = function (s) { + if (typeof(s) === 'string') { + return encodeURIComponent(s); + } + + return s; +}; + +/// A heuristic for detecting slow devices. +let isSlowDeviceResult = undefined; +const isSlowDevice = function () { + if (!isSlowDeviceResult) { + return isSlowDeviceResult; + } + + try { + let ua = navigator.userAgent.toLowerCase(); + + let iOS = /ipad|iphone|ipod/.test(ua) && !window.MSStream; + let android = /android/.test(ua) && !window.MSStream; + isSlowDeviceResult = (iOS || android); + } catch (e) { + isSlowDeviceResult = false; + } + + return isSlowDeviceResult; +}; + +NETDATA.guid = function () { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); +}; + +NETDATA.zeropad = function (x) { + if (x > -10 && x < 10) { + return '0' + x.toString(); + } else { + return x.toString(); + } +}; + +NETDATA.seconds4human = function (seconds, options) { + let defaultOptions = { + now: 'now', + space: ' ', + negative_suffix: 'ago', + day: 'day', + days: 'days', + hour: 'hour', + hours: 'hours', + minute: 'min', + minutes: 'mins', + second: 'sec', + seconds: 'secs', + and: 'and' + }; + + if (typeof options !== 'object') { + options = defaultOptions; + } else { + for (var x in defaultOptions) { + if (typeof options[x] !== 'string') { + options[x] = defaultOptions[x]; + } + } + } + + if (typeof seconds === 'string') { + seconds = parseInt(seconds, 10); + } + + if (seconds === 0) { + return options.now; + } + + let suffix = ''; + if (seconds < 0) { + seconds = -seconds; + if (options.negative_suffix !== '') { + suffix = options.space + options.negative_suffix; + } + } + + let days = Math.floor(seconds / 86400); + seconds -= (days * 86400); + + let hours = Math.floor(seconds / 3600); + seconds -= (hours * 3600); + + let minutes = Math.floor(seconds / 60); + seconds -= (minutes * 60); + + let strings = []; + + if (days > 1) { + strings.push(days.toString() + options.space + options.days); + } else if (days === 1) { + strings.push(days.toString() + options.space + options.day); + } + + if (hours > 1) { + strings.push(hours.toString() + options.space + options.hours); + } else if (hours === 1) { + strings.push(hours.toString() + options.space + options.hour); + } + + if (minutes > 1) { + strings.push(minutes.toString() + options.space + options.minutes); + } else if (minutes === 1) { + strings.push(minutes.toString() + options.space + options.minute); + } + + if (seconds > 1) { + strings.push(Math.floor(seconds).toString() + options.space + options.seconds); + } else if (seconds === 1) { + strings.push(Math.floor(seconds).toString() + options.space + options.second); + } + + if (strings.length === 1) { + return strings.pop() + suffix; + } + + let last = strings.pop(); + return strings.join(", ") + " " + options.and + " " + last + suffix; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// element data attributes + +NETDATA.dataAttribute = function (element, attribute, def) { + let key = 'data-' + attribute.toString(); + if (element.hasAttribute(key)) { + let data = element.getAttribute(key); + + if (data === 'true') { + return true; + } + if (data === 'false') { + return false; + } + if (data === 'null') { + return null; + } + + // Only convert to a number if it doesn't change the string + if (data === +data + '') { + return +data; + } + + if (/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/.test(data)) { + return JSON.parse(data); + } + + return data; + } else { + return def; + } +}; + +NETDATA.dataAttributeBoolean = function (element, attribute, def) { + let value = NETDATA.dataAttribute(element, attribute, def); + + if (value === true || value === false) // gmosx: Love this :) + { + return value; + } + + if (typeof(value) === 'string') { + if (value === 'yes' || value === 'on') { + return true; + } + + if (value === '' || value === 'no' || value === 'off' || value === 'null') { + return false; + } + + return def; + } + + if (typeof(value) === 'number') { + return value !== 0; + } + + return def; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// fast numbers formatting + +NETDATA.fastNumberFormat = { + formattersFixed: [], + formattersZeroBased: [], + + // this is the fastest and the preferred + getIntlNumberFormat: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + + return this.formattersZeroBased[key]; + } else { + // this is never used + // it is added just for completeness + return new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }, + + // this respects locale + getLocaleString: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + + return this.formattersZeroBased[key]; + } else { + return { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + }, + + // the fallback + getFixed: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + + return this.formattersZeroBased[key]; + } else { + return { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + }, + + testIntlNumberFormat: function () { + let value = 1.12345; + let e1 = "1.12", e2 = "1,12"; + let s = ""; + + try { + let x = new Intl.NumberFormat(undefined, { + useGrouping: true, + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + + s = x.format(value); + } catch (e) { + s = ""; + } + + // console.log('NumberFormat: ', s); + return (s === e1 || s === e2); + }, + + testLocaleString: function () { + let value = 1.12345; + let e1 = "1.12", e2 = "1,12"; + let s = ""; + + try { + s = value.toLocaleString(undefined, { + useGrouping: true, + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + } catch (e) { + s = ""; + } + + // console.log('localeString: ', s); + return (s === e1 || s === e2); + }, + + // on first run we decide which formatter to use + get: function (min, max) { + if (this.testIntlNumberFormat()) { + // console.log('numberformat'); + this.get = this.getIntlNumberFormat; + } else if (this.testLocaleString()) { + // console.log('localestring'); + this.get = this.getLocaleString; + } else { + // console.log('fixed'); + this.get = this.getFixed; + } + return this.get(min, max); + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// Detect the netdata server + +// http://stackoverflow.com/questions/984510/what-is-my-script-src-url +// http://stackoverflow.com/questions/6941533/get-protocol-domain-and-port-from-url +NETDATA._scriptSource = function () { + let script = null; + + if (typeof document.currentScript !== 'undefined') { + script = document.currentScript; + } else { + const all_scripts = document.getElementsByTagName('script'); + script = all_scripts[all_scripts.length - 1]; + } + + if (typeof script.getAttribute.length !== 'undefined') { + script = script.src; + } else { + script = script.getAttribute('src', -1); + } + + return script; +}; + +// *** src/dashboard.js/server-detection.js + +if (typeof netdataServer !== 'undefined') { + NETDATA.serverDefault = netdataServer; +} else { + let s = NETDATA._scriptSource(); + if (s) { + NETDATA.serverDefault = s.replace(/\/dashboard.js(\?.*)?$/g, ""); + } else { + console.log('WARNING: Cannot detect the URL of the netdata server.'); + NETDATA.serverDefault = null; + } +} + +if (NETDATA.serverDefault === null) { + NETDATA.serverDefault = ''; +} else if (NETDATA.serverDefault.slice(-1) !== '/') { + NETDATA.serverDefault += '/'; +} + +if (typeof netdataServerStatic !== 'undefined' && netdataServerStatic !== null && netdataServerStatic !== '') { + NETDATA.serverStatic = netdataServerStatic; + if (NETDATA.serverStatic.slice(-1) !== '/') { + NETDATA.serverStatic += '/'; + } +} else { + NETDATA.serverStatic = NETDATA.serverDefault; +} + +// *** src/dashboard.js/dependencies.js + +// default URLs for all the external files we need +// make them RELATIVE so that the whole thing can also be +// installed under a web server +NETDATA.jQuery = NETDATA.serverStatic + 'lib/jquery-2.2.4.min.js'; +NETDATA.peity_js = NETDATA.serverStatic + 'lib/jquery.peity-3.2.0.min.js'; +NETDATA.sparkline_js = NETDATA.serverStatic + 'lib/jquery.sparkline-2.1.2.min.js'; +NETDATA.easypiechart_js = NETDATA.serverStatic + 'lib/jquery.easypiechart-97b5824.min.js'; +NETDATA.gauge_js = NETDATA.serverStatic + 'lib/gauge-1.3.2.min.js'; +NETDATA.dygraph_js = NETDATA.serverStatic + 'lib/dygraph-c91c859.min.js'; +NETDATA.dygraph_smooth_js = NETDATA.serverStatic + 'lib/dygraph-smooth-plotter-c91c859.js'; +// NETDATA.raphael_js = NETDATA.serverStatic + 'lib/raphael-2.2.4-min.js'; +// NETDATA.c3_js = NETDATA.serverStatic + 'lib/c3-0.4.18.min.js'; +// NETDATA.c3_css = NETDATA.serverStatic + 'css/c3-0.4.18.min.css'; +NETDATA.d3pie_js = NETDATA.serverStatic + 'lib/d3pie-0.2.1-netdata-3.js'; +NETDATA.d3_js = NETDATA.serverStatic + 'lib/d3-4.12.2.min.js'; +// NETDATA.morris_js = NETDATA.serverStatic + 'lib/morris-0.5.1.min.js'; +// NETDATA.morris_css = NETDATA.serverStatic + 'css/morris-0.5.1.css'; +NETDATA.google_js = 'https://www.google.com/jsapi'; +// Error Handling + +NETDATA.errorCodes = { + 100: {message: "Cannot load chart library", alert: true}, + 101: {message: "Cannot load jQuery", alert: true}, + 402: {message: "Chart library not found", alert: false}, + 403: {message: "Chart library not enabled/is failed", alert: false}, + 404: {message: "Chart not found", alert: false}, + 405: {message: "Cannot download charts index from server", alert: true}, + 406: {message: "Invalid charts index downloaded from server", alert: true}, + 407: {message: "Cannot HELLO netdata server", alert: false}, + 408: {message: "Netdata servers sent invalid response to HELLO", alert: false}, + 409: {message: "Cannot ACCESS netdata registry", alert: false}, + 410: {message: "Netdata registry ACCESS failed", alert: false}, + 411: {message: "Netdata registry server send invalid response to DELETE ", alert: false}, + 412: {message: "Netdata registry DELETE failed", alert: false}, + 413: {message: "Netdata registry server send invalid response to SWITCH ", alert: false}, + 414: {message: "Netdata registry SWITCH failed", alert: false}, + 415: {message: "Netdata alarms download failed", alert: false}, + 416: {message: "Netdata alarms log download failed", alert: false}, + 417: {message: "Netdata registry server send invalid response to SEARCH ", alert: false}, + 418: {message: "Netdata registry SEARCH failed", alert: false} +}; + +NETDATA.errorLast = { + code: 0, + message: "", + datetime: 0 +}; + +NETDATA.error = function (code, msg) { + NETDATA.errorLast.code = code; + NETDATA.errorLast.message = msg; + NETDATA.errorLast.datetime = Date.now(); + + console.log("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg); + + let ret = true; + if (typeof netdataErrorCallback === 'function') { + ret = netdataErrorCallback('system', code, msg); + } + + if (ret && NETDATA.errorCodes[code].alert) { + alert("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg); + } +}; + +NETDATA.errorReset = function () { + NETDATA.errorLast.code = 0; + NETDATA.errorLast.message = "You are doing fine!"; + NETDATA.errorLast.datetime = 0; +}; +// *** src/dashboard.js/compatibility.js + +// Compatibility fixes. + +// fix IE issue with console +if (!window.console) { + window.console = { + log: function () { + } + }; +} + +// if string.endsWith is not defined, define it +if (typeof String.prototype.endsWith !== 'function') { + String.prototype.endsWith = function (s) { + if (s.length > this.length) { + return false; + } + return this.slice(-s.length) === s; + }; +} + +// if string.startsWith is not defined, define it +if (typeof String.prototype.startsWith !== 'function') { + String.prototype.startsWith = function (s) { + if (s.length > this.length) { + return false; + } + return this.slice(s.length) === s; + }; +} +// ---------------------------------------------------------------------------------------------------------------- +// XSS checks + +NETDATA.xss = { + enabled: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS, + enabled_for_data: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS, + + string: function (s) { + return s.toString() + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }, + + object: function (name, obj, ignore_regex) { + if (typeof ignore_regex !== 'undefined' && ignore_regex.test(name)) { + // console.log('XSS: ignoring "' + name + '"'); + return obj; + } + + switch (typeof(obj)) { + case 'string': + const ret = this.string(obj); + if (ret !== obj) { + console.log('XSS protection changed string ' + name + ' from "' + obj + '" to "' + ret + '"'); + } + return ret; + + case 'object': + if (obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + // console.log('checking array "' + name + '"'); + + let len = obj.length; + while (len--) { + obj[len] = this.object(name + '[' + len + ']', obj[len], ignore_regex); + } + } else { + // console.log('checking object "' + name + '"'); + + for (var i in obj) { + if (obj.hasOwnProperty(i) === false) { + continue; + } + if (this.string(i) !== i) { + console.log('XSS protection removed invalid object member "' + name + '.' + i + '"'); + delete obj[i]; + } else { + obj[i] = this.object(name + '.' + i, obj[i], ignore_regex); + } + } + } + return obj; + + default: + return obj; + } + }, + + checkOptional: function (name, obj, ignore_regex) { + if (this.enabled) { + //console.log('XSS: checking optional "' + name + '"...'); + return this.object(name, obj, ignore_regex); + } + return obj; + }, + + checkAlways: function (name, obj, ignore_regex) { + //console.log('XSS: checking always "' + name + '"...'); + return this.object(name, obj, ignore_regex); + }, + + checkData: function (name, obj, ignore_regex) { + if (this.enabled_for_data) { + //console.log('XSS: checking data "' + name + '"...'); + return this.object(name, obj, ignore_regex); + } + return obj; + } +}; +NETDATA.colorHex2Rgb = function (hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function (m, r, g, b) { + return r + r + g + g + b + b; + }); + + let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +}; + +NETDATA.colorLuminance = function (hex, lum) { + // validate hex string + hex = String(hex).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + lum = lum || 0; + + // convert to decimal and change luminosity + let rgb = "#"; + for (let i = 0; i < 3; i++) { + let c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb += ("00" + c).substr(c.length); + } + + return rgb; +}; +NETDATA.unitsConversion = { + keys: {}, // keys for data-common-units + latest: {}, // latest selected units for data-common-units + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + scalableUnits: { + 'packets/s': { + 'pps': 1, + 'Kpps': 1000, + 'Mpps': 1000000 + }, + 'pps': { + 'pps': 1, + 'Kpps': 1000, + 'Mpps': 1000000 + }, + 'kilobits/s': { + 'bits/s': 1 / 1000, + 'kilobits/s': 1, + 'megabits/s': 1000, + 'gigabits/s': 1000000, + 'terabits/s': 1000000000 + }, + 'kilobytes/s': { + 'bytes/s': 1 / 1024, + 'kilobytes/s': 1, + 'megabytes/s': 1024, + 'gigabytes/s': 1024 * 1024, + 'terabytes/s': 1024 * 1024 * 1024 + }, + 'KB/s': { + 'B/s': 1 / 1024, + 'KB/s': 1, + 'MB/s': 1024, + 'GB/s': 1024 * 1024, + 'TB/s': 1024 * 1024 * 1024 + }, + 'KiB/s': { + 'B/s': 1 / 1024, + 'KiB/s': 1, + 'MiB/s': 1024, + 'GiB/s': 1024 * 1024, + 'TiB/s': 1024 * 1024 * 1024 + }, + 'B': { + 'B': 1, + 'KiB': 1024, + 'MiB': 1024 * 1024, + 'GiB': 1024 * 1024 * 1024, + 'TiB': 1024 * 1024 * 1024 * 1024, + 'PiB': 1024 * 1024 * 1024 * 1024 * 1024 + }, + 'KB': { + 'B': 1 / 1024, + 'KB': 1, + 'MB': 1024, + 'GB': 1024 * 1024, + 'TB': 1024 * 1024 * 1024 + }, + 'KiB': { + 'B': 1 / 1024, + 'KiB': 1, + 'MiB': 1024, + 'GiB': 1024 * 1024, + 'TiB': 1024 * 1024 * 1024 + }, + 'MB': { + 'B': 1 / (1024 * 1024), + 'KB': 1 / 1024, + 'MB': 1, + 'GB': 1024, + 'TB': 1024 * 1024, + 'PB': 1024 * 1024 * 1024 + }, + 'MiB': { + 'B': 1 / (1024 * 1024), + 'KiB': 1 / 1024, + 'MiB': 1, + 'GiB': 1024, + 'TiB': 1024 * 1024, + 'PiB': 1024 * 1024 * 1024 + }, + 'GB': { + 'B': 1 / (1024 * 1024 * 1024), + 'KB': 1 / (1024 * 1024), + 'MB': 1 / 1024, + 'GB': 1, + 'TB': 1024, + 'PB': 1024 * 1024, + 'EB': 1024 * 1024 * 1024 + }, + 'GiB': { + 'B': 1 / (1024 * 1024 * 1024), + 'KiB': 1 / (1024 * 1024), + 'MiB': 1 / 1024, + 'GiB': 1, + 'TiB': 1024, + 'PiB': 1024 * 1024, + 'EiB': 1024 * 1024 * 1024 + } + /* + 'milliseconds': { + 'seconds': 1000 + }, + 'seconds': { + 'milliseconds': 0.001, + 'seconds': 1, + 'minutes': 60, + 'hours': 3600, + 'days': 86400 + } + */ + }, + + convertibleUnits: { + 'Celsius': { + 'Fahrenheit': { + check: function (max) { + void(max); + return NETDATA.options.current.temperature === 'fahrenheit'; + }, + convert: function (value) { + return value * 9 / 5 + 32; + } + } + }, + 'celsius': { + 'fahrenheit': { + check: function (max) { + void(max); + return NETDATA.options.current.temperature === 'fahrenheit'; + }, + convert: function (value) { + return value * 9 / 5 + 32; + } + } + }, + 'seconds': { + 'time': { + check: function (max) { + void(max); + return NETDATA.options.current.seconds_as_time; + }, + convert: function (seconds) { + return NETDATA.unitsConversion.seconds2time(seconds); + } + } + }, + 'milliseconds': { + 'milliseconds': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max < 1000; + }, + convert: function (milliseconds) { + let tms = Math.round(milliseconds * 10); + milliseconds = Math.floor(tms / 10); + + tms -= milliseconds * 10; + + return (milliseconds).toString() + '.' + tms.toString(); + } + }, + 'seconds': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max >= 1000 && max < 60000; + }, + convert: function (milliseconds) { + milliseconds = Math.round(milliseconds); + + let seconds = Math.floor(milliseconds / 1000); + milliseconds -= seconds * 1000; + + milliseconds = Math.round(milliseconds / 10); + + return seconds.toString() + '.' + + NETDATA.zeropad(milliseconds); + } + }, + 'M:SS.ms': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max >= 60000; + }, + convert: function (milliseconds) { + milliseconds = Math.round(milliseconds); + + let minutes = Math.floor(milliseconds / 60000); + milliseconds -= minutes * 60000; + + let seconds = Math.floor(milliseconds / 1000); + milliseconds -= seconds * 1000; + + milliseconds = Math.round(milliseconds / 10); + + return minutes.toString() + ':' + + NETDATA.zeropad(seconds) + '.' + + NETDATA.zeropad(milliseconds); + } + } + } + }, + + seconds2time: function (seconds) { + seconds = Math.abs(seconds); + + let days = Math.floor(seconds / 86400); + seconds -= days * 86400; + + let hours = Math.floor(seconds / 3600); + seconds -= hours * 3600; + + let minutes = Math.floor(seconds / 60); + seconds -= minutes * 60; + + seconds = Math.round(seconds); + + let ms_txt = ''; + /* + let ms = seconds - Math.floor(seconds); + seconds -= ms; + ms = Math.round(ms * 1000); + + if (ms > 1) { + if (ms < 10) + ms_txt = '.00' + ms.toString(); + else if (ms < 100) + ms_txt = '.0' + ms.toString(); + else + ms_txt = '.' + ms.toString(); + } + */ + + return ((days > 0) ? days.toString() + 'd:' : '').toString() + + NETDATA.zeropad(hours) + ':' + + NETDATA.zeropad(minutes) + ':' + + NETDATA.zeropad(seconds) + + ms_txt; + }, + + // get a function that converts the units + // + every time units are switched call the callback + get: function (uuid, min, max, units, desired_units, common_units_name, switch_units_callback) { + // validate the parameters + if (typeof units === 'undefined') { + units = 'undefined'; + } + + // check if we support units conversion + if (typeof this.scalableUnits[units] === 'undefined' && typeof this.convertibleUnits[units] === 'undefined') { + // we can't convert these units + //console.log('DEBUG: ' + uuid.toString() + ' can\'t convert units: ' + units.toString()); + return function (value) { + return value; + }; + } + + // check if the caller wants the original units + if (typeof desired_units === 'undefined' || desired_units === null || desired_units === 'original' || desired_units === units) { + //console.log('DEBUG: ' + uuid.toString() + ' original units wanted'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + + // now we know we can convert the units + // and the caller wants some kind of conversion + + let tunits = null; + let tdivider = 0; + + if (typeof this.scalableUnits[units] !== 'undefined') { + // units that can be scaled + // we decide a divider + + // console.log('NETDATA.unitsConversion.get(' + units.toString() + ', ' + desired_units.toString() + ', function()) decide divider with min = ' + min.toString() + ', max = ' + max.toString()); + + if (desired_units === 'auto') { + // the caller wants to auto-scale the units + + // find the absolute maximum value that is rendered on the chart + // based on this we decide the scale + min = Math.abs(min); + max = Math.abs(max); + if (min > max) { + max = min; + } + + // find the smallest scale that provides integers + // for (x in this.scalableUnits[units]) { + // if (this.scalableUnits[units].hasOwnProperty(x)) { + // let m = this.scalableUnits[units][x]; + // if (m <= max && m > tdivider) { + // tunits = x; + // tdivider = m; + // } + // } + // } + const sunit = this.scalableUnits[units]; + for (var x of Object.keys(sunit)) { + let m = sunit[x]; + if (m <= max && m > tdivider) { + tunits = x; + tdivider = m; + } + } + + if (tunits === null || tdivider <= 0) { + // we couldn't find one + //console.log('DEBUG: ' + uuid.toString() + ' cannot find an auto-scaling candidate for units: ' + units.toString() + ' (max: ' + max.toString() + ')'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + + if (typeof common_units_name === 'string' && typeof uuid === 'string') { + // the caller wants several charts to have the same units + // data-common-units + + let common_units_key = common_units_name + '-' + units; + + // add our divider into the list of keys + let t = this.keys[common_units_key]; + if (typeof t === 'undefined') { + this.keys[common_units_key] = {}; + t = this.keys[common_units_key]; + } + t[uuid] = { + units: tunits, + divider: tdivider + }; + + // find the max divider of all charts + let common_units = t[uuid]; + for (var x in t) { + if (t.hasOwnProperty(x) && t[x].divider > common_units.divider) { + common_units = t[x]; + } + } + + // save our common_max to the latest keys + let latest = this.latest[common_units_key]; + if (typeof latest === 'undefined') { + this.latest[common_units_key] = {}; + latest = this.latest[common_units_key]; + } + latest.units = common_units.units; + latest.divider = common_units.divider; + + tunits = latest.units; + tdivider = latest.divider; + + //console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + tunits.toString() + ' with divider ' + tdivider.toString() + ', common-units=' + common_units_name.toString() + ((t[uuid].divider !== tdivider)?' USED COMMON, mine was ' + t[uuid].units:' set common').toString()); + + // apply it to this chart + switch_units_callback(tunits); + return function (value) { + if (tdivider !== latest.divider) { + // another chart switched our common units + // we should switch them too + //console.log('DEBUG: ' + uuid + ' switching units due to a common-units change, from ' + tunits.toString() + ' to ' + latest.units.toString()); + tunits = latest.units; + tdivider = latest.divider; + switch_units_callback(tunits); + } + + return value / tdivider; + }; + } else { + // the caller did not give data-common-units + // this chart auto-scales independently of all others + //console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + tunits.toString() + ' with divider ' + tdivider.toString() + ', autonomously'); + + switch_units_callback(tunits); + return function (value) { + return value / tdivider; + }; + } + } else { + // the caller wants specific units + + if (typeof this.scalableUnits[units][desired_units] !== 'undefined') { + // all good, set the new units + tdivider = this.scalableUnits[units][desired_units]; + // console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + desired_units.toString() + ' with divider ' + tdivider.toString() + ', by reference'); + switch_units_callback(desired_units); + return function (value) { + return value / tdivider; + }; + } else { + // oops! switch back to original units + console.log('Units conversion from ' + units.toString() + ' to ' + desired_units.toString() + ' is not supported.'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } + } else if (typeof this.convertibleUnits[units] !== 'undefined') { + // units that can be converted + if (desired_units === 'auto') { + for (var x in this.convertibleUnits[units]) { + if (this.convertibleUnits[units].hasOwnProperty(x)) { + if (this.convertibleUnits[units][x].check(max)) { + //console.log('DEBUG: ' + uuid.toString() + ' converting ' + units.toString() + ' to: ' + x.toString()); + switch_units_callback(x); + return this.convertibleUnits[units][x].convert; + } + } + } + + // none checked ok + //console.log('DEBUG: ' + uuid.toString() + ' no conversion available for ' + units.toString() + ' to: ' + desired_units.toString()); + switch_units_callback(units); + return function (value) { + return value; + }; + } else if (typeof this.convertibleUnits[units][desired_units] !== 'undefined') { + switch_units_callback(desired_units); + return this.convertibleUnits[units][desired_units].convert; + } else { + console.log('Units conversion from ' + units.toString() + ' to ' + desired_units.toString() + ' is not supported.'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } else { + // hm... did we forget to implement the new type? + console.log(`Unmatched unit conversion method for units ${units.toString()}`); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } +}; + +NETDATA.icons = { + left: '<i class="fas fa-backward"></i>', + reset: '<i class="fas fa-play"></i>', + right: '<i class="fas fa-forward"></i>', + zoomIn: '<i class="fas fa-plus"></i>', + zoomOut: '<i class="fas fa-minus"></i>', + resize: '<i class="fas fa-sort"></i>', + lineChart: '<i class="fas fa-chart-line"></i>', + areaChart: '<i class="fas fa-chart-area"></i>', + noChart: '<i class="fas fa-chart-area"></i>', + loading: '<i class="fas fa-sync-alt"></i>', + noData: '<i class="fas fa-exclamation-triangle"></i>' +}; + +if (typeof netdataIcons === 'object') { + // for (let icon in NETDATA.icons) { + // if (NETDATA.icons.hasOwnProperty(icon) && typeof(netdataIcons[icon]) === 'string') + // NETDATA.icons[icon] = netdataIcons[icon]; + // } + for (var icon of Object.keys(NETDATA.icons)) { + if (typeof(netdataIcons[icon]) === 'string') { + NETDATA.icons[icon] = netdataIcons[icon] + } + } +} + +if (typeof netdataSnapshotData === 'undefined') { + netdataSnapshotData = null; +} + +if (typeof netdataShowHelp === 'undefined') { + netdataShowHelp = true; +} + +if (typeof netdataShowAlarms === 'undefined') { + netdataShowAlarms = false; +} + +if (typeof netdataRegistryAfterMs !== 'number' || netdataRegistryAfterMs < 0) { + netdataRegistryAfterMs = 0; // 1500; +} + +if (typeof netdataRegistry === 'undefined') { + // backward compatibility + netdataRegistry = (typeof netdataNoRegistry !== 'undefined' && netdataNoRegistry === false); +} + +if (netdataRegistry === false && typeof netdataRegistryCallback === 'function') { + netdataRegistry = true; +} + +// ---------------------------------------------------------------------------------------------------------------- +// the defaults for all charts + +// if the user does not specify any of these, the following will be used + +NETDATA.chartDefaults = { + width: '100%', // the chart width - can be null + height: '100%', // the chart height - can be null + min_width: null, // the chart minimum width - can be null + library: 'dygraph', // the graphing library to use + method: 'average', // the grouping method + before: 0, // panning + after: -600, // panning + pixels_per_point: 1, // the detail of the chart + fill_luminance: 0.8 // luminance of colors in solid areas +}; + +// ---------------------------------------------------------------------------------------------------------------- +// global options + +NETDATA.options = { + pauseCallback: null, // a callback when we are really paused + + pause: false, // when enabled we don't auto-refresh the charts + + targets: [], // an array of all the state objects that are + // currently active (independently of their + // viewport visibility) + + updated_dom: true, // when true, the DOM has been updated with + // new elements we have to check. + + auto_refresher_fast_weight: 0, // this is the current time in ms, spent + // rendering charts continuously. + // used with .current.fast_render_timeframe + + page_is_visible: true, // when true, this page is visible + + auto_refresher_stop_until: 0, // timestamp in ms - used internally, to stop the + // auto-refresher for some time (when a chart is + // performing pan or zoom, we need to stop refreshing + // all other charts, to have the maximum speed for + // rendering the chart that is panned or zoomed). + // Used with .current.global_pan_sync_time + + on_scroll_refresher_stop_until: 0, // timestamp in ms - used to stop evaluating + // charts for some time, after a page scroll + + last_page_resize: Date.now(), // the timestamp of the last resize request + + last_page_scroll: 0, // the timestamp the last time the page was scrolled + + browser_timezone: 'unknown', // timezone detected by javascript + server_timezone: 'unknown', // timezone reported by the server + + force_data_points: 0, // force the number of points to be returned for charts + fake_chart_rendering: false, // when set to true, the dashboard will download data but will not render the charts + + passive_events: null, // true if the browser supports passive events + + // the current profile + // we may have many... + current: { + units: 'auto', // can be 'auto' or 'original' + temperature: 'celsius', // can be 'celsius' or 'fahrenheit' + seconds_as_time: true, // show seconds as DDd:HH:MM:SS ? + timezone: 'default', // the timezone to use, or 'default' + user_set_server_timezone: 'default', // as set by the user on the dashboard + + legend_toolbox: true, // show the legend toolbox on charts + resize_charts: true, // show the resize handler on charts + + pixels_per_point: isSlowDevice() ? 5 : 1, // the minimum pixels per point for all charts + // increase this to speed javascript up + // each chart library has its own limit too + // the max of this and the chart library is used + // the final is calculated every time, so a change + // here will have immediate effect on the next chart + // update + + idle_between_charts: 100, // ms - how much time to wait between chart updates + + fast_render_timeframe: 200, // ms - render continuously until this time of continuous + // rendering has been reached + // this setting is used to make it render e.g. 10 + // charts at once, sleep idle_between_charts time + // and continue for another 10 charts. + + idle_between_loops: 500, // ms - if all charts have been updated, wait this + // time before starting again. + + idle_parallel_loops: 100, // ms - the time between parallel refresher updates + + idle_lost_focus: 500, // ms - when the window does not have focus, check + // if focus has been regained, every this time + + global_pan_sync_time: 300, // ms - when you pan or zoom a chart, the background + // auto-refreshing of charts is paused for this amount + // of time + + sync_selection_delay: 400, // ms - when you pan or zoom a chart, wait this amount + // of time before setting up synchronized selections + // on hover. + + sync_selection: true, // enable or disable selection sync + + pan_and_zoom_delay: 50, // when panning or zooming, how ofter to update the chart + + sync_pan_and_zoom: true, // enable or disable pan and zoom sync + + pan_and_zoom_data_padding: true, // fetch more data for the master chart when panning or zooming + + update_only_visible: true, // enable or disable visibility management / used for printing + + parallel_refresher: !isSlowDevice(), // enable parallel refresh of charts + + concurrent_refreshes: true, // when parallel_refresher is enabled, sync also the charts + + destroy_on_hide: isSlowDevice(), // destroy charts when they are not visible + + show_help: netdataShowHelp, // when enabled the charts will show some help + show_help_delay_show_ms: 500, + show_help_delay_hide_ms: 0, + + eliminate_zero_dimensions: true, // do not show dimensions with just zeros + + stop_updates_when_focus_is_lost: true, // boolean - shall we stop auto-refreshes when document does not have user focus + stop_updates_while_resizing: 1000, // ms - time to stop auto-refreshes while resizing the charts + + double_click_speed: 500, // ms - time between clicks / taps to detect double click/tap + + smooth_plot: !isSlowDevice(), // enable smooth plot, where possible + + color_fill_opacity_line: 1.0, + color_fill_opacity_area: 0.2, + color_fill_opacity_stacked: 0.8, + + pan_and_zoom_factor: 0.25, // the increment when panning and zooming with the toolbox + pan_and_zoom_factor_multiplier_control: 2.0, + pan_and_zoom_factor_multiplier_shift: 3.0, + pan_and_zoom_factor_multiplier_alt: 4.0, + + abort_ajax_on_scroll: false, // kill pending ajax page scroll + async_on_scroll: false, // sync/async onscroll handler + onscroll_worker_duration_threshold: 30, // time in ms, for async scroll handler + + retries_on_data_failures: 3, // how many retries to make if we can't fetch chart data from the server + + setOptionCallback: function () { + } + }, + + debug: { + show_boxes: false, + main_loop: false, + focus: false, + visibility: false, + chart_data_url: false, + chart_errors: true, // remember to set it to false before merging + chart_timing: false, + chart_calls: false, + libraries: false, + dygraph: false, + globalSelectionSync: false, + globalPanAndZoom: false + } +}; + +NETDATA.statistics = { + refreshes_total: 0, + refreshes_active: 0, + refreshes_active_max: 0 +}; + +// local storage options + +NETDATA.localStorage = { + default: {}, + current: {}, + callback: {} // only used for resetting back to defaults +}; + +NETDATA.localStorageTested = -1; +NETDATA.localStorageTest = function () { + if (NETDATA.localStorageTested !== -1) { + return NETDATA.localStorageTested; + } + + if (typeof Storage !== "undefined" && typeof localStorage === 'object') { + let test = 'test'; + try { + localStorage.setItem(test, test); + localStorage.removeItem(test); + NETDATA.localStorageTested = true; + } catch (e) { + NETDATA.localStorageTested = false; + } + } else { + NETDATA.localStorageTested = false; + } + + return NETDATA.localStorageTested; +}; + +NETDATA.localStorageGet = function (key, def, callback) { + let ret = def; + + if (typeof NETDATA.localStorage.default[key.toString()] === 'undefined') { + NETDATA.localStorage.default[key.toString()] = def; + NETDATA.localStorage.callback[key.toString()] = callback; + } + + if (NETDATA.localStorageTest()) { + try { + // console.log('localStorage: loading "' + key.toString() + '"'); + ret = localStorage.getItem(key.toString()); + // console.log('netdata loaded: ' + key.toString() + ' = ' + ret.toString()); + if (ret === null || ret === 'undefined') { + // console.log('localStorage: cannot load it, saving "' + key.toString() + '" with value "' + JSON.stringify(def) + '"'); + localStorage.setItem(key.toString(), JSON.stringify(def)); + ret = def; + } else { + // console.log('localStorage: got "' + key.toString() + '" with value "' + ret + '"'); + ret = JSON.parse(ret); + // console.log('localStorage: loaded "' + key.toString() + '" as value ' + ret + ' of type ' + typeof(ret)); + } + } catch (error) { + console.log('localStorage: failed to read "' + key.toString() + '", using default: "' + def.toString() + '"'); + ret = def; + } + } + + if (typeof ret === 'undefined' || ret === 'undefined') { + console.log('localStorage: LOADED UNDEFINED "' + key.toString() + '" as value ' + ret + ' of type ' + typeof(ret)); + ret = def; + } + + NETDATA.localStorage.current[key.toString()] = ret; + return ret; +}; + +NETDATA.localStorageSet = function (key, value, callback) { + if (typeof value === 'undefined' || value === 'undefined') { + console.log('localStorage: ATTEMPT TO SET UNDEFINED "' + key.toString() + '" as value ' + value + ' of type ' + typeof(value)); + } + + if (typeof NETDATA.localStorage.default[key.toString()] === 'undefined') { + NETDATA.localStorage.default[key.toString()] = value; + NETDATA.localStorage.current[key.toString()] = value; + NETDATA.localStorage.callback[key.toString()] = callback; + } + + if (NETDATA.localStorageTest()) { + // console.log('localStorage: saving "' + key.toString() + '" with value "' + JSON.stringify(value) + '"'); + try { + localStorage.setItem(key.toString(), JSON.stringify(value)); + } catch (e) { + console.log('localStorage: failed to save "' + key.toString() + '" with value: "' + value.toString() + '"'); + } + } + + NETDATA.localStorage.current[key.toString()] = value; + return value; +}; + +NETDATA.localStorageGetRecursive = function (obj, prefix, callback) { + let keys = Object.keys(obj); + let len = keys.length; + while (len--) { + let i = keys[len]; + + if (typeof obj[i] === 'object') { + //console.log('object ' + prefix + '.' + i.toString()); + NETDATA.localStorageGetRecursive(obj[i], prefix + '.' + i.toString(), callback); + continue; + } + + obj[i] = NETDATA.localStorageGet(prefix + '.' + i.toString(), obj[i], callback); + } +}; + +NETDATA.setOption = function (key, value) { + if (key.toString() === 'setOptionCallback') { + if (typeof NETDATA.options.current.setOptionCallback === 'function') { + NETDATA.options.current[key.toString()] = value; + NETDATA.options.current.setOptionCallback(); + } + } else if (NETDATA.options.current[key.toString()] !== value) { + let name = 'options.' + key.toString(); + + if (typeof NETDATA.localStorage.default[name.toString()] === 'undefined') { + console.log('localStorage: setOption() on unsaved option: "' + name.toString() + '", value: ' + value); + } + + //console.log(NETDATA.localStorage); + //console.log('setOption: setting "' + key.toString() + '" to "' + value + '" of type ' + typeof(value) + ' original type ' + typeof(NETDATA.options.current[key.toString()])); + //console.log(NETDATA.options); + NETDATA.options.current[key.toString()] = NETDATA.localStorageSet(name.toString(), value, null); + + if (typeof NETDATA.options.current.setOptionCallback === 'function') { + NETDATA.options.current.setOptionCallback(); + } + } + + return true; +}; + +NETDATA.getOption = function (key) { + return NETDATA.options.current[key.toString()]; +}; + +// read settings from local storage +NETDATA.localStorageGetRecursive(NETDATA.options.current, 'options', null); + +// always start with this option enabled. +NETDATA.setOption('stop_updates_when_focus_is_lost', true); + +NETDATA.resetOptions = function () { + let keys = Object.keys(NETDATA.localStorage.default); + let len = keys.length; + + while (len--) { + let i = keys[len]; + let a = i.split('.'); + + if (a[0] === 'options') { + if (a[1] === 'setOptionCallback') { + continue; + } + if (typeof NETDATA.localStorage.default[i] === 'undefined') { + continue; + } + if (NETDATA.options.current[i] === NETDATA.localStorage.default[i]) { + continue; + } + + NETDATA.setOption(a[1], NETDATA.localStorage.default[i]); + } else if (a[0] === 'chart_heights') { + if (typeof NETDATA.localStorage.callback[i] === 'function' && typeof NETDATA.localStorage.default[i] !== 'undefined') { + NETDATA.localStorage.callback[i](NETDATA.localStorage.default[i]); + } + } + } + + NETDATA.dateTime.init(NETDATA.options.current.timezone); +}; + +// *** src/dashboard.js/timeout.js + +// TODO: Better name needed + +NETDATA.timeout = { + // by default, these are just wrappers to setTimeout() / clearTimeout() + + step: function (callback) { + return window.setTimeout(callback, 1000 / 60); + }, + + set: function (callback, delay) { + return window.setTimeout(callback, delay); + }, + + clear: function (id) { + return window.clearTimeout(id); + }, + + init: function () { + let custom = true; + + if (window.requestAnimationFrame) { + this.step = function (callback) { + return window.requestAnimationFrame(callback); + }; + + this.clear = function (handle) { + return window.cancelAnimationFrame(handle.value); + }; + // } else if (window.webkitRequestAnimationFrame) { + // this.step = function (callback) { + // return window.webkitRequestAnimationFrame(callback); + // }; + + // if (window.webkitCancelAnimationFrame) { + // this.clear = function (handle) { + // return window.webkitCancelAnimationFrame(handle.value); + // }; + // } else if (window.webkitCancelRequestAnimationFrame) { + // this.clear = function (handle) { + // return window.webkitCancelRequestAnimationFrame(handle.value); + // }; + // } + // } else if (window.mozRequestAnimationFrame) { + // this.step = function (callback) { + // return window.mozRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.mozCancelRequestAnimationFrame(handle.value); + // }; + // } else if (window.oRequestAnimationFrame) { + // this.step = function (callback) { + // return window.oRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.oCancelRequestAnimationFrame(handle.value); + // }; + // } else if (window.msRequestAnimationFrame) { + // this.step = function (callback) { + // return window.msRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.msCancelRequestAnimationFrame(handle.value); + // }; + } else { + custom = false; + } + + if (custom) { + // we have installed custom .step() / .clear() functions + // overwrite the .set() too + + this.set = function (callback, delay) { + let start = Date.now(), + handle = new Object(); + + const loop = () => { + let current = Date.now(), + delta = current - start; + + if (delta >= delay) { + callback.call(); + } else { + handle.value = this.step(loop); + } + } + + handle.value = this.step(loop); + return handle; + }; + } + } +}; + +NETDATA.timeout.init(); +// Codacy declarations +/* global netdataTheme */ + +NETDATA.themes = { + white: { + bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-3.3.7.css', + dashboard_css: NETDATA.serverStatic + 'dashboard.css?v20180210-1', + background: '#FFFFFF', + foreground: '#000000', + grid: '#F0F0F0', + axis: '#F0F0F0', + highlight: '#F5F5F5', + colors: ['#3366CC', '#DC3912', '#109618', '#FF9900', '#990099', '#DD4477', + '#3B3EAC', '#66AA00', '#0099C6', '#B82E2E', '#AAAA11', '#5574A6', + '#994499', '#22AA99', '#6633CC', '#E67300', '#316395', '#8B0707', + '#329262', '#3B3EAC'], + easypiechart_track: '#f0f0f0', + easypiechart_scale: '#dfe0e0', + gauge_pointer: '#C0C0C0', + gauge_stroke: '#F0F0F0', + gauge_gradient: false, + d3pie: { + title: '#333333', + subtitle: '#666666', + footer: '#888888', + other: '#aaaaaa', + mainlabel: '#333333', + percentage: '#dddddd', + value: '#aaaa22', + tooltip_bg: '#000000', + tooltip_fg: '#efefef', + segment_stroke: "#ffffff", + gradient_color: '#000000' + } + }, + slate: { + bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-slate-flat-3.3.7.css?v20161229-1', + dashboard_css: NETDATA.serverStatic + 'dashboard.slate.css?v20180210-1', + background: '#272b30', + foreground: '#C8C8C8', + grid: '#283236', + axis: '#283236', + highlight: '#383838', + /* colors: [ '#55bb33', '#ff2222', '#0099C6', '#faa11b', '#adbce0', '#DDDD00', + '#4178ba', '#f58122', '#a5cc39', '#f58667', '#f5ef89', '#cf93c0', + '#a5d18a', '#b8539d', '#3954a3', '#c8a9cf', '#c7de8a', '#fad20a', + '#a6a479', '#a66da8' ], + */ + colors: ['#66AA00', '#FE3912', '#3366CC', '#D66300', '#0099C6', '#DDDD00', + '#5054e6', '#EE9911', '#BB44CC', '#e45757', '#ef0aef', '#CC7700', + '#22AA99', '#109618', '#905bfd', '#f54882', '#4381bf', '#ff3737', + '#329262', '#3B3EFF'], + easypiechart_track: '#373b40', + easypiechart_scale: '#373b40', + gauge_pointer: '#474b50', + gauge_stroke: '#373b40', + gauge_gradient: false, + d3pie: { + title: '#C8C8C8', + subtitle: '#283236', + footer: '#283236', + other: '#283236', + mainlabel: '#C8C8C8', + percentage: '#dddddd', + value: '#cccc44', + tooltip_bg: '#272b30', + tooltip_fg: '#C8C8C8', + segment_stroke: "#283236", + gradient_color: '#000000' + } + } +}; + +if (typeof netdataTheme !== 'undefined' && typeof NETDATA.themes[netdataTheme] !== 'undefined') { + NETDATA.themes.current = NETDATA.themes[netdataTheme]; +} else { + NETDATA.themes.current = NETDATA.themes.white; +} + +NETDATA.colors = NETDATA.themes.current.colors; + +// these are the colors Google Charts are using +// we have them here to attempt emulate their look and feel on the other chart libraries +// http://there4.io/2012/05/02/google-chart-color-list/ +//NETDATA.colors = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6', +// '#DD4477', '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11', +// '#6633CC', '#E67300', '#8B0707', '#329262', '#5574A6', '#3B3EAC' ]; + +// an alternative set +// http://www.mulinblog.com/a-color-palette-optimized-for-data-visualization/ +// (blue) (red) (orange) (green) (pink) (brown) (purple) (yellow) (gray) +//NETDATA.colors = [ '#5DA5DA', '#F15854', '#FAA43A', '#60BD68', '#F17CB0', '#B2912F', '#B276B2', '#DECF3F', '#4D4D4D' ]; +// dygraph + +// Codacy declarations +/* global smoothPlotter */ +/* global Dygraph */ + +NETDATA.dygraph = { + smooth: false +}; + +NETDATA.dygraphToolboxPanAndZoom = function (state, after, before) { + if (after < state.netdata_first) { + after = state.netdata_first; + } + + if (before > state.netdata_last) { + before = state.netdata_last; + } + + state.setMode('zoom'); + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_user_action = true; + state.tmp.dygraph_force_zoom = true; + // state.log('toolboxPanAndZoom'); + state.updateChartPanOrZoom(after, before); + NETDATA.globalPanAndZoom.setMaster(state, after, before); +}; + +NETDATA.dygraphSetSelection = function (state, t) { + if (typeof state.tmp.dygraph_instance !== 'undefined') { + let r = state.calculateRowForTime(t); + if (r !== -1) { + state.tmp.dygraph_instance.setSelection(r); + return true; + } else { + state.tmp.dygraph_instance.clearSelection(); + state.legendShowUndefined(); + } + } + + return false; +}; + +NETDATA.dygraphClearSelection = function (state) { + if (typeof state.tmp.dygraph_instance !== 'undefined') { + state.tmp.dygraph_instance.clearSelection(); + } + return true; +}; + +NETDATA.dygraphSmoothInitialize = function (callback) { + $.ajax({ + url: NETDATA.dygraph_smooth_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.dygraph.smooth = true; + smoothPlotter.smoothing = 0.3; + }) + .fail(function () { + NETDATA.dygraph.smooth = false; + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); +}; + +NETDATA.dygraphInitialize = function (callback) { + if (typeof netdataNoDygraphs === 'undefined' || !netdataNoDygraphs) { + $.ajax({ + url: NETDATA.dygraph_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js); + }) + .fail(function () { + NETDATA.chartLibraries.dygraph.enabled = false; + NETDATA.error(100, NETDATA.dygraph_js); + }) + .always(function () { + if (NETDATA.chartLibraries.dygraph.enabled && NETDATA.options.current.smooth_plot) { + NETDATA.dygraphSmoothInitialize(callback); + } else if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.dygraph.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.dygraphChartUpdate = function (state, data) { + let dygraph = state.tmp.dygraph_instance; + + if (typeof dygraph === 'undefined') { + return NETDATA.dygraphChartCreate(state, data); + } + + // when the chart is not visible, and hidden + // if there is a window resize, dygraph detects + // its element size as 0x0. + // this will make it re-appear properly + + if (state.tm.last_unhidden > state.tmp.dygraph_last_rendered) { + dygraph.resize(); + } + + let options = { + file: data.result.data, + colors: state.chartColors(), + labels: data.result.labels, + //labelsDivWidth: state.chartWidth() - 70, + includeZero: state.tmp.dygraph_include_zero, + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names) + }; + + if (state.tmp.dygraph_chart_type === 'stacked') { + if (options.includeZero && state.dimensions_visibility.countSelected() < options.visibility.length) { + options.includeZero = 0; + } + } + + if (!NETDATA.chartLibraries.dygraph.isSparkline(state)) { + options.ylabel = state.units_current; // (state.units_desired === 'auto')?"":state.units_current; + } + + if (state.tmp.dygraph_force_zoom) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() forced zoom update'); + } + + options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; + //options.isZoomedIgnoreProgrammaticZoom = true; + state.tmp.dygraph_force_zoom = false; + } else if (state.current.name !== 'auto') { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() loose update'); + } + } else { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() strict update'); + } + + options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; + //options.isZoomedIgnoreProgrammaticZoom = true; + } + + options.valueRange = state.tmp.dygraph_options.valueRange; + + let oldMax = null, oldMin = null; + if (state.tmp.__commonMin !== null) { + state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; + oldMin = options.valueRange[0] = NETDATA.commonMin.get(state); + } + if (state.tmp.__commonMax !== null) { + state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; + oldMax = options.valueRange[1] = NETDATA.commonMax.get(state); + } + + if (state.tmp.dygraph_smooth_eligible) { + if ((NETDATA.options.current.smooth_plot && state.tmp.dygraph_options.plotter !== smoothPlotter) + || (NETDATA.options.current.smooth_plot === false && state.tmp.dygraph_options.plotter === smoothPlotter)) { + NETDATA.dygraphChartCreate(state, data); + return; + } + } + + if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { + // pan and zoom on snapshots + options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; + //options.isZoomedIgnoreProgrammaticZoom = true; + } + + if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { + if (Array.isArray(options.valueRange) && options.valueRange[0] <= 0) { + options.valueRange[0] = null; + } + } + + dygraph.updateOptions(options); + + let redraw = false; + if (oldMin !== null && oldMin > state.tmp.dygraph_instance.axes_[0].extremeRange[0]) { + state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; + options.valueRange[0] = NETDATA.commonMin.get(state); + redraw = true; + } + if (oldMax !== null && oldMax < state.tmp.dygraph_instance.axes_[0].extremeRange[1]) { + state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; + options.valueRange[1] = NETDATA.commonMax.get(state); + redraw = true; + } + + if (redraw) { + // state.log('forcing redraw to adapt to common- min/max'); + dygraph.updateOptions(options); + } + + state.tmp.dygraph_last_rendered = Date.now(); + return true; +}; + +NETDATA.dygraphChartCreate = function (state, data) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartCreate()'); + } + + state.tmp.dygraph_chart_type = NETDATA.dataAttribute(state.element, 'dygraph-type', state.chart.chart_type); + if (state.tmp.dygraph_chart_type === 'stacked' && data.dimensions === 1) { + state.tmp.dygraph_chart_type = 'area'; + } + if (state.tmp.dygraph_chart_type === 'stacked' && NETDATA.chartLibraries.dygraph.isLogScale(state)) { + state.tmp.dygraph_chart_type = 'area'; + } + + let highlightCircleSize = NETDATA.chartLibraries.dygraph.isSparkline(state) ? 3 : 4; + + let smooth = NETDATA.dygraph.smooth + ? (NETDATA.dataAttributeBoolean(state.element, 'dygraph-smooth', (state.tmp.dygraph_chart_type === 'line' && NETDATA.chartLibraries.dygraph.isSparkline(state) === false))) + : false; + + state.tmp.dygraph_include_zero = NETDATA.dataAttribute(state.element, 'dygraph-includezero', (state.tmp.dygraph_chart_type === 'stacked')); + let drawAxis = NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawaxis', true); + + state.tmp.dygraph_options = { + colors: NETDATA.dataAttribute(state.element, 'dygraph-colors', state.chartColors()), + + // leave a few pixels empty on the right of the chart + rightGap: NETDATA.dataAttribute(state.element, 'dygraph-rightgap', 5), + showRangeSelector: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showrangeselector', false), + showRoller: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showroller', false), + title: NETDATA.dataAttribute(state.element, 'dygraph-title', state.title), + titleHeight: NETDATA.dataAttribute(state.element, 'dygraph-titleheight', 19), + legend: NETDATA.dataAttribute(state.element, 'dygraph-legend', 'always'), // we need this to get selection events + labels: data.result.labels, + labelsDiv: NETDATA.dataAttribute(state.element, 'dygraph-labelsdiv', state.element_legend_childs.hidden), + //labelsDivStyles: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivstyles', { 'fontSize':'1px' }), + //labelsDivWidth: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivwidth', state.chartWidth() - 70), + labelsSeparateLines: NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsseparatelines', true), + labelsShowZeroValues: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsshowzerovalues', true), + labelsKMB: false, + labelsKMG2: false, + showLabelsOnHighlight: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showlabelsonhighlight', true), + hideOverlayOnMouseOut: NETDATA.dataAttributeBoolean(state.element, 'dygraph-hideoverlayonmouseout', true), + includeZero: state.tmp.dygraph_include_zero, + xRangePad: NETDATA.dataAttribute(state.element, 'dygraph-xrangepad', 0), + yRangePad: NETDATA.dataAttribute(state.element, 'dygraph-yrangepad', 1), + valueRange: NETDATA.dataAttribute(state.element, 'dygraph-valuerange', [null, null]), + ylabel: state.units_current, // (state.units_desired === 'auto')?"":state.units_current, + yLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-ylabelwidth', 12), + + // the function to plot the chart + plotter: null, + + // The width of the lines connecting data points. + // This can be used to increase the contrast or some graphs. + strokeWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokewidth', ((state.tmp.dygraph_chart_type === 'stacked') ? 0.1 : ((smooth === true) ? 1.5 : 0.7))), + strokePattern: NETDATA.dataAttribute(state.element, 'dygraph-strokepattern', undefined), + + // The size of the dot to draw on each point in pixels (see drawPoints). + // A dot is always drawn when a point is "isolated", + // i.e. there is a missing point on either side of it. + // This also controls the size of those dots. + drawPoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawpoints', false), + + // Draw points at the edges of gaps in the data. + // This improves visibility of small data segments or other data irregularities. + drawGapEdgePoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgapedgepoints', true), + connectSeparatedPoints: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-connectseparatedpoints', false), + pointSize: NETDATA.dataAttribute(state.element, 'dygraph-pointsize', 1), + + // enabling this makes the chart with little square lines + stepPlot: NETDATA.dataAttributeBoolean(state.element, 'dygraph-stepplot', false), + + // Draw a border around graph lines to make crossing lines more easily + // distinguishable. Useful for graphs with many lines. + strokeBorderColor: NETDATA.dataAttribute(state.element, 'dygraph-strokebordercolor', NETDATA.themes.current.background), + strokeBorderWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokeborderwidth', (state.tmp.dygraph_chart_type === 'stacked') ? 0.0 : 0.0), + fillGraph: NETDATA.dataAttribute(state.element, 'dygraph-fillgraph', (state.tmp.dygraph_chart_type === 'area' || state.tmp.dygraph_chart_type === 'stacked')), + fillAlpha: NETDATA.dataAttribute(state.element, 'dygraph-fillalpha', + ((state.tmp.dygraph_chart_type === 'stacked') + ? NETDATA.options.current.color_fill_opacity_stacked + : NETDATA.options.current.color_fill_opacity_area) + ), + stackedGraph: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraph', (state.tmp.dygraph_chart_type === 'stacked')), + stackedGraphNaNFill: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraphnanfill', 'none'), + drawAxis: drawAxis, + axisLabelFontSize: NETDATA.dataAttribute(state.element, 'dygraph-axislabelfontsize', 10), + axisLineColor: NETDATA.dataAttribute(state.element, 'dygraph-axislinecolor', NETDATA.themes.current.axis), + axisLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-axislinewidth', 1.0), + drawGrid: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgrid', true), + gridLinePattern: NETDATA.dataAttribute(state.element, 'dygraph-gridlinepattern', null), + gridLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-gridlinewidth', 1.0), + gridLineColor: NETDATA.dataAttribute(state.element, 'dygraph-gridlinecolor', NETDATA.themes.current.grid), + maxNumberWidth: NETDATA.dataAttribute(state.element, 'dygraph-maxnumberwidth', 8), + sigFigs: NETDATA.dataAttribute(state.element, 'dygraph-sigfigs', null), + digitsAfterDecimal: NETDATA.dataAttribute(state.element, 'dygraph-digitsafterdecimal', 2), + valueFormatter: NETDATA.dataAttribute(state.element, 'dygraph-valueformatter', undefined), + highlightCircleSize: NETDATA.dataAttribute(state.element, 'dygraph-highlightcirclesize', highlightCircleSize), + highlightSeriesOpts: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesopts', null), // TOO SLOW: { strokeWidth: 1.5 }, + highlightSeriesBackgroundAlpha: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesbackgroundalpha', null), // TOO SLOW: (state.tmp.dygraph_chart_type === 'stacked')?0.7:0.5, + pointClickCallback: NETDATA.dataAttribute(state.element, 'dygraph-pointclickcallback', undefined), + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names), + logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? 'y' : undefined, + + axes: { + x: { + pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-xpixelsperlabel', 50), + ticker: Dygraph.dateTicker, + axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-xaxislabelwidth', 60), + drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawxaxis', drawAxis), + axisLabelFormatter: function (d, gran) { + void(gran); + return NETDATA.dateTime.xAxisTimeString(d); + } + }, + y: { + logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? true : undefined, + pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-ypixelsperlabel', 15), + axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-yaxislabelwidth', 50), + drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawyaxis', drawAxis), + axisLabelFormatter: function (y) { + + // unfortunately, we have to call this every single time + state.legendFormatValueDecimalsFromMinMax( + this.axes_[0].extremeRange[0], + this.axes_[0].extremeRange[1] + ); + + let old_units = this.user_attrs_.ylabel; + let v = state.legendFormatValue(y); + let new_units = state.units_current; + + if (state.units_desired === 'auto' && typeof old_units !== 'undefined' && new_units !== old_units && !NETDATA.chartLibraries.dygraph.isSparkline(state)) { + // console.log(this); + // state.log('units discrepancy: old = ' + old_units + ', new = ' + new_units); + let len = this.plugins_.length; + while (len--) { + // console.log(this.plugins_[len]); + if (typeof this.plugins_[len].plugin.ylabel_div_ !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_ !== null + && typeof this.plugins_[len].plugin.ylabel_div_.children !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_.children !== null + && typeof this.plugins_[len].plugin.ylabel_div_.children[0].children !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_.children[0].children !== null + ) { + this.plugins_[len].plugin.ylabel_div_.children[0].children[0].innerHTML = new_units; + this.user_attrs_.ylabel = new_units; + break; + } + } + + if (len < 0) { + state.log('units discrepancy, but cannot find dygraphs div to change: old = ' + old_units + ', new = ' + new_units); + } + } + + return v; + } + } + }, + legendFormatter: function (data) { + if (state.tmp.dygraph_mouse_down) { + return; + } + + let elements = state.element_legend_childs; + + // if the hidden div is not there + // we are not managing the legend + if (elements.hidden === null) { + return; + } + + if (typeof data.x !== 'undefined') { + state.legendSetDate(data.x); + let i = data.series.length; + while (i--) { + let series = data.series[i]; + if (series.isVisible) { + state.legendSetLabelValue(series.label, series.y); + } else { + state.legendSetLabelValue(series.label, null); + } + } + } + + return ''; + }, + drawCallback: function (dygraph, is_initial) { + + // the user has panned the chart and this is called to re-draw the chart + // 1. refresh this chart by adding data to it + // 2. notify all the other charts about the update they need + + // to prevent an infinite loop (feedback), we use + // state.tmp.dygraph_user_action + // - when true, this is initiated by a user + // - when false, this is feedback + + if (state.current.name !== 'auto' && state.tmp.dygraph_user_action) { + state.tmp.dygraph_user_action = false; + + let x_range = dygraph.xAxisRange(); + let after = Math.round(x_range[0]); + let before = Math.round(x_range[1]); + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphDrawCallback(dygraph, ' + is_initial + '): mode ' + state.current.name + ' ' + (after / 1000).toString() + ' - ' + (before / 1000).toString()); + //console.log(state); + } + + if (before <= state.netdata_last && after >= state.netdata_first) { + // update only when we are within the data limits + state.updateChartPanOrZoom(after, before); + } + } + }, + zoomCallback: function (minDate, maxDate, yRanges) { + + // the user has selected a range on the chart + // 1. refresh this chart by adding data to it + // 2. notify all the other charts about the update they need + + void(yRanges); + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphZoomCallback(): ' + state.current.name); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + state.setMode('zoom'); + + // refresh it to the greatest possible zoom level + state.tmp.dygraph_user_action = true; + state.tmp.dygraph_force_zoom = true; + state.updateChartPanOrZoom(minDate, maxDate); + }, + highlightCallback: function (event, x, points, row, seriesName) { + void(seriesName); + + state.pauseChart(); + + // there is a bug in dygraph when the chart is zoomed enough + // the time it thinks is selected is wrong + // here we calculate the time t based on the row number selected + // which is ok + // let t = state.data_after + row * state.data_update_every; + // console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t === x)?'SAME':(Math.abs(x-t)<=state.data_update_every)?'SIMILAR':'DIFFERENT') + ', rows in db: ' + state.data_points + ' visible(x) = ' + state.timeIsVisible(x) + ' visible(t) = ' + state.timeIsVisible(t) + ' r(x) = ' + state.calculateRowForTime(x) + ' r(t) = ' + state.calculateRowForTime(t) + ' range: ' + state.data_after + ' - ' + state.data_before + ' real: ' + state.data.after + ' - ' + state.data.before + ' every: ' + state.data_update_every); + + if (state.tmp.dygraph_mouse_down !== true) { + NETDATA.globalSelectionSync.sync(state, x); + } + + // fix legend zIndex using the internal structures of dygraph legend module + // this works, but it is a hack! + // state.tmp.dygraph_instance.plugins_[0].plugin.legend_div_.style.zIndex = 10000; + }, + unhighlightCallback: function (event) { + void(event); + + if (state.tmp.dygraph_mouse_down) { + return; + } + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphUnhighlightCallback()'); + } + + state.unpauseChart(); + NETDATA.globalSelectionSync.stop(); + }, + underlayCallback: function (canvas, area, g) { + + // the chart is about to be drawn + // this function renders global highlighted time-frame + + if (NETDATA.globalChartUnderlay.isActive()) { + let after = NETDATA.globalChartUnderlay.after; + let before = NETDATA.globalChartUnderlay.before; + + if (after < state.view_after) { + after = state.view_after; + } + + if (before > state.view_before) { + before = state.view_before; + } + + if (after < before) { + let bottom_left = g.toDomCoords(after, -20); + let top_right = g.toDomCoords(before, +20); + + let left = bottom_left[0]; + let right = top_right[0]; + + canvas.fillStyle = NETDATA.themes.current.highlight; + canvas.fillRect(left, area.y, right - left, area.h); + } + } + }, + interactionModel: { + mousedown: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mousedown()'); + } + + state.tmp.dygraph_user_action = true; + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphMouseDown()'); + } + + // Right-click should not initiate anything. + if (event.button && event.button === 2) { + return; + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_mouse_down = true; + context.initializeMouseDown(event, dygraph, context); + + //console.log(event); + if (event.button && event.button === 1) { + if (event.shiftKey) { + //console.log('middle mouse button dragging (PAN)'); + + state.setMode('pan'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startPan(event, dygraph, context); + } else if (event.altKey || event.ctrlKey || event.metaKey) { + //console.log('middle mouse button highlight'); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); + Dygraph.startZoom(event, dygraph, context); + } else { + //console.log('middle mouse button selection for zoom (ZOOM)'); + + state.setMode('zoom'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startZoom(event, dygraph, context); + } + } else { + if (event.shiftKey) { + //console.log('left mouse button selection for zoom (ZOOM)'); + + state.setMode('zoom'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startZoom(event, dygraph, context); + } else if (event.altKey || event.ctrlKey || event.metaKey) { + //console.log('left mouse button highlight'); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); + Dygraph.startZoom(event, dygraph, context); + } else { + //console.log('left mouse button dragging (PAN)'); + + state.setMode('pan'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startPan(event, dygraph, context); + } + } + }, + mousemove: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mousemove()'); + } + + if (state.tmp.dygraph_highlight_after !== null) { + //console.log('highlight selection...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.moveZoom(event, dygraph, context); + event.preventDefault(); + } else if (context.isPanning) { + //console.log('panning...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + //NETDATA.globalSelectionSync.stop(); + //NETDATA.globalSelectionSync.delay(); + state.setMode('pan'); + context.is2DPan = false; + Dygraph.movePan(event, dygraph, context); + } else if (context.isZooming) { + //console.log('zooming...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + //NETDATA.globalSelectionSync.stop(); + //NETDATA.globalSelectionSync.delay(); + state.setMode('zoom'); + Dygraph.moveZoom(event, dygraph, context); + } + }, + mouseup: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = false; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mouseup()'); + } + + if (state.tmp.dygraph_highlight_after !== null) { + //console.log('done highlight selection'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + + NETDATA.globalChartUnderlay.set(state + , state.tmp.dygraph_highlight_after + , dygraph.toDataXCoord(event.offsetX) + , state.view_after + , state.view_before + ); + + state.tmp.dygraph_highlight_after = null; + + context.isZooming = false; + dygraph.clearZoomRect_(); + dygraph.drawGraph_(false); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } else if (context.isPanning) { + //console.log('done panning'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.endPan(event, dygraph, context); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } else if (context.isZooming) { + //console.log('done zomming'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.endZoom(event, dygraph, context); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } + }, + click: function (event, dygraph, context) { + void(dygraph); + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.click()'); + } + + event.preventDefault(); + }, + dblclick: function (event, dygraph, context) { + void(event); + void(dygraph); + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.dblclick()'); + } + NETDATA.resetAllCharts(state); + }, + wheel: function (event, dygraph, context) { + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.wheel()'); + } + + // Take the offset of a mouse event on the dygraph canvas and + // convert it to a pair of percentages from the bottom left. + // (Not top left, bottom is where the lower value is.) + function offsetToPercentage(g, offsetX, offsetY) { + // This is calculating the pixel offset of the leftmost date. + let xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0]; + let yar0 = g.yAxisRange(0); + + // This is calculating the pixel of the highest value. (Top pixel) + let yOffset = g.toDomCoords(null, yar0[1])[1]; + + // x y w and h are relative to the corner of the drawing area, + // so that the upper corner of the drawing area is (0, 0). + let x = offsetX - xOffset; + let y = offsetY - yOffset; + + // This is computing the rightmost pixel, effectively defining the + // width. + let w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset; + + // This is computing the lowest pixel, effectively defining the height. + let h = g.toDomCoords(null, yar0[0])[1] - yOffset; + + // Percentage from the left. + let xPct = w === 0 ? 0 : (x / w); + // Percentage from the top. + let yPct = h === 0 ? 0 : (y / h); + + // The (1-) part below changes it from "% distance down from the top" + // to "% distance up from the bottom". + return [xPct, (1 - yPct)]; + } + + // Adjusts [x, y] toward each other by zoomInPercentage% + // Split it so the left/bottom axis gets xBias/yBias of that change and + // tight/top gets (1-xBias)/(1-yBias) of that change. + // + // If a bias is missing it splits it down the middle. + function zoomRange(g, zoomInPercentage, xBias, yBias) { + xBias = xBias || 0.5; + yBias = yBias || 0.5; + + function adjustAxis(axis, zoomInPercentage, bias) { + let delta = axis[1] - axis[0]; + let increment = delta * zoomInPercentage; + let foo = [increment * bias, increment * (1 - bias)]; + + return [axis[0] + foo[0], axis[1] - foo[1]]; + } + + let yAxes = g.yAxisRanges(); + let newYAxes = []; + for (let i = 0; i < yAxes.length; i++) { + newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias); + } + + return adjustAxis(g.xAxisRange(), zoomInPercentage, xBias); + } + + if (event.altKey || event.shiftKey) { + state.tmp.dygraph_user_action = true; + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + // http://dygraphs.com/gallery/interaction-api.js + let normal_def; + if (typeof event.wheelDelta === 'number' && !isNaN(event.wheelDelta)) + // chrome + { + normal_def = event.wheelDelta / 40; + } else + // firefox + { + normal_def = event.deltaY * -1.2; + } + + let normal = (event.detail) ? event.detail * -1 : normal_def; + let percentage = normal / 50; + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + + let percentages = offsetToPercentage(dygraph, event.offsetX, event.offsetY); + let xPct = percentages[0]; + let yPct = percentages[1]; + + let new_x_range = zoomRange(dygraph, percentage, xPct, yPct); + let after = new_x_range[0]; + let before = new_x_range[1]; + + let first = state.netdata_first + state.data_update_every; + let last = state.netdata_last + state.data_update_every; + + if (before > last) { + after -= (before - last); + before = last; + } + if (after < first) { + after = first; + } + + state.setMode('zoom'); + state.updateChartPanOrZoom(after, before, function () { + dygraph.updateOptions({dateWindow: [after, before]}); + }); + + event.preventDefault(); + } + }, + touchstart: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = true; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchstart()'); + } + + state.tmp.dygraph_user_action = true; + state.setMode('zoom'); + state.pauseChart(); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + Dygraph.defaultInteractionModel.touchstart(event, dygraph, context); + + // we overwrite the touch directions at the end, to overwrite + // the internal default of dygraph + context.touchDirections = {x: true, y: false}; + + state.dygraph_last_touch_start = Date.now(); + state.dygraph_last_touch_move = 0; + + if (typeof event.touches[0].pageX === 'number') { + state.dygraph_last_touch_page_x = event.touches[0].pageX; + } else { + state.dygraph_last_touch_page_x = 0; + } + }, + touchmove: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchmove()'); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.defaultInteractionModel.touchmove(event, dygraph, context); + + state.dygraph_last_touch_move = Date.now(); + }, + touchend: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = false; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchend()'); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.defaultInteractionModel.touchend(event, dygraph, context); + + // if it didn't move, it is a selection + if (state.dygraph_last_touch_move === 0 && state.dygraph_last_touch_page_x !== 0) { + NETDATA.globalSelectionSync.dontSyncBefore = 0; + NETDATA.globalSelectionSync.setMaster(state); + + // internal api of dygraph + let pct = (state.dygraph_last_touch_page_x - (dygraph.plotter_.area.x + state.element.getBoundingClientRect().left)) / dygraph.plotter_.area.w; + console.log('pct: ' + pct.toString()); + + let t = Math.round(state.view_after + (state.view_before - state.view_after) * pct); + if (NETDATA.dygraphSetSelection(state, t)) { + NETDATA.globalSelectionSync.sync(state, t); + } + } + + // if it was double tap within double click time, reset the charts + let now = Date.now(); + if (typeof state.dygraph_last_touch_end !== 'undefined') { + if (state.dygraph_last_touch_move === 0) { + let dt = now - state.dygraph_last_touch_end; + if (dt <= NETDATA.options.current.double_click_speed) { + NETDATA.resetAllCharts(state); + } + } + } + + // remember the timestamp of the last touch end + state.dygraph_last_touch_end = now; + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } + } + }; + + if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { + if (Array.isArray(state.tmp.dygraph_options.valueRange) && state.tmp.dygraph_options.valueRange[0] <= 0) { + state.tmp.dygraph_options.valueRange[0] = null; + } + } + + if (NETDATA.chartLibraries.dygraph.isSparkline(state)) { + state.tmp.dygraph_options.drawGrid = false; + state.tmp.dygraph_options.drawAxis = false; + state.tmp.dygraph_options.title = undefined; + state.tmp.dygraph_options.ylabel = undefined; + state.tmp.dygraph_options.yLabelWidth = 0; + //state.tmp.dygraph_options.labelsDivWidth = 120; + //state.tmp.dygraph_options.labelsDivStyles.width = '120px'; + state.tmp.dygraph_options.labelsSeparateLines = true; + state.tmp.dygraph_options.rightGap = 0; + state.tmp.dygraph_options.yRangePad = 1; + state.tmp.dygraph_options.axes.x.drawAxis = false; + state.tmp.dygraph_options.axes.y.drawAxis = false; + } + + if (smooth) { + state.tmp.dygraph_smooth_eligible = true; + + if (NETDATA.options.current.smooth_plot) { + state.tmp.dygraph_options.plotter = smoothPlotter; + } + } + else { + state.tmp.dygraph_smooth_eligible = false; + } + + if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { + // pan and zoom on snapshots + state.tmp.dygraph_options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; + //state.tmp.dygraph_options.isZoomedIgnoreProgrammaticZoom = true; + } + + state.tmp.dygraph_instance = new Dygraph(state.element_chart, + data.result.data, state.tmp.dygraph_options); + + state.tmp.dygraph_force_zoom = false; + state.tmp.dygraph_user_action = false; + state.tmp.dygraph_last_rendered = Date.now(); + state.tmp.dygraph_highlight_after = null; + + if (state.tmp.dygraph_options.valueRange[0] === null && state.tmp.dygraph_options.valueRange[1] === null) { + if (typeof state.tmp.dygraph_instance.axes_[0].extremeRange !== 'undefined') { + state.tmp.__commonMin = NETDATA.dataAttribute(state.element, 'common-min', null); + state.tmp.__commonMax = NETDATA.dataAttribute(state.element, 'common-max', null); + } else { + state.log('incompatible version of Dygraph detected'); + state.tmp.__commonMin = null; + state.tmp.__commonMax = null; + } + } else { + // if the user gave a valueRange, respect it + state.tmp.__commonMin = null; + state.tmp.__commonMax = null; + } + + return true; +}; +// ---------------------------------------------------------------------------------------------------------------- +// sparkline + +NETDATA.sparklineInitialize = function (callback) { + if (typeof netdataNoSparklines === 'undefined' || !netdataNoSparklines) { + $.ajax({ + url: NETDATA.sparkline_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js); + }) + .fail(function () { + NETDATA.chartLibraries.sparkline.enabled = false; + NETDATA.error(100, NETDATA.sparkline_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.sparkline.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.sparklineChartUpdate = function (state, data) { + state.sparkline_options.width = state.chartWidth(); + state.sparkline_options.height = state.chartHeight(); + + $(state.element_chart).sparkline(data.result, state.sparkline_options); + return true; +}; + +NETDATA.sparklineChartCreate = function (state, data) { + let type = NETDATA.dataAttribute(state.element, 'sparkline-type', 'line'); + let lineColor = NETDATA.dataAttribute(state.element, 'sparkline-linecolor', state.chartCustomColors()[0]); + let fillColor = NETDATA.dataAttribute(state.element, 'sparkline-fillcolor', ((state.chart.chart_type === 'line') ? NETDATA.themes.current.background : NETDATA.colorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance))); + let chartRangeMin = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemin', undefined); + let chartRangeMax = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemax', undefined); + let composite = NETDATA.dataAttribute(state.element, 'sparkline-composite', undefined); + let enableTagOptions = NETDATA.dataAttribute(state.element, 'sparkline-enabletagoptions', undefined); + let tagOptionPrefix = NETDATA.dataAttribute(state.element, 'sparkline-tagoptionprefix', undefined); + let tagValuesAttribute = NETDATA.dataAttribute(state.element, 'sparkline-tagvaluesattribute', undefined); + let disableHiddenCheck = NETDATA.dataAttribute(state.element, 'sparkline-disablehiddencheck', undefined); + let defaultPixelsPerValue = NETDATA.dataAttribute(state.element, 'sparkline-defaultpixelspervalue', undefined); + let spotColor = NETDATA.dataAttribute(state.element, 'sparkline-spotcolor', undefined); + let minSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-minspotcolor', undefined); + let maxSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-maxspotcolor', undefined); + let spotRadius = NETDATA.dataAttribute(state.element, 'sparkline-spotradius', undefined); + let valueSpots = NETDATA.dataAttribute(state.element, 'sparkline-valuespots', undefined); + let highlightSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightspotcolor', undefined); + let highlightLineColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightlinecolor', undefined); + let lineWidth = NETDATA.dataAttribute(state.element, 'sparkline-linewidth', undefined); + let normalRangeMin = NETDATA.dataAttribute(state.element, 'sparkline-normalrangemin', undefined); + let normalRangeMax = NETDATA.dataAttribute(state.element, 'sparkline-normalrangemax', undefined); + let drawNormalOnTop = NETDATA.dataAttribute(state.element, 'sparkline-drawnormalontop', undefined); + let xvalues = NETDATA.dataAttribute(state.element, 'sparkline-xvalues', undefined); + let chartRangeClip = NETDATA.dataAttribute(state.element, 'sparkline-chartrangeclip', undefined); + let chartRangeMinX = NETDATA.dataAttribute(state.element, 'sparkline-chartrangeminx', undefined); + let chartRangeMaxX = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemaxx', undefined); + let disableInteraction = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disableinteraction', false); + let disableTooltips = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disabletooltips', false); + let disableHighlight = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disablehighlight', false); + let highlightLighten = NETDATA.dataAttribute(state.element, 'sparkline-highlightlighten', 1.4); + let highlightColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightcolor', undefined); + let tooltipContainer = NETDATA.dataAttribute(state.element, 'sparkline-tooltipcontainer', undefined); + let tooltipClassname = NETDATA.dataAttribute(state.element, 'sparkline-tooltipclassname', undefined); + let tooltipFormat = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformat', undefined); + let tooltipPrefix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipprefix', undefined); + let tooltipSuffix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipsuffix', ' ' + state.units_current); + let tooltipSkipNull = NETDATA.dataAttributeBoolean(state.element, 'sparkline-tooltipskipnull', true); + let tooltipValueLookups = NETDATA.dataAttribute(state.element, 'sparkline-tooltipvaluelookups', undefined); + let tooltipFormatFieldlist = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformatfieldlist', undefined); + let tooltipFormatFieldlistKey = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformatfieldlistkey', undefined); + let numberFormatter = NETDATA.dataAttribute(state.element, 'sparkline-numberformatter', function (n) { + return n.toFixed(2); + }); + let numberDigitGroupSep = NETDATA.dataAttribute(state.element, 'sparkline-numberdigitgroupsep', undefined); + let numberDecimalMark = NETDATA.dataAttribute(state.element, 'sparkline-numberdecimalmark', undefined); + let numberDigitGroupCount = NETDATA.dataAttribute(state.element, 'sparkline-numberdigitgroupcount', undefined); + let animatedZooms = NETDATA.dataAttributeBoolean(state.element, 'sparkline-animatedzooms', false); + + if (spotColor === 'disable') { + spotColor = ''; + } + if (minSpotColor === 'disable') { + minSpotColor = ''; + } + if (maxSpotColor === 'disable') { + maxSpotColor = ''; + } + + // state.log('sparkline type ' + type + ', lineColor: ' + lineColor + ', fillColor: ' + fillColor); + + state.sparkline_options = { + type: type, + lineColor: lineColor, + fillColor: fillColor, + chartRangeMin: chartRangeMin, + chartRangeMax: chartRangeMax, + composite: composite, + enableTagOptions: enableTagOptions, + tagOptionPrefix: tagOptionPrefix, + tagValuesAttribute: tagValuesAttribute, + disableHiddenCheck: disableHiddenCheck, + defaultPixelsPerValue: defaultPixelsPerValue, + spotColor: spotColor, + minSpotColor: minSpotColor, + maxSpotColor: maxSpotColor, + spotRadius: spotRadius, + valueSpots: valueSpots, + highlightSpotColor: highlightSpotColor, + highlightLineColor: highlightLineColor, + lineWidth: lineWidth, + normalRangeMin: normalRangeMin, + normalRangeMax: normalRangeMax, + drawNormalOnTop: drawNormalOnTop, + xvalues: xvalues, + chartRangeClip: chartRangeClip, + chartRangeMinX: chartRangeMinX, + chartRangeMaxX: chartRangeMaxX, + disableInteraction: disableInteraction, + disableTooltips: disableTooltips, + disableHighlight: disableHighlight, + highlightLighten: highlightLighten, + highlightColor: highlightColor, + tooltipContainer: tooltipContainer, + tooltipClassname: tooltipClassname, + tooltipChartTitle: state.title, + tooltipFormat: tooltipFormat, + tooltipPrefix: tooltipPrefix, + tooltipSuffix: tooltipSuffix, + tooltipSkipNull: tooltipSkipNull, + tooltipValueLookups: tooltipValueLookups, + tooltipFormatFieldlist: tooltipFormatFieldlist, + tooltipFormatFieldlistKey: tooltipFormatFieldlistKey, + numberFormatter: numberFormatter, + numberDigitGroupSep: numberDigitGroupSep, + numberDecimalMark: numberDecimalMark, + numberDigitGroupCount: numberDigitGroupCount, + animatedZooms: animatedZooms, + width: state.chartWidth(), + height: state.chartHeight() + }; + + $(state.element_chart).sparkline(data.result, state.sparkline_options); + + return true; +}; +// google charts + +NETDATA.googleInitialize = function (callback) { + if (typeof netdataNoGoogleCharts === 'undefined' || !netdataNoGoogleCharts) { + $.ajax({ + url: NETDATA.google_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('google', NETDATA.google_js); + google.load('visualization', '1.1', { + 'packages': ['corechart', 'controls'], + 'callback': callback + }); + }) + .fail(function () { + NETDATA.chartLibraries.google.enabled = false; + NETDATA.error(100, NETDATA.google_js); + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.google.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.googleChartUpdate = function (state, data) { + let datatable = new google.visualization.DataTable(data.result); + state.google_instance.draw(datatable, state.google_options); + return true; +}; + +NETDATA.googleChartCreate = function (state, data) { + let datatable = new google.visualization.DataTable(data.result); + + state.google_options = { + colors: state.chartColors(), + + // do not set width, height - the chart resizes itself + //width: state.chartWidth(), + //height: state.chartHeight(), + lineWidth: 1, + title: state.title, + fontSize: 11, + hAxis: { + // title: "Time of Day", + // format:'HH:mm:ss', + viewWindowMode: 'maximized', + slantedText: false, + format: 'HH:mm:ss', + textStyle: { + fontSize: 9 + }, + gridlines: { + color: '#EEE' + } + }, + vAxis: { + title: state.units_current, + viewWindowMode: 'pretty', + minValue: -0.1, + maxValue: 0.1, + direction: 1, + textStyle: { + fontSize: 9 + }, + gridlines: { + color: '#EEE' + } + }, + chartArea: { + width: '65%', + height: '80%' + }, + focusTarget: 'category', + annotation: { + '1': { + style: 'line' + } + }, + pointsVisible: 0, + titlePosition: 'out', + titleTextStyle: { + fontSize: 11 + }, + tooltip: { + isHtml: false, + ignoreBounds: true, + textStyle: { + fontSize: 9 + } + }, + curveType: 'function', + areaOpacity: 0.3, + isStacked: false + }; + + switch (state.chart.chart_type) { + case "area": + state.google_options.vAxis.viewWindowMode = 'maximized'; + state.google_options.areaOpacity = NETDATA.options.current.color_fill_opacity_area; + state.google_instance = new google.visualization.AreaChart(state.element_chart); + break; + + case "stacked": + state.google_options.isStacked = true; + state.google_options.areaOpacity = NETDATA.options.current.color_fill_opacity_stacked; + state.google_options.vAxis.viewWindowMode = 'maximized'; + state.google_options.vAxis.minValue = null; + state.google_options.vAxis.maxValue = null; + state.google_instance = new google.visualization.AreaChart(state.element_chart); + break; + + default: + case "line": + state.google_options.lineWidth = 2; + state.google_instance = new google.visualization.LineChart(state.element_chart); + break; + } + + state.google_instance.draw(datatable, state.google_options); + return true; +}; +// gauge.js + +NETDATA.gaugeInitialize = function (callback) { + if (typeof netdataNoGauge === 'undefined' || !netdataNoGauge) { + $.ajax({ + url: NETDATA.gauge_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('gauge', NETDATA.gauge_js); + }) + .fail(function () { + NETDATA.chartLibraries.gauge.enabled = false; + NETDATA.error(100, NETDATA.gauge_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }) + } + else { + NETDATA.chartLibraries.gauge.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.gaugeAnimation = function (state, status) { + let speed = 32; + + if (typeof status === 'boolean' && status === false) { + speed = 1000000000; + } else if (typeof status === 'number') { + speed = status; + } + + // console.log('gauge speed ' + speed); + state.tmp.gauge_instance.animationSpeed = speed; + state.tmp.___gaugeOld__.speed = speed; +}; + +NETDATA.gaugeSet = function (state, value, min, max) { + if (typeof value !== 'number') { + value = 0; + } + if (typeof min !== 'number') { + min = 0; + } + if (typeof max !== 'number') { + max = 0; + } + if (value > max) { + max = value; + } + if (value < min) { + min = value; + } + if (min > max) { + let t = min; + min = max; + max = t; + } + else if (min === max) { + max = min + 1; + } + + state.legendFormatValueDecimalsFromMinMax(min, max); + + // gauge.js has an issue if the needle + // is smaller than min or larger than max + // when we set the new values + // the needle will go crazy + + // to prevent it, we always feed it + // with a percentage, so that the needle + // is always between min and max + let pcent = (value - min) * 100 / (max - min); + + // bug fix for gauge.js 1.3.1 + // if the value is the absolute min or max, the chart is broken + if (pcent < 0.001) { + pcent = 0.001; + } + if (pcent > 99.999) { + pcent = 99.999; + } + + state.tmp.gauge_instance.set(pcent); + // console.log('gauge set ' + pcent + ', value ' + value + ', min ' + min + ', max ' + max); + + state.tmp.___gaugeOld__.value = value; + state.tmp.___gaugeOld__.min = min; + state.tmp.___gaugeOld__.max = max; +}; + +NETDATA.gaugeSetLabels = function (state, value, min, max) { + if (state.tmp.___gaugeOld__.valueLabel !== value) { + state.tmp.___gaugeOld__.valueLabel = value; + state.tmp.gaugeChartLabel.innerText = state.legendFormatValue(value); + } + if (state.tmp.___gaugeOld__.minLabel !== min) { + state.tmp.___gaugeOld__.minLabel = min; + state.tmp.gaugeChartMin.innerText = state.legendFormatValue(min); + } + if (state.tmp.___gaugeOld__.maxLabel !== max) { + state.tmp.___gaugeOld__.maxLabel = max; + state.tmp.gaugeChartMax.innerText = state.legendFormatValue(max); + } +}; + +NETDATA.gaugeClearSelection = function (state, force) { + if (typeof state.tmp.gaugeEvent !== 'undefined' && typeof state.tmp.gaugeEvent.timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.gaugeEvent.timer); + state.tmp.gaugeEvent.timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.gaugeChartUpdate(state, state.data); + } else { + NETDATA.gaugeAnimation(state, false); + NETDATA.gaugeSetLabels(state, null, null, null); + NETDATA.gaugeSet(state, null, null, null); + } + + NETDATA.gaugeAnimation(state, true); + return true; +}; + +NETDATA.gaugeSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.gaugeClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.gaugeClearSelection(state, true); + } + + if (typeof state.tmp.gaugeEvent === 'undefined') { + state.tmp.gaugeEvent = { + timer: undefined, + value: 0, + min: 0, + max: 0 + }; + } + + let value = state.data.result[state.data.result.length - 1 - slot]; + let min = (state.tmp.gaugeMin === null) ? NETDATA.commonMin.get(state) : state.tmp.gaugeMin; + let max = (state.tmp.gaugeMax === null) ? NETDATA.commonMax.get(state) : state.tmp.gaugeMax; + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + state.tmp.gaugeEvent.value = value; + state.tmp.gaugeEvent.min = min; + state.tmp.gaugeEvent.max = max; + NETDATA.gaugeSetLabels(state, value, min, max); + + if (state.tmp.gaugeEvent.timer === undefined) { + NETDATA.gaugeAnimation(state, false); + + state.tmp.gaugeEvent.timer = NETDATA.timeout.set(function () { + state.tmp.gaugeEvent.timer = undefined; + NETDATA.gaugeSet(state, state.tmp.gaugeEvent.value, state.tmp.gaugeEvent.min, state.tmp.gaugeEvent.max); + }, 0); + } + + return true; +}; + +NETDATA.gaugeChartUpdate = function (state, data) { + let value, min, max; + + if (NETDATA.globalPanAndZoom.isActive() || state.isAutoRefreshable() === false) { + NETDATA.gaugeSetLabels(state, null, null, null); + state.tmp.gauge_instance.set(0); + } else { + value = data.result[0]; + min = (state.tmp.gaugeMin === null) ? NETDATA.commonMin.get(state) : state.tmp.gaugeMin; + max = (state.tmp.gaugeMax === null) ? NETDATA.commonMax.get(state) : state.tmp.gaugeMax; + if (value < min) { + min = value; + } + if (value > max) { + max = value; + } + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + NETDATA.gaugeSet(state, value, min, max); + NETDATA.gaugeSetLabels(state, value, min, max); + } + + return true; +}; + +NETDATA.gaugeChartCreate = function (state, data) { + // let chart = $(state.element_chart); + + let value = data.result[0]; + let min = NETDATA.dataAttribute(state.element, 'gauge-min-value', null); + let max = NETDATA.dataAttribute(state.element, 'gauge-max-value', null); + // let adjust = NETDATA.dataAttribute(state.element, 'gauge-adjust', null); + let pointerColor = NETDATA.dataAttribute(state.element, 'gauge-pointer-color', NETDATA.themes.current.gauge_pointer); + let strokeColor = NETDATA.dataAttribute(state.element, 'gauge-stroke-color', NETDATA.themes.current.gauge_stroke); + let startColor = NETDATA.dataAttribute(state.element, 'gauge-start-color', state.chartCustomColors()[0]); + let stopColor = NETDATA.dataAttribute(state.element, 'gauge-stop-color', void 0); + let generateGradient = NETDATA.dataAttribute(state.element, 'gauge-generate-gradient', false); + + if (min === null) { + min = NETDATA.commonMin.get(state); + state.tmp.gaugeMin = null; + } else { + state.tmp.gaugeMin = min; + } + + if (max === null) { + max = NETDATA.commonMax.get(state); + state.tmp.gaugeMax = null; + } else { + state.tmp.gaugeMax = max; + } + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + let width = state.chartWidth(), height = state.chartHeight(); //, ratio = 1.5; + // console.log('gauge width: ' + width.toString() + ', height: ' + height.toString()); + //switch(adjust) { + // case 'width': width = height * ratio; break; + // case 'height': + // default: height = width / ratio; break; + //} + //state.element.style.width = width.toString() + 'px'; + //state.element.style.height = height.toString() + 'px'; + + let lum_d = 0.05; + + let options = { + lines: 12, // The number of lines to draw + angle: 0.14, // The span of the gauge arc + lineWidth: 0.57, // The line thickness + radiusScale: 1.0, // Relative radius + pointer: { + length: 0.85, // 0.9 The radius of the inner circle + strokeWidth: 0.045, // The rotation offset + color: pointerColor // Fill color + }, + limitMax: true, // If false, the max value of the gauge will be updated if value surpass max + limitMin: true, // If true, the min value of the gauge will be fixed unless you set it manually + colorStart: startColor, // Colors + colorStop: stopColor, // just experiment with them + strokeColor: strokeColor, // to see which ones work best for you + generateGradient: (generateGradient === true), // gmosx: + gradientType: 0, + highDpiSupport: true // High resolution support + }; + + if (generateGradient.constructor === Array) { + // example options: + // data-gauge-generate-gradient="[0, 50, 100]" + // data-gauge-gradient-percent-color-0="#FFFFFF" + // data-gauge-gradient-percent-color-50="#999900" + // data-gauge-gradient-percent-color-100="#000000" + + options.percentColors = []; + let len = generateGradient.length; + while (len--) { + let pcent = generateGradient[len]; + let color = NETDATA.dataAttribute(state.element, 'gauge-gradient-percent-color-' + pcent.toString(), false); + if (color !== false) { + let a = []; + a[0] = pcent / 100; + a[1] = color; + options.percentColors.unshift(a); + } + } + if (options.percentColors.length === 0) { + delete options.percentColors; + } + } else if (generateGradient === false && NETDATA.themes.current.gauge_gradient) { + //noinspection PointlessArithmeticExpressionJS + options.percentColors = [ + [0.0, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 0))], + [0.1, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 1))], + [0.2, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 2))], + [0.3, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 3))], + [0.4, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 4))], + [0.5, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 5))], + [0.6, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 6))], + [0.7, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 7))], + [0.8, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 8))], + [0.9, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 9))], + [1.0, NETDATA.colorLuminance(startColor, 0.0)]]; + } + + state.tmp.gauge_canvas = document.createElement('canvas'); + state.tmp.gauge_canvas.id = 'gauge-' + state.uuid + '-canvas'; + state.tmp.gauge_canvas.className = 'gaugeChart'; + state.tmp.gauge_canvas.width = width; + state.tmp.gauge_canvas.height = height; + state.element_chart.appendChild(state.tmp.gauge_canvas); + + let valuefontsize = Math.floor(height / 5); + let valuetop = Math.round((height - valuefontsize) / 3.2); + state.tmp.gaugeChartLabel = document.createElement('span'); + state.tmp.gaugeChartLabel.className = 'gaugeChartLabel'; + state.tmp.gaugeChartLabel.style.fontSize = valuefontsize + 'px'; + state.tmp.gaugeChartLabel.style.top = valuetop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartLabel); + + let titlefontsize = Math.round(valuefontsize / 2.1); + let titletop = 0; + state.tmp.gaugeChartTitle = document.createElement('span'); + state.tmp.gaugeChartTitle.className = 'gaugeChartTitle'; + state.tmp.gaugeChartTitle.innerText = state.title; + state.tmp.gaugeChartTitle.style.fontSize = titlefontsize + 'px'; + state.tmp.gaugeChartTitle.style.lineHeight = titlefontsize + 'px'; + state.tmp.gaugeChartTitle.style.top = titletop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartTitle); + + let unitfontsize = Math.round(titlefontsize * 0.9); + state.tmp.gaugeChartUnits = document.createElement('span'); + state.tmp.gaugeChartUnits.className = 'gaugeChartUnits'; + state.tmp.gaugeChartUnits.innerText = state.units_current; + state.tmp.gaugeChartUnits.style.fontSize = unitfontsize + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartUnits); + + state.tmp.gaugeChartMin = document.createElement('span'); + state.tmp.gaugeChartMin.className = 'gaugeChartMin'; + state.tmp.gaugeChartMin.style.fontSize = Math.round(valuefontsize * 0.75).toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartMin); + + state.tmp.gaugeChartMax = document.createElement('span'); + state.tmp.gaugeChartMax.className = 'gaugeChartMax'; + state.tmp.gaugeChartMax.style.fontSize = Math.round(valuefontsize * 0.75).toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartMax); + + // when we just re-create the chart + // do not animate the first update + let animate = true; + if (typeof state.tmp.gauge_instance !== 'undefined') { + animate = false; + } + + state.tmp.gauge_instance = new Gauge(state.tmp.gauge_canvas).setOptions(options); // create sexy gauge! + + state.tmp.___gaugeOld__ = { + value: value, + min: min, + max: max, + valueLabel: null, + minLabel: null, + maxLabel: null + }; + + // we will always feed a percentage + state.tmp.gauge_instance.minValue = 0; + state.tmp.gauge_instance.maxValue = 100; + + NETDATA.gaugeAnimation(state, animate); + NETDATA.gaugeSet(state, value, min, max); + NETDATA.gaugeSetLabels(state, value, min, max); + NETDATA.gaugeAnimation(state, true); + + state.legendSetUnitsString = function (units) { + if (typeof state.tmp.gaugeChartUnits !== 'undefined' && state.tmp.units !== units) { + state.tmp.gaugeChartUnits.innerText = units; + state.tmp.___gaugeOld__.valueLabel = null; + state.tmp.___gaugeOld__.minLabel = null; + state.tmp.___gaugeOld__.maxLabel = null; + state.tmp.units = units; + } + }; + state.legendShowUndefined = function () { + if (typeof state.tmp.gauge_instance !== 'undefined') { + NETDATA.gaugeClearSelection(state); + } + }; + + return true; +}; +// ---------------------------------------------------------------------------------------------------------------- + +NETDATA.easypiechartPercentFromValueMinMax = function (state, value, min, max) { + if (typeof value !== 'number') { + value = 0; + } + if (typeof min !== 'number') { + min = 0; + } + if (typeof max !== 'number') { + max = 0; + } + + if (min > max) { + let t = min; + min = max; + max = t; + } + + if (min > value) { + min = value; + } + if (max < value) { + max = value; + } + + state.legendFormatValueDecimalsFromMinMax(min, max); + + if (state.tmp.easyPieChartMin === null && min > 0) { + min = 0; + } + if (state.tmp.easyPieChartMax === null && max < 0) { + max = 0; + } + + let pcent; + + if (min < 0 && max > 0) { + // it is both positive and negative + // zero at the top center of the chart + max = (-min > max) ? -min : max; + pcent = Math.round(value * 100 / max); + } else if (value >= 0 && min >= 0 && max >= 0) { + // clockwise + pcent = Math.round((value - min) * 100 / (max - min)); + if (pcent === 0) { + pcent = 0.1; + } + } else { + // counter clockwise + pcent = Math.round((value - max) * 100 / (max - min)); + if (pcent === 0) { + pcent = -0.1; + } + } + + return pcent; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// easy-pie-chart + +NETDATA.easypiechartInitialize = function (callback) { + if (typeof netdataNoEasyPieChart === 'undefined' || !netdataNoEasyPieChart) { + $.ajax({ + url: NETDATA.easypiechart_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('easypiechart', NETDATA.easypiechart_js); + }) + .fail(function () { + NETDATA.chartLibraries.easypiechart.enabled = false; + NETDATA.error(100, NETDATA.easypiechart_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }) + } else { + NETDATA.chartLibraries.easypiechart.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.easypiechartClearSelection = function (state, force) { + if (typeof state.tmp.easyPieChartEvent !== 'undefined' && typeof state.tmp.easyPieChartEvent.timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.easyPieChartEvent.timer); + state.tmp.easyPieChartEvent.timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.easypiechartChartUpdate(state, state.data); + } + else { + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(null); + state.tmp.easyPieChart_instance.update(0); + } + state.tmp.easyPieChart_instance.enableAnimation(); + + return true; +}; + +NETDATA.easypiechartSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.easypiechartClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.easypiechartClearSelection(state, true); + } + + if (typeof state.tmp.easyPieChartEvent === 'undefined') { + state.tmp.easyPieChartEvent = { + timer: undefined, + value: 0, + pcent: 0 + }; + } + + let value = state.data.result[state.data.result.length - 1 - slot]; + let min = (state.tmp.easyPieChartMin === null) ? NETDATA.commonMin.get(state) : state.tmp.easyPieChartMin; + let max = (state.tmp.easyPieChartMax === null) ? NETDATA.commonMax.get(state) : state.tmp.easyPieChartMax; + let pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + + state.tmp.easyPieChartEvent.value = value; + state.tmp.easyPieChartEvent.pcent = pcent; + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + + if (state.tmp.easyPieChartEvent.timer === undefined) { + state.tmp.easyPieChart_instance.disableAnimation(); + + state.tmp.easyPieChartEvent.timer = NETDATA.timeout.set(function () { + state.tmp.easyPieChartEvent.timer = undefined; + state.tmp.easyPieChart_instance.update(state.tmp.easyPieChartEvent.pcent); + }, 0); + } + + return true; +}; + +NETDATA.easypiechartChartUpdate = function (state, data) { + let value, min, max, pcent; + + if (NETDATA.globalPanAndZoom.isActive() || state.isAutoRefreshable() === false) { + value = null; + pcent = 0; + } + else { + value = data.result[0]; + min = (state.tmp.easyPieChartMin === null) ? NETDATA.commonMin.get(state) : state.tmp.easyPieChartMin; + max = (state.tmp.easyPieChartMax === null) ? NETDATA.commonMax.get(state) : state.tmp.easyPieChartMax; + pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + } + + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + state.tmp.easyPieChart_instance.update(pcent); + return true; +}; + +NETDATA.easypiechartChartCreate = function (state, data) { + let chart = $(state.element_chart); + + let value = data.result[0]; + let min = NETDATA.dataAttribute(state.element, 'easypiechart-min-value', null); + let max = NETDATA.dataAttribute(state.element, 'easypiechart-max-value', null); + + if (min === null) { + min = NETDATA.commonMin.get(state); + state.tmp.easyPieChartMin = null; + } + else { + state.tmp.easyPieChartMin = min; + } + + if (max === null) { + max = NETDATA.commonMax.get(state); + state.tmp.easyPieChartMax = null; + } + else { + state.tmp.easyPieChartMax = max; + } + + let size = state.chartWidth(); + let stroke = Math.floor(size / 22); + if (stroke < 3) { + stroke = 2; + } + + let valuefontsize = Math.floor((size * 2 / 3) / 5); + let valuetop = Math.round((size - valuefontsize - (size / 40)) / 2); + state.tmp.easyPieChartLabel = document.createElement('span'); + state.tmp.easyPieChartLabel.className = 'easyPieChartLabel'; + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + state.tmp.easyPieChartLabel.style.fontSize = valuefontsize + 'px'; + state.tmp.easyPieChartLabel.style.top = valuetop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartLabel); + + let titlefontsize = Math.round(valuefontsize * 1.6 / 3); + let titletop = Math.round(valuetop - (titlefontsize * 2) - (size / 40)); + state.tmp.easyPieChartTitle = document.createElement('span'); + state.tmp.easyPieChartTitle.className = 'easyPieChartTitle'; + state.tmp.easyPieChartTitle.innerText = state.title; + state.tmp.easyPieChartTitle.style.fontSize = titlefontsize + 'px'; + state.tmp.easyPieChartTitle.style.lineHeight = titlefontsize + 'px'; + state.tmp.easyPieChartTitle.style.top = titletop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartTitle); + + let unitfontsize = Math.round(titlefontsize * 0.9); + let unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40)); + state.tmp.easyPieChartUnits = document.createElement('span'); + state.tmp.easyPieChartUnits.className = 'easyPieChartUnits'; + state.tmp.easyPieChartUnits.innerText = state.units_current; + state.tmp.easyPieChartUnits.style.fontSize = unitfontsize + 'px'; + state.tmp.easyPieChartUnits.style.top = unittop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartUnits); + + let barColor = NETDATA.dataAttribute(state.element, 'easypiechart-barcolor', undefined); + if (typeof barColor === 'undefined' || barColor === null) { + barColor = state.chartCustomColors()[0]; + } else { + // <div ... data-easypiechart-barcolor="(function(percent){return(percent < 50 ? '#5cb85c' : percent < 85 ? '#f0ad4e' : '#cb3935');})" ...></div> + let tmp = eval(barColor); + if (typeof tmp === 'function') { + barColor = tmp; + } + } + + let pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + chart.data('data-percent', pcent); + + chart.easyPieChart({ + barColor: barColor, + trackColor: NETDATA.dataAttribute(state.element, 'easypiechart-trackcolor', NETDATA.themes.current.easypiechart_track), + scaleColor: NETDATA.dataAttribute(state.element, 'easypiechart-scalecolor', NETDATA.themes.current.easypiechart_scale), + scaleLength: NETDATA.dataAttribute(state.element, 'easypiechart-scalelength', 5), + lineCap: NETDATA.dataAttribute(state.element, 'easypiechart-linecap', 'round'), + lineWidth: NETDATA.dataAttribute(state.element, 'easypiechart-linewidth', stroke), + trackWidth: NETDATA.dataAttribute(state.element, 'easypiechart-trackwidth', undefined), + size: NETDATA.dataAttribute(state.element, 'easypiechart-size', size), + rotate: NETDATA.dataAttribute(state.element, 'easypiechart-rotate', 0), + animate: NETDATA.dataAttribute(state.element, 'easypiechart-animate', {duration: 500, enabled: true}), + easing: NETDATA.dataAttribute(state.element, 'easypiechart-easing', undefined) + }); + + // when we just re-create the chart + // do not animate the first update + let animate = true; + if (typeof state.tmp.easyPieChart_instance !== 'undefined') { + animate = false; + } + + state.tmp.easyPieChart_instance = chart.data('easyPieChart'); + if (animate === false) { + state.tmp.easyPieChart_instance.disableAnimation(); + } + state.tmp.easyPieChart_instance.update(pcent); + if (animate === false) { + state.tmp.easyPieChart_instance.enableAnimation(); + } + + state.legendSetUnitsString = function (units) { + if (typeof state.tmp.easyPieChartUnits !== 'undefined' && state.tmp.units !== units) { + state.tmp.easyPieChartUnits.innerText = units; + state.tmp.units = units; + } + }; + state.legendShowUndefined = function () { + if (typeof state.tmp.easyPieChart_instance !== 'undefined') { + NETDATA.easypiechartClearSelection(state); + } + }; + + return true; +}; + +// d3pie + +NETDATA.d3pieInitialize = function (callback) { + if (typeof netdataNoD3pie === 'undefined' || !netdataNoD3pie) { + + // d3pie requires D3 + if (!NETDATA.chartLibraries.d3.initialized) { + if (NETDATA.chartLibraries.d3.enabled) { + NETDATA.d3Initialize(function () { + NETDATA.d3pieInitialize(callback); + }); + } else { + NETDATA.chartLibraries.d3pie.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } + } else { + $.ajax({ + url: NETDATA.d3pie_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('d3pie', NETDATA.d3pie_js); + }) + .fail(function () { + NETDATA.chartLibraries.d3pie.enabled = false; + NETDATA.error(100, NETDATA.d3pie_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } + } else { + NETDATA.chartLibraries.d3pie.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.d3pieSetContent = function (state, data, index) { + state.legendFormatValueDecimalsFromMinMax( + data.min, + data.max + ); + + let content = []; + let colors = state.chartColors(); + let len = data.result.labels.length; + for (let i = 1; i < len; i++) { + let label = data.result.labels[i]; + let value = data.result.data[index][label]; + let color = colors[i - 1]; + + if (value !== null && value > 0) { + content.push({ + label: label, + value: value, + color: color + }); + } + } + + if (content.length === 0) { + content.push({ + label: 'no data', + value: 100, + color: '#666666' + }); + } + + state.tmp.d3pie_last_slot = index; + return content; +}; + +NETDATA.d3pieDateRange = function (state, data, index) { + let dt = Math.round((data.before - data.after + 1) / data.points); + let dt_str = NETDATA.seconds4human(dt); + + let before = data.result.data[index].time; + let after = before - (dt * 1000); + + let d1 = NETDATA.dateTime.localeDateString(after); + let t1 = NETDATA.dateTime.localeTimeString(after); + let d2 = NETDATA.dateTime.localeDateString(before); + let t2 = NETDATA.dateTime.localeTimeString(before); + + if (d1 === d2) { + return d1 + ' ' + t1 + ' to ' + t2 + ', ' + dt_str; + } + + return d1 + ' ' + t1 + ' to ' + d2 + ' ' + t2 + ', ' + dt_str; +}; + +NETDATA.d3pieSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.d3pieClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + slot = state.data.result.data.length - slot - 1; + + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.d3pieClearSelection(state, true); + } + + if (state.tmp.d3pie_last_slot === slot) { + // we already show this slot, don't do anything + return true; + } + + if (state.tmp.d3pie_timer === undefined) { + state.tmp.d3pie_timer = NETDATA.timeout.set(function () { + state.tmp.d3pie_timer = undefined; + NETDATA.d3pieChange(state, NETDATA.d3pieSetContent(state, state.data, slot), NETDATA.d3pieDateRange(state, state.data, slot)); + }, 0); + } + + return true; +}; + +NETDATA.d3pieClearSelection = function (state, force) { + if (typeof state.tmp.d3pie_timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.d3pie_timer); + state.tmp.d3pie_timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.d3pieChartUpdate(state, state.data); + } else { + if (state.tmp.d3pie_last_slot !== -1) { + state.tmp.d3pie_last_slot = -1; + NETDATA.d3pieChange(state, [{label: 'no data', value: 1, color: '#666666'}], 'no data available'); + } + } + + return true; +}; + +NETDATA.d3pieChange = function (state, content, footer) { + if (state.d3pie_forced_subtitle === null) { + //state.d3pie_instance.updateProp("header.subtitle.text", state.units_current); + state.d3pie_instance.options.header.subtitle.text = state.units_current; + } + + if (state.d3pie_forced_footer === null) { + //state.d3pie_instance.updateProp("footer.text", footer); + state.d3pie_instance.options.footer.text = footer; + } + + //state.d3pie_instance.updateProp("data.content", content); + state.d3pie_instance.options.data.content = content; + state.d3pie_instance.destroy(); + state.d3pie_instance.recreate(); + return true; +}; + +NETDATA.d3pieChartUpdate = function (state, data) { + return NETDATA.d3pieChange(state, NETDATA.d3pieSetContent(state, data, 0), NETDATA.d3pieDateRange(state, data, 0)); +}; + +NETDATA.d3pieChartCreate = function (state, data) { + + state.element_chart.id = 'd3pie-' + state.uuid; + // console.log('id = ' + state.element_chart.id); + + let content = NETDATA.d3pieSetContent(state, data, 0); + + state.d3pie_forced_title = NETDATA.dataAttribute(state.element, 'd3pie-title', null); + state.d3pie_forced_subtitle = NETDATA.dataAttribute(state.element, 'd3pie-subtitle', null); + state.d3pie_forced_footer = NETDATA.dataAttribute(state.element, 'd3pie-footer', null); + + state.d3pie_options = { + header: { + title: { + text: (state.d3pie_forced_title !== null) ? state.d3pie_forced_title : state.title, + color: NETDATA.dataAttribute(state.element, 'd3pie-title-color', NETDATA.themes.current.d3pie.title), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-title-fontsize', 12), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-title-fontweight', "bold"), + font: NETDATA.dataAttribute(state.element, 'd3pie-title-font', "arial") + }, + subtitle: { + text: (state.d3pie_forced_subtitle !== null) ? state.d3pie_forced_subtitle : state.units_current, + color: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-color', NETDATA.themes.current.d3pie.subtitle), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-fontweight', "normal"), + font: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-font', "arial") + }, + titleSubtitlePadding: 1 + }, + footer: { + text: (state.d3pie_forced_footer !== null) ? state.d3pie_forced_footer : NETDATA.d3pieDateRange(state, data, 0), + color: NETDATA.dataAttribute(state.element, 'd3pie-footer-color', NETDATA.themes.current.d3pie.footer), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-footer-fontsize', 9), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-footer-fontweight', "bold"), + font: NETDATA.dataAttribute(state.element, 'd3pie-footer-font', "arial"), + location: NETDATA.dataAttribute(state.element, 'd3pie-footer-location', "bottom-center") // bottom-left, bottom-center, bottom-right + }, + size: { + canvasHeight: state.chartHeight(), + canvasWidth: state.chartWidth(), + pieInnerRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieinnerradius', "45%"), + pieOuterRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieouterradius', "80%") + }, + data: { + // none, random, value-asc, value-desc, label-asc, label-desc + sortOrder: NETDATA.dataAttribute(state.element, 'd3pie-sortorder', "value-desc"), + smallSegmentGrouping: { + enabled: NETDATA.dataAttributeBoolean(state.element, "d3pie-smallsegmentgrouping-enabled", false), + value: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-value', 1), + // percentage, value + valueType: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-valuetype', "percentage"), + label: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-label', "other"), + color: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-color', NETDATA.themes.current.d3pie.other) + }, + + // REQUIRED! This is where you enter your pie data; it needs to be an array of objects + // of this form: { label: "label", value: 1.5, color: "#000000" } - color is optional + content: content + }, + labels: { + outer: { + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-format', "label-value1"), + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-hidewhenlessthanpercentage', null), + pieDistance: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-piedistance', 15) + }, + inner: { + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-format', "percentage"), + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-hidewhenlessthanpercentage', 2) + }, + mainLabel: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-color', NETDATA.themes.current.d3pie.mainlabel), // or 'segment' for dynamic color + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-fontweight', "normal") + }, + percentage: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-color', NETDATA.themes.current.d3pie.percentage), + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-fontweight', "bold"), + decimalPlaces: 0 + }, + value: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-color', NETDATA.themes.current.d3pie.value), + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-fontweight', "bold") + }, + lines: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-labels-lines-enabled', true), + style: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-style', "curved"), + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-color', "segment") // "segment" or a hex color + }, + truncation: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-labels-truncation-enabled', false), + truncateLength: NETDATA.dataAttribute(state.element, 'd3pie-labels-truncation-truncatelength', 30) + }, + formatter: function (context) { + // console.log(context); + if (context.part === 'value') { + return state.legendFormatValue(context.value); + } + if (context.part === 'percentage') { + return context.label + '%'; + } + + return context.label; + } + }, + effects: { + load: { + effect: "none", // none / default + speed: 0 // commented in the d3pie code to speed it up + }, + pullOutSegmentOnClick: { + effect: "bounce", // none / linear / bounce / elastic / back + speed: 400, + size: 5 + }, + highlightSegmentOnMouseover: true, + highlightLuminosity: -0.2 + }, + tooltips: { + enabled: false, + type: "placeholder", // caption|placeholder + string: "", + placeholderParser: null, // function + styles: { + fadeInSpeed: 250, + backgroundColor: NETDATA.themes.current.d3pie.tooltip_bg, + backgroundOpacity: 0.5, + color: NETDATA.themes.current.d3pie.tooltip_fg, + borderRadius: 2, + font: "arial", + fontSize: 12, + padding: 4 + } + }, + misc: { + colors: { + background: 'transparent', // transparent or color # + // segments: state.chartColors(), + segmentStroke: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-segmentstroke', NETDATA.themes.current.d3pie.segment_stroke) + }, + gradient: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-misc-gradient-enabled', false), + percentage: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-percentage', 95), + color: NETDATA.dataAttribute(state.element, 'd3pie-misc-gradient-color', NETDATA.themes.current.d3pie.gradient_color) + }, + canvasPadding: { + top: 5, + right: 5, + bottom: 5, + left: 5 + }, + pieCenterOffset: { + x: 0, + y: 0 + }, + cssPrefix: NETDATA.dataAttribute(state.element, 'd3pie-cssprefix', null) + }, + callbacks: { + onload: null, + onMouseoverSegment: null, + onMouseoutSegment: null, + onClickSegment: null + } + }; + + state.d3pie_instance = new d3pie(state.element_chart, state.d3pie_options); + return true; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// D3 + +NETDATA.d3Initialize = function(callback) { + if (typeof netdataStopD3 === 'undefined' || !netdataStopD3) { + $.ajax({ + url: NETDATA.d3_js, + cache: true, + dataType: "script", + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function() { + NETDATA.registerChartLibrary('d3', NETDATA.d3_js); + }) + .fail(function() { + NETDATA.chartLibraries.d3.enabled = false; + NETDATA.error(100, NETDATA.d3_js); + }) + .always(function() { + if (typeof callback === "function") + return callback(); + }); + } else { + NETDATA.chartLibraries.d3.enabled = false; + if (typeof callback === "function") + return callback(); + } +}; + +NETDATA.d3ChartUpdate = function(state, data) { + void(state); + void(data); + + return false; +}; + +NETDATA.d3ChartCreate = function(state, data) { + void(state); + void(data); + + return false; +}; + +// peity + +NETDATA.peityInitialize = function (callback) { + if (typeof netdataNoPeitys === 'undefined' || !netdataNoPeitys) { + $.ajax({ + url: NETDATA.peity_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('peity', NETDATA.peity_js); + }) + .fail(function () { + NETDATA.chartLibraries.peity.enabled = false; + NETDATA.error(100, NETDATA.peity_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.peity.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.peityChartUpdate = function (state, data) { + state.peity_instance.innerHTML = data.result; + + if (state.peity_options.stroke !== state.chartCustomColors()[0]) { + state.peity_options.stroke = state.chartCustomColors()[0]; + if (state.chart.chart_type === 'line') { + state.peity_options.fill = NETDATA.themes.current.background; + } else { + state.peity_options.fill = NETDATA.colorLuminance(state.chartCustomColors()[0], NETDATA.chartDefaults.fill_luminance); + } + } + + $(state.peity_instance).peity('line', state.peity_options); + return true; +}; + +NETDATA.peityChartCreate = function (state, data) { + state.peity_instance = document.createElement('div'); + state.element_chart.appendChild(state.peity_instance); + + state.peity_options = { + stroke: NETDATA.themes.current.foreground, + strokeWidth: NETDATA.dataAttribute(state.element, 'peity-strokewidth', 1), + width: state.chartWidth(), + height: state.chartHeight(), + fill: NETDATA.themes.current.foreground + }; + + NETDATA.peityChartUpdate(state, data); + return true; +}; + +// Charts Libraries Registration + +NETDATA.chartLibraries = { + "dygraph": { + initialize: NETDATA.dygraphInitialize, + create: NETDATA.dygraphChartCreate, + update: NETDATA.dygraphChartUpdate, + resize: function (state) { + if (typeof state.tmp.dygraph_instance !== 'undefined' && typeof state.tmp.dygraph_instance.resize === 'function') { + state.tmp.dygraph_instance.resize(); + } + }, + setSelection: NETDATA.dygraphSetSelection, + clearSelection: NETDATA.dygraphClearSelection, + toolboxPanAndZoom: NETDATA.dygraphToolboxPanAndZoom, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + return 'ms' + '%7C' + 'flip' + (this.isLogScale(state) ? ('%7C' + 'abs') : '').toString(); + }, + legend: function (state) { + return (this.isSparkline(state) === false && NETDATA.dataAttributeBoolean(state.element, 'legend', true) === true) ? 'right-side' : null; + }, + autoresize: function (state) { + void(state); + return true; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + return (this.isSparkline(state) === false) ? 3 : 2; + }, + isSparkline: function (state) { + if (typeof state.tmp.dygraph_sparkline === 'undefined') { + state.tmp.dygraph_sparkline = (this.theme(state) === 'sparkline'); + } + return state.tmp.dygraph_sparkline; + }, + isLogScale: function (state) { + if (typeof state.tmp.dygraph_logscale === 'undefined') { + state.tmp.dygraph_logscale = (this.theme(state) === 'logscale'); + } + return state.tmp.dygraph_logscale; + }, + theme: function (state) { + if (typeof state.tmp.dygraph_theme === 'undefined') { + state.tmp.dygraph_theme = NETDATA.dataAttribute(state.element, 'dygraph-theme', 'default'); + } + return state.tmp.dygraph_theme; + }, + container_class: function (state) { + if (this.legend(state) !== null) { + return 'netdata-container-with-legend'; + } + return 'netdata-container'; + } + }, + "sparkline": { + initialize: NETDATA.sparklineInitialize, + create: NETDATA.sparklineChartCreate, + update: NETDATA.sparklineChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'flip' + '%7C' + 'abs'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "peity": { + initialize: NETDATA.peityInitialize, + create: NETDATA.peityChartCreate, + update: NETDATA.peityChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'ssvcomma'; + }, + options: function (state) { + void(state); + return 'null2zero' + '%7C' + 'flip' + '%7C' + 'abs'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + // "morris": { + // initialize: NETDATA.morrisInitialize, + // create: NETDATA.morrisChartCreate, + // update: NETDATA.morrisChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + // format: function(state) { void(state); return 'json'; }, + // options: function(state) { void(state); return 'objectrows' + '%7C' + 'ms'; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 50; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 15; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + "google": { + initialize: NETDATA.googleInitialize, + create: NETDATA.googleChartCreate, + update: NETDATA.googleChartUpdate, + resize: null, + setSelection: undefined, //function(state, t) { void(state); return true; }, + clearSelection: undefined, //function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.rows$'), + format: function (state) { + void(state); + return 'datatable'; + }, + options: function (state) { + void(state); + return ''; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 300; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 4; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + // "raphael": { + // initialize: NETDATA.raphaelInitialize, + // create: NETDATA.raphaelChartCreate, + // update: NETDATA.raphaelChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + // format: function(state) { void(state); return 'json'; }, + // options: function(state) { void(state); return ''; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 5000; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 3; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + // "c3": { + // initialize: NETDATA.c3Initialize, + // create: NETDATA.c3ChartCreate, + // update: NETDATA.c3ChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + // format: function(state) { void(state); return 'csvjsonarray'; }, + // options: function(state) { void(state); return 'milliseconds'; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 5000; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 15; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + "d3pie": { + initialize: NETDATA.d3pieInitialize, + create: NETDATA.d3pieChartCreate, + update: NETDATA.d3pieChartUpdate, + resize: null, + setSelection: NETDATA.d3pieSetSelection, + clearSelection: NETDATA.d3pieClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + void(state); + return 'objectrows' + '%7C' + 'ms'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 15; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "d3": { + initialize: NETDATA.d3Initialize, + create: NETDATA.d3ChartCreate, + update: NETDATA.d3ChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + void(state); + return ''; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "easypiechart": { + initialize: NETDATA.easypiechartInitialize, + create: NETDATA.easypiechartChartCreate, + update: NETDATA.easypiechartChartUpdate, + resize: null, + setSelection: NETDATA.easypiechartSetSelection, + clearSelection: NETDATA.easypiechartClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'absolute'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + aspect_ratio: 100, + container_class: function (state) { + void(state); + return 'netdata-container-easypiechart'; + } + }, + "gauge": { + initialize: NETDATA.gaugeInitialize, + create: NETDATA.gaugeChartCreate, + update: NETDATA.gaugeChartUpdate, + resize: null, + setSelection: NETDATA.gaugeSetSelection, + clearSelection: NETDATA.gaugeClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'absolute'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + aspect_ratio: 60, + container_class: function (state) { + void(state); + return 'netdata-container-gauge'; + } + } +}; + +NETDATA.registerChartLibrary = function (library, url) { + if (NETDATA.options.debug.libraries) { + console.log("registering chart library: " + library); + } + + NETDATA.chartLibraries[library].url = url; + NETDATA.chartLibraries[library].initialized = true; + NETDATA.chartLibraries[library].enabled = true; +}; + +// *** src/dashboard.js/chart-registry.js + +// Chart Registry + +// When multiple charts need the same chart, we avoid downloading it +// multiple times (and having it in browser memory multiple time) +// by using this registry. + +// Every time we download a chart definition, we save it here with .add() +// Then we try to get it back with .get(). If that fails, we download it. + +NETDATA.fixHost = function (host) { + while (host.slice(-1) === '/') { + host = host.substring(0, host.length - 1); + } + + return host; +}; + +NETDATA.chartRegistry = { + charts: {}, + + globalReset: function () { + this.charts = {}; + }, + + add: function (host, id, data) { + if (typeof this.charts[host] === 'undefined') { + this.charts[host] = {}; + } + + //console.log('added ' + host + '/' + id); + this.charts[host][id] = data; + }, + + get: function (host, id) { + if (typeof this.charts[host] === 'undefined') { + return null; + } + + if (typeof this.charts[host][id] === 'undefined') { + return null; + } + + //console.log('cached ' + host + '/' + id); + return this.charts[host][id]; + }, + + downloadAll: function (host, callback) { + host = NETDATA.fixHost(host); + + let self = this; + + function got_data(h, data, callback) { + if (data !== null) { + self.charts[h] = data.charts; + + // update the server timezone in our options + if (typeof data.timezone === 'string') { + NETDATA.options.server_timezone = data.timezone; + } + } else { + NETDATA.error(406, h + '/api/v1/charts'); + } + + if (typeof callback === 'function') { + callback(data); + } + } + + if (netdataSnapshotData !== null) { + got_data(host, netdataSnapshotData.charts, callback); + } else { + $.ajax({ + url: host + '/api/v1/charts', + async: true, + cache: false, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/charts', data); + got_data(host, data, callback); + }) + .fail(function () { + NETDATA.error(405, host + '/api/v1/charts'); + + if (typeof callback === 'function') { + callback(null); + } + }); + } + } +}; + +// Compute common (joint) values over multiple charts. + + +// commonMin & commonMax + +NETDATA.commonMin = { + keys: {}, + latest: {}, + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + get: function (state) { + if (typeof state.tmp.__commonMin === 'undefined') { + // get the commonMin setting + state.tmp.__commonMin = NETDATA.dataAttribute(state.element, 'common-min', null); + } + + let min = state.data.min; + let name = state.tmp.__commonMin; + + if (name === null) { + // we don't need commonMin + //state.log('no need for commonMin'); + return min; + } + + let t = this.keys[name]; + if (typeof t === 'undefined') { + // add our commonMin + this.keys[name] = {}; + t = this.keys[name]; + } + + let uuid = state.uuid; + if (typeof t[uuid] !== 'undefined') { + if (t[uuid] === min) { + //state.log('commonMin ' + state.tmp.__commonMin + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } else if (min < this.latest[name]) { + //state.log('commonMin ' + state.tmp.__commonMin + ' increased: ' + min); + t[uuid] = min; + this.latest[name] = min; + return min; + } + } + + // add our min + t[uuid] = min; + + // find the common min + let m = min; + // for (let i in t) { + // if (t.hasOwnProperty(i) && t[i] < m) m = t[i]; + // } + for (var ti of Object.values(t)) { + if (ti < m) { + m = ti; + } + } + + //state.log('commonMin ' + state.tmp.__commonMin + ' updated: ' + m); + this.latest[name] = m; + return m; + } +}; + +NETDATA.commonMax = { + keys: {}, + latest: {}, + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + get: function (state) { + if (typeof state.tmp.__commonMax === 'undefined') { + // get the commonMax setting + state.tmp.__commonMax = NETDATA.dataAttribute(state.element, 'common-max', null); + } + + let max = state.data.max; + let name = state.tmp.__commonMax; + + if (name === null) { + // we don't need commonMax + //state.log('no need for commonMax'); + return max; + } + + let t = this.keys[name]; + if (typeof t === 'undefined') { + // add our commonMax + this.keys[name] = {}; + t = this.keys[name]; + } + + let uuid = state.uuid; + if (typeof t[uuid] !== 'undefined') { + if (t[uuid] === max) { + //state.log('commonMax ' + state.tmp.__commonMax + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } else if (max > this.latest[name]) { + //state.log('commonMax ' + state.tmp.__commonMax + ' increased: ' + max); + t[uuid] = max; + this.latest[name] = max; + return max; + } + } + + // add our max + t[uuid] = max; + + // find the common max + let m = max; + // for (let i in t) { + // if (t.hasOwnProperty(i) && t[i] > m) m = t[i]; + // } + for (var ti of Object.values(t)) { + if (ti > m) { + m = ti; + } + } + + //state.log('commonMax ' + state.tmp.__commonMax + ' updated: ' + m); + this.latest[name] = m; + return m; + } +}; + +NETDATA.commonColors = { + keys: {}, + + globalReset: function () { + this.keys = {}; + }, + + get: function (state, label) { + let ret = this.refill(state); + + if (typeof ret.assigned[label] === 'undefined') { + ret.assigned[label] = ret.available.shift(); + } + + return ret.assigned[label]; + }, + + refill: function (state) { + let ret, len; + + if (typeof state.tmp.__commonColors === 'undefined') { + ret = this.prepare(state); + } else { + ret = this.keys[state.tmp.__commonColors]; + if (typeof ret === 'undefined') { + ret = this.prepare(state); + } + } + + if (ret.available.length === 0) { + if (ret.copy_theme || ret.custom.length === 0) { + // copy the theme colors + len = NETDATA.themes.current.colors.length; + while (len--) { + ret.available.unshift(NETDATA.themes.current.colors[len]); + } + } + + // copy the custom colors + len = ret.custom.length; + while (len--) { + ret.available.unshift(ret.custom[len]); + } + } + + state.colors_assigned = ret.assigned; + state.colors_available = ret.available; + state.colors_custom = ret.custom; + + return ret; + }, + + __read_custom_colors: function (state, ret) { + // add the user supplied colors + let c = NETDATA.dataAttribute(state.element, 'colors', undefined); + if (typeof c === 'string' && c.length > 0) { + c = c.split(' '); + let len = c.length; + + if (len > 0 && c[len - 1] === 'ONLY') { + len--; + ret.copy_theme = false; + } + + while (len--) { + ret.custom.unshift(c[len]); + } + } + }, + + prepare: function (state) { + let has_custom_colors = false; + + if (typeof state.tmp.__commonColors === 'undefined') { + let defname = state.chart.context; + + // if this chart has data-colors="" + // we should use the chart uuid as the default key (private palette) + // (data-common-colors="NAME" will be used anyways) + let c = NETDATA.dataAttribute(state.element, 'colors', undefined); + if (typeof c === 'string' && c.length > 0) { + defname = state.uuid; + has_custom_colors = true; + } + + // get the commonColors setting + state.tmp.__commonColors = NETDATA.dataAttribute(state.element, 'common-colors', defname); + } + + let name = state.tmp.__commonColors; + let ret = this.keys[name]; + + if (typeof ret === 'undefined') { + // add our commonMax + this.keys[name] = { + assigned: {}, // name-value of dimensions and their colors + available: [], // an array of colors available to be used + custom: [], // the array of colors defined by the user + charts: {}, // the charts linked to this + copy_theme: true + }; + ret = this.keys[name]; + } + + if (typeof ret.charts[state.uuid] === 'undefined') { + ret.charts[state.uuid] = state; + + if (has_custom_colors) { + this.__read_custom_colors(state, ret); + } + } + + return ret; + } +}; + +// *** src/dashboard.js/main.js + +// Codacy declarations +/* global clipboard */ + +if (NETDATA.options.debug.main_loop) { + console.log('welcome to NETDATA'); +} + +NETDATA.onresizeCallback = null; +NETDATA.onresize = function () { + NETDATA.options.last_page_resize = Date.now(); + NETDATA.onscroll(); + + if (typeof NETDATA.onresizeCallback === 'function') { + NETDATA.onresizeCallback(); + } +}; + +NETDATA.abortAllRefreshes = function () { + let targets = NETDATA.options.targets; + let len = targets.length; + + while (len--) { + if (targets[len].fetching_data) { + if (typeof targets[len].xhr !== 'undefined') { + targets[len].xhr.abort(); + targets[len].running = false; + targets[len].fetching_data = false; + } + } + } +}; + +NETDATA.onscrollStartDelay = function () { + NETDATA.options.last_page_scroll = Date.now(); + + NETDATA.options.on_scroll_refresher_stop_until = + NETDATA.options.last_page_scroll + + (NETDATA.options.current.async_on_scroll ? 1000 : 0); +}; + +NETDATA.onscrollEndDelay = function () { + NETDATA.options.on_scroll_refresher_stop_until = + Date.now() + + (NETDATA.options.current.async_on_scroll ? NETDATA.options.current.onscroll_worker_duration_threshold : 0); +}; + +NETDATA.onscroll_updater_timeout_id = undefined; +NETDATA.onscrollUpdater = function () { + NETDATA.globalSelectionSync.stop(); + + if (NETDATA.options.abort_ajax_on_scroll) { + NETDATA.abortAllRefreshes(); + } + + // when the user scrolls he sees that we have + // hidden all the not-visible charts + // using this little function we try to switch + // the charts back to visible quickly + + if (!NETDATA.intersectionObserver.enabled()) { + if (!NETDATA.options.current.parallel_refresher) { + let targets = NETDATA.options.targets; + let len = targets.length; + + while (len--) { + if (!targets[len].running) { + targets[len].isVisible(); + } + } + } + } + + NETDATA.onscrollEndDelay(); +}; + +NETDATA.scrollUp = false; +NETDATA.scrollY = window.scrollY; +NETDATA.onscroll = function () { + //console.log('onscroll() begin'); + + NETDATA.onscrollStartDelay(); + NETDATA.chartRefresherReschedule(); + + NETDATA.scrollUp = (window.scrollY > NETDATA.scrollY); + NETDATA.scrollY = window.scrollY; + + if (NETDATA.onscroll_updater_timeout_id) { + NETDATA.timeout.clear(NETDATA.onscroll_updater_timeout_id); + } + + NETDATA.onscroll_updater_timeout_id = NETDATA.timeout.set(NETDATA.onscrollUpdater, 0); + //console.log('onscroll() end'); +}; + +NETDATA.supportsPassiveEvents = function () { + if (NETDATA.options.passive_events === null) { + let supportsPassive = false; + try { + let opts = Object.defineProperty({}, 'passive', { + get: function () { + supportsPassive = true; + } + }); + window.addEventListener("test", null, opts); + } catch (e) { + console.log('browser does not support passive events'); + } + + NETDATA.options.passive_events = supportsPassive; + } + + // console.log('passive ' + NETDATA.options.passive_events); + return NETDATA.options.passive_events; +}; + +window.addEventListener('resize', NETDATA.onresize, NETDATA.supportsPassiveEvents() ? {passive: true} : false); +window.addEventListener('scroll', NETDATA.onscroll, NETDATA.supportsPassiveEvents() ? {passive: true} : false); +// window.onresize = NETDATA.onresize; +// window.onscroll = NETDATA.onscroll; + +// ---------------------------------------------------------------------------------------------------------------- +// Global Pan and Zoom on charts + +// Using this structure are synchronize all the charts, so that +// when you pan or zoom one, all others are automatically refreshed +// to the same timespan. + +NETDATA.globalPanAndZoom = { + seq: 0, // timestamp ms + // every time a chart is panned or zoomed + // we set the timestamp here + // then we use it as a sequence number + // to find if other charts are synchronized + // to this time-range + + master: null, // the master chart (state), to which all others + // are synchronized + + force_before_ms: null, // the timespan to sync all other charts + force_after_ms: null, + + callback: null, + + globalReset: function () { + this.clearMaster(); + this.seq = 0; + this.master = null; + this.force_after_ms = null; + this.force_before_ms = null; + this.callback = null; + }, + + delay: function () { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.delay()'); + } + + NETDATA.options.auto_refresher_stop_until = Date.now() + NETDATA.options.current.global_pan_sync_time; + }, + + // set a new master + setMaster: function (state, after, before) { + this.delay(); + + if (!NETDATA.options.current.sync_pan_and_zoom) { + return; + } + + if (this.master === null) { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.setMaster(' + state.id + ', ' + after + ', ' + before + ') SET MASTER'); + } + } else if (this.master !== state) { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.setMaster(' + state.id + ', ' + after + ', ' + before + ') CHANGED MASTER'); + } + + this.master.resetChart(true, true); + } + + let now = Date.now(); + this.master = state; + this.seq = now; + this.force_after_ms = after; + this.force_before_ms = before; + + if (typeof this.callback === 'function') { + this.callback(true, after, before); + } + }, + + // clear the master + clearMaster: function () { + // if (NETDATA.options.debug.globalPanAndZoom === true) + // console.log('globalPanAndZoom.clearMaster()'); + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.clearMaster()'); + } + + if (this.master !== null) { + let st = this.master; + this.master = null; + st.resetChart(); + } + + this.master = null; + this.seq = 0; + this.force_after_ms = null; + this.force_before_ms = null; + NETDATA.options.auto_refresher_stop_until = 0; + + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + }, + + // is the given state the master of the global + // pan and zoom sync? + isMaster: function (state) { + return (this.master === state); + }, + + // are we currently have a global pan and zoom sync? + isActive: function () { + return (this.master !== null && this.force_before_ms !== null && this.force_after_ms !== null && this.seq !== 0); + }, + + // check if a chart, other than the master + // needs to be refreshed, due to the global pan and zoom + shouldBeAutoRefreshed: function (state) { + if (this.master === null || this.seq === 0) { + return false; + } + + //if (state.needsRecreation()) + // return true; + + return (state.tm.pan_and_zoom_seq !== this.seq); + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// global chart underlay (time-frame highlighting) + +NETDATA.globalChartUnderlay = { + callback: null, // what to call when a highlighted range is setup + after: null, // highlight after this time + before: null, // highlight before this time + view_after: null, // the charts after_ms viewport when the highlight was setup + view_before: null, // the charts before_ms viewport, when the highlight was setup + state: null, // the chart the highlight was setup + + isActive: function () { + return (this.after !== null && this.before !== null); + }, + + hasViewport: function () { + return (this.state !== null && this.view_after !== null && this.view_before !== null); + }, + + init: function (state, after, before, view_after, view_before) { + this.state = (typeof state !== 'undefined') ? state : null; + this.after = (typeof after !== 'undefined' && after !== null && after > 0) ? after : null; + this.before = (typeof before !== 'undefined' && before !== null && before > 0) ? before : null; + this.view_after = (typeof view_after !== 'undefined' && view_after !== null && view_after > 0) ? view_after : null; + this.view_before = (typeof view_before !== 'undefined' && view_before !== null && view_before > 0) ? view_before : null; + }, + + setup: function () { + if (this.isActive()) { + if (this.state === null) { + this.state = NETDATA.options.targets[0]; + } + + if (typeof this.callback === 'function') { + this.callback(true, this.after, this.before); + } + } else { + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + } + }, + + set: function (state, after, before, view_after, view_before) { + if (after > before) { + let t = after; + after = before; + before = t; + } + + this.init(state, after, before, view_after, view_before); + + // if (this.hasViewport() === true) + // NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before); + if (this.hasViewport()) { + NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before); + } + + this.setup(); + }, + + clear: function () { + this.after = null; + this.before = null; + this.state = null; + this.view_after = null; + this.view_before = null; + + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + }, + + focus: function () { + if (this.isActive() && this.hasViewport()) { + if (this.state === null) { + this.state = NETDATA.options.targets[0]; + } + + if (NETDATA.globalPanAndZoom.isMaster(this.state)) { + NETDATA.globalPanAndZoom.clearMaster(); + } + + NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before, true); + } + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// dimensions selection + +// TODO +// move color assignment to dimensions, here + +let dimensionStatus = function (parent, label, name_div, value_div, color) { + this.enabled = false; + this.parent = parent; + this.label = label; + this.name_div = null; + this.value_div = null; + this.color = NETDATA.themes.current.foreground; + this.selected = (parent.unselected_count === 0); + + this.setOptions(name_div, value_div, color); +}; + +dimensionStatus.prototype.invalidate = function () { + this.name_div = null; + this.value_div = null; + this.enabled = false; +}; + +dimensionStatus.prototype.setOptions = function (name_div, value_div, color) { + this.color = color; + + if (this.name_div !== name_div) { + this.name_div = name_div; + this.name_div.title = this.label; + this.name_div.style.setProperty('color', this.color, 'important'); + if (!this.selected) { + this.name_div.className = 'netdata-legend-name not-selected'; + } else { + this.name_div.className = 'netdata-legend-name selected'; + } + } + + if (this.value_div !== value_div) { + this.value_div = value_div; + this.value_div.title = this.label; + this.value_div.style.setProperty('color', this.color, 'important'); + if (!this.selected) { + this.value_div.className = 'netdata-legend-value not-selected'; + } else { + this.value_div.className = 'netdata-legend-value selected'; + } + } + + this.enabled = true; + this.setHandler(); +}; + +dimensionStatus.prototype.setHandler = function () { + if (!this.enabled) { + return; + } + + let ds = this; + + // this.name_div.onmousedown = this.value_div.onmousedown = function(e) { + this.name_div.onclick = this.value_div.onclick = function (e) { + e.preventDefault(); + if (ds.isSelected()) { + // this is selected + if (e.shiftKey || e.ctrlKey) { + // control or shift key is pressed -> unselect this (except is none will remain selected, in which case select all) + ds.unselect(); + + if (ds.parent.countSelected() === 0) { + ds.parent.selectAll(); + } + } else { + // no key is pressed -> select only this (except if it is the only selected already, in which case select all) + if (ds.parent.countSelected() === 1) { + ds.parent.selectAll(); + } else { + ds.parent.selectNone(); + ds.select(); + } + } + } + else { + // this is not selected + if (e.shiftKey || e.ctrlKey) { + // control or shift key is pressed -> select this too + ds.select(); + } else { + // no key is pressed -> select only this + ds.parent.selectNone(); + ds.select(); + } + } + + ds.parent.state.redrawChart(); + } +}; + +dimensionStatus.prototype.select = function () { + if (!this.enabled) { + return; + } + + this.name_div.className = 'netdata-legend-name selected'; + this.value_div.className = 'netdata-legend-value selected'; + this.selected = true; +}; + +dimensionStatus.prototype.unselect = function () { + if (!this.enabled) { + return; + } + + this.name_div.className = 'netdata-legend-name not-selected'; + this.value_div.className = 'netdata-legend-value hidden'; + this.selected = false; +}; + +dimensionStatus.prototype.isSelected = function () { + // return(this.enabled === true && this.selected === true); + return this.enabled && this.selected; +}; + +// ---------------------------------------------------------------------------------------------------------------- + +let dimensionsVisibility = function (state) { + this.state = state; + this.len = 0; + this.dimensions = {}; + this.selected_count = 0; + this.unselected_count = 0; +}; + +dimensionsVisibility.prototype.dimensionAdd = function (label, name_div, value_div, color) { + if (typeof this.dimensions[label] === 'undefined') { + this.len++; + this.dimensions[label] = new dimensionStatus(this, label, name_div, value_div, color); + } else { + this.dimensions[label].setOptions(name_div, value_div, color); + } + + return this.dimensions[label]; +}; + +dimensionsVisibility.prototype.dimensionGet = function (label) { + return this.dimensions[label]; +}; + +dimensionsVisibility.prototype.invalidateAll = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].invalidate(); + } +}; + +dimensionsVisibility.prototype.selectAll = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].select(); + } +}; + +dimensionsVisibility.prototype.countSelected = function () { + let selected = 0; + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + if (this.dimensions[keys[len]].isSelected()) { + selected++; + } + } + + return selected; +}; + +dimensionsVisibility.prototype.selectNone = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].unselect(); + } +}; + +dimensionsVisibility.prototype.selected2BooleanArray = function (array) { + let ret = []; + this.selected_count = 0; + this.unselected_count = 0; + + let len = array.length; + while (len--) { + let ds = this.dimensions[array[len]]; + if (typeof ds === 'undefined') { + // console.log(array[i] + ' is not found'); + ret.unshift(false); + } else if (ds.isSelected()) { + ret.unshift(true); + this.selected_count++; + } else { + ret.unshift(false); + this.unselected_count++; + } + } + + if (this.selected_count === 0 && this.unselected_count !== 0) { + this.selectAll(); + return this.selected2BooleanArray(array); + } + + return ret; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// date/time conversion + +NETDATA.dateTime = { + using_timezone: false, + + // these are the old netdata functions + // we fallback to these, if the new ones fail + + localeDateStringNative: function (d) { + return d.toLocaleDateString(); + }, + + localeTimeStringNative: function (d) { + return d.toLocaleTimeString(); + }, + + xAxisTimeStringNative: function (d) { + return NETDATA.zeropad(d.getHours()) + ":" + + NETDATA.zeropad(d.getMinutes()) + ":" + + NETDATA.zeropad(d.getSeconds()); + }, + + // initialize the new date/time conversion + // functions. + // if this fails, we fallback to the above + init: function (timezone) { + //console.log('init with timezone: ' + timezone); + + // detect browser timezone + try { + NETDATA.options.browser_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch (e) { + console.log('failed to detect browser timezone: ' + e.toString()); + NETDATA.options.browser_timezone = 'cannot-detect-it'; + } + + let ret = false; + + try { + let dateOptions = { + localeMatcher: 'best fit', + formatMatcher: 'best fit', + weekday: 'short', + year: 'numeric', + month: 'short', + day: '2-digit' + }; + + let timeOptions = { + localeMatcher: 'best fit', + hour12: false, + formatMatcher: 'best fit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + + let xAxisOptions = { + localeMatcher: 'best fit', + hour12: false, + formatMatcher: 'best fit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + + if (typeof timezone === 'string' && timezone !== '' && timezone !== 'default') { + dateOptions.timeZone = timezone; + timeOptions.timeZone = timezone; + timeOptions.timeZoneName = 'short'; + xAxisOptions.timeZone = timezone; + this.using_timezone = true; + } else { + timezone = 'default'; + this.using_timezone = false; + } + + this.dateFormat = new Intl.DateTimeFormat(navigator.language, dateOptions); + this.timeFormat = new Intl.DateTimeFormat(navigator.language, timeOptions); + this.xAxisFormat = new Intl.DateTimeFormat(navigator.language, xAxisOptions); + + this.localeDateString = function (d) { + return this.dateFormat.format(d); + }; + + this.localeTimeString = function (d) { + return this.timeFormat.format(d); + }; + + this.xAxisTimeString = function (d) { + return this.xAxisFormat.format(d); + }; + + //let d = new Date(); + //let t = this.dateFormat.format(d) + ' ' + this.timeFormat.format(d) + ' ' + this.xAxisFormat.format(d); + + ret = true; + } catch (e) { + console.log('Cannot setup Date/Time formatting: ' + e.toString()); + + timezone = 'default'; + this.localeDateString = this.localeDateStringNative; + this.localeTimeString = this.localeTimeStringNative; + this.xAxisTimeString = this.xAxisTimeStringNative; + this.using_timezone = false; + + ret = false; + } + + // save it + //console.log('init setOption timezone: ' + timezone); + NETDATA.setOption('timezone', timezone); + + return ret; + } +}; +NETDATA.dateTime.init(NETDATA.options.current.timezone); + +// ---------------------------------------------------------------------------------------------------------------- +// global selection sync + +NETDATA.globalSelectionSync = { + state: null, + dontSyncBefore: 0, + last_t: 0, + slaves: [], + timeoutId: undefined, + + globalReset: function () { + this.stop(); + this.state = null; + this.dontSyncBefore = 0; + this.last_t = 0; + this.slaves = []; + this.timeoutId = undefined; + }, + + active: function () { + return (this.state !== null); + }, + + // return true if global selection sync can be enabled now + enabled: function () { + // console.log('enabled()'); + // can we globally apply selection sync? + if (!NETDATA.options.current.sync_selection) { + return false; + } + + return (this.dontSyncBefore <= Date.now()); + }, + + // set the global selection sync master + setMaster: function (state) { + if (!this.enabled()) { + this.stop(); + return; + } + + if (this.state === state) { + return; + } + + if (this.state !== null) { + this.stop(); + } + + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.setMaster(' + state.id + ')'); + } + + state.selected = true; + this.state = state; + this.last_t = 0; + + // find all slaves + let targets = NETDATA.intersectionObserver.targets(); + this.slaves = []; + let len = targets.length; + while (len--) { + let st = targets[len]; + if (this.state !== st && st.globalSelectionSyncIsEligible()) { + this.slaves.push(st); + } + } + + // this.delay(100); + }, + + // stop global selection sync + stop: function () { + if (this.state !== null) { + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.stop()'); + } + + let len = this.slaves.length; + while (len--) { + this.slaves[len].clearSelection(); + } + + this.state.clearSelection(); + + this.last_t = 0; + this.slaves = []; + this.state = null; + } + }, + + // delay global selection sync for some time + delay: function (ms) { + if (NETDATA.options.current.sync_selection) { + // if (NETDATA.options.debug.globalSelectionSync === true) { + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.delay()'); + } + + if (typeof ms === 'number') { + this.dontSyncBefore = Date.now() + ms; + } else { + this.dontSyncBefore = Date.now() + NETDATA.options.current.sync_selection_delay; + } + } + }, + + __syncSlaves: function () { + // if (NETDATA.globalSelectionSync.enabled() === true) { + if (NETDATA.globalSelectionSync.enabled()) { + // if (NETDATA.options.debug.globalSelectionSync === true) + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.__syncSlaves()'); + } + + let t = NETDATA.globalSelectionSync.last_t; + let len = NETDATA.globalSelectionSync.slaves.length; + while (len--) { + NETDATA.globalSelectionSync.slaves[len].setSelection(t); + } + + this.timeoutId = undefined; + } + }, + + // sync all the visible charts to the given time + // this is to be called from the chart libraries + sync: function (state, t) { + // if (NETDATA.options.current.sync_selection === true) { + if (NETDATA.options.current.sync_selection) { + // if (NETDATA.options.debug.globalSelectionSync === true) + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.sync(' + state.id + ', ' + t.toString() + ')'); + } + + this.setMaster(state); + + if (t === this.last_t) { + return; + } + + this.last_t = t; + + if (state.foreignElementSelection !== null) { + state.foreignElementSelection.innerText = NETDATA.dateTime.localeDateString(t) + ' ' + NETDATA.dateTime.localeTimeString(t); + } + + if (this.timeoutId) { + NETDATA.timeout.clear(this.timeoutId); + } + + this.timeoutId = NETDATA.timeout.set(this.__syncSlaves, 0); + } + } +}; + +NETDATA.intersectionObserver = { + observer: null, + visible_targets: [], + + options: { + root: null, + rootMargin: "0px", + threshold: null + }, + + enabled: function () { + return this.observer !== null; + }, + + globalReset: function () { + if (this.observer !== null) { + this.visible_targets = []; + this.observer.disconnect(); + this.init(); + } + }, + + targets: function () { + if (this.enabled() && this.visible_targets.length > 0) { + return this.visible_targets; + } else { + return NETDATA.options.targets; + } + }, + + switchChartVisibility: function () { + let old = this.__visibilityRatioOld; + + if (old !== this.__visibilityRatio) { + if (old === 0 && this.__visibilityRatio > 0) { + this.unhideChart(); + } else if (old > 0 && this.__visibilityRatio === 0) { + this.hideChart(); + } + + this.__visibilityRatioOld = this.__visibilityRatio; + } + }, + + handler: function (entries, observer) { + entries.forEach(function (entry) { + let state = NETDATA.chartState(entry.target); + + let idx; + if (entry.intersectionRatio > 0) { + idx = NETDATA.intersectionObserver.visible_targets.indexOf(state); + if (idx === -1) { + if (NETDATA.scrollUp) { + NETDATA.intersectionObserver.visible_targets.push(state); + } else { + NETDATA.intersectionObserver.visible_targets.unshift(state); + } + } + else if (state.__visibilityRatio === 0) { + state.log("was not visible until now, but was already in visible_targets"); + } + } else { + idx = NETDATA.intersectionObserver.visible_targets.indexOf(state); + if (idx !== -1) { + NETDATA.intersectionObserver.visible_targets.splice(idx, 1); + } else if (state.__visibilityRatio > 0) { + state.log("was visible, but not found in visible_targets"); + } + } + + state.__visibilityRatio = entry.intersectionRatio; + + if (!NETDATA.options.current.async_on_scroll) { + if (window.requestIdleCallback) { + window.requestIdleCallback(function () { + NETDATA.intersectionObserver.switchChartVisibility.call(state); + }, {timeout: 100}); + } else { + NETDATA.intersectionObserver.switchChartVisibility.call(state); + } + } + }); + }, + + observe: function (state) { + if (this.enabled()) { + state.__visibilityRatioOld = 0; + state.__visibilityRatio = 0; + this.observer.observe(state.element); + + state.isVisible = function () { + if (!NETDATA.options.current.update_only_visible) { + return true; + } + + NETDATA.intersectionObserver.switchChartVisibility.call(this); + + return this.__visibilityRatio > 0; + } + } + }, + + init: function () { + if (typeof netdataIntersectionObserver === 'undefined' || netdataIntersectionObserver) { + try { + this.observer = new IntersectionObserver(this.handler, this.options); + } catch (e) { + console.log("IntersectionObserver is not supported on this browser"); + this.observer = null; + } + } + //else { + // console.log("IntersectionObserver is disabled"); + //} + } +}; +NETDATA.intersectionObserver.init(); + +// ---------------------------------------------------------------------------------------------------------------- +// Our state object, where all per-chart values are stored + +let chartState = function (element) { + this.element = element; + + // IMPORTANT: + // all private functions should use 'that', instead of 'this' + // Alternatively, you can use arrow functions (related issue #4514) + let that = this; + + // ============================================================================================================ + // ERROR HANDLING + + /* error() - private + * show an error instead of the chart + */ + let error = (msg) => { + let ret = true; + + if (typeof netdataErrorCallback === 'function') { + ret = netdataErrorCallback('chart', this.id, msg); + } + + if (ret) { + this.element.innerHTML = this.id + ': ' + msg; + this.enabled = false; + this.current = this.pan; + } + }; + + // console logging + this.log = function (msg) { + console.log(this.id + ' (' + this.library_name + ' ' + this.uuid + '): ' + msg); + }; + + this.debugLog = function (msg) { + if (this.debug) { + this.log(msg); + } + }; + + // ============================================================================================================ + // EARLY INITIALIZATION + + // These are variables that should exist even if the chart is never to be rendered. + // Be careful what you add here - there may be thousands of charts on the page. + + // GUID - a unique identifier for the chart + this.uuid = NETDATA.guid(); + + // string - the name of chart + this.id = NETDATA.dataAttribute(this.element, 'netdata', undefined); + if (typeof this.id === 'undefined') { + error("netdata elements need data-netdata"); + return; + } + + // string - the key for localStorage settings + this.settings_id = NETDATA.dataAttribute(this.element, 'id', null); + + // the user given dimensions of the element + this.width = NETDATA.dataAttribute(this.element, 'width', NETDATA.chartDefaults.width); + this.height = NETDATA.dataAttribute(this.element, 'height', NETDATA.chartDefaults.height); + this.height_original = this.height; + + if (this.settings_id !== null) { + this.height = NETDATA.localStorageGet('chart_heights.' + this.settings_id, this.height, function (height) { + // this is the callback that will be called + // if and when the user resets all localStorage variables + // to their defaults + + resizeChartToHeight(height); + }); + } + + // the chart library requested by the user + this.library_name = NETDATA.dataAttribute(this.element, 'chart-library', NETDATA.chartDefaults.library); + + // check the requested library is available + // we don't initialize it here - it will be initialized when + // this chart will be first used + if (typeof NETDATA.chartLibraries[this.library_name] === 'undefined') { + NETDATA.error(402, this.library_name); + error('chart library "' + this.library_name + '" is not found'); + this.enabled = false; + } else if (!NETDATA.chartLibraries[this.library_name].enabled) { + NETDATA.error(403, this.library_name); + error('chart library "' + this.library_name + '" is not enabled'); + this.enabled = false; + } else { + this.library = NETDATA.chartLibraries[this.library_name]; + } + + this.auto = { + name: 'auto', + autorefresh: true, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + this.pan = { + name: 'pan', + autorefresh: false, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + this.zoom = { + name: 'zoom', + autorefresh: false, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + + // this is a pointer to one of the sub-classes below + // auto, pan, zoom + this.current = this.auto; + + this.running = false; // boolean - true when the chart is being refreshed now + this.enabled = true; // boolean - is the chart enabled for refresh? + + this.force_update_every = null; // number - overwrite the visualization update frequency of the chart + + this.tmp = {}; + + this.foreignElementBefore = null; + this.foreignElementAfter = null; + this.foreignElementDuration = null; + this.foreignElementUpdateEvery = null; + this.foreignElementSelection = null; + + // ============================================================================================================ + // PRIVATE FUNCTIONS + + // reset the runtime status variables to their defaults + const runtimeInit = () => { + this.paused = false; // boolean - is the chart paused for any reason? + this.selected = false; // boolean - is the chart shown a selection? + + this.chart_created = false; // boolean - is the library.create() been called? + this.dom_created = false; // boolean - is the chart DOM been created? + this.fetching_data = false; // boolean - true while we fetch data via ajax + + this.updates_counter = 0; // numeric - the number of refreshes made so far + this.updates_since_last_unhide = 0; // numeric - the number of refreshes made since the last time the chart was unhidden + this.updates_since_last_creation = 0; // numeric - the number of refreshes made since the last time the chart was created + + this.tm = { + last_initialized: 0, // milliseconds - the timestamp it was last initialized + last_dom_created: 0, // milliseconds - the timestamp its DOM was last created + last_mode_switch: 0, // milliseconds - the timestamp it switched modes + + last_info_downloaded: 0, // milliseconds - the timestamp we downloaded the chart + last_updated: 0, // the timestamp the chart last updated with data + pan_and_zoom_seq: 0, // the sequence number of the global synchronization + // between chart. + // Used with NETDATA.globalPanAndZoom.seq + last_visible_check: 0, // the time we last checked if it is visible + last_resized: 0, // the time the chart was resized + last_hidden: 0, // the time the chart was hidden + last_unhidden: 0, // the time the chart was unhidden + last_autorefreshed: 0 // the time the chart was last refreshed + }; + + this.data = null; // the last data as downloaded from the netdata server + this.data_url = 'invalid://'; // string - the last url used to update the chart + this.data_points = 0; // number - the number of points returned from netdata + this.data_after = 0; // milliseconds - the first timestamp of the data + this.data_before = 0; // milliseconds - the last timestamp of the data + this.data_update_every = 0; // milliseconds - the frequency to update the data + + this.tmp = {}; // members that can be destroyed to save memory + }; + + // initialize all the variables that are required for the chart to be rendered + const lateInitialization = () => { + if (typeof this.host !== 'undefined') { + return; + } + + // string - the netdata server URL, without any path + this.host = NETDATA.dataAttribute(this.element, 'host', NETDATA.serverDefault); + + // make sure the host does not end with / + // all netdata API requests use absolute paths + while (this.host.slice(-1) === '/') { + this.host = this.host.substring(0, this.host.length - 1); + } + + // string - the grouping method requested by the user + this.method = NETDATA.dataAttribute(this.element, 'method', NETDATA.chartDefaults.method); + this.gtime = NETDATA.dataAttribute(this.element, 'gtime', 0); + + // the time-range requested by the user + this.after = NETDATA.dataAttribute(this.element, 'after', NETDATA.chartDefaults.after); + this.before = NETDATA.dataAttribute(this.element, 'before', NETDATA.chartDefaults.before); + + // the pixels per point requested by the user + this.pixels_per_point = NETDATA.dataAttribute(this.element, 'pixels-per-point', 1); + this.points = NETDATA.dataAttribute(this.element, 'points', null); + + // the forced update_every + this.force_update_every = NETDATA.dataAttribute(this.element, 'update-every', null); + if (typeof this.force_update_every !== 'number' || this.force_update_every <= 1) { + if (this.force_update_every !== null) { + this.log('ignoring invalid value of property data-update-every'); + } + + this.force_update_every = null; + } else { + this.force_update_every *= 1000; + } + + // the dimensions requested by the user + this.dimensions = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'dimensions', null)); + + this.title = NETDATA.dataAttribute(this.element, 'title', null); // the title of the chart + this.units = NETDATA.dataAttribute(this.element, 'units', null); // the units of the chart dimensions + this.units_desired = NETDATA.dataAttribute(this.element, 'desired-units', NETDATA.options.current.units); // the units of the chart dimensions + this.units_current = this.units; + this.units_common = NETDATA.dataAttribute(this.element, 'common-units', null); + + // additional options to pass to netdata + this.append_options = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'append-options', null)); + + // override options to pass to netdata + this.override_options = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'override-options', null)); + + this.debug = NETDATA.dataAttributeBoolean(this.element, 'debug', false); + + this.value_decimal_detail = -1; + let d = NETDATA.dataAttribute(this.element, 'decimal-digits', -1); + if (typeof d === 'number') { + this.value_decimal_detail = d; + } else if (typeof d !== 'undefined') { + this.log('ignoring decimal-digits value: ' + d.toString()); + } + + // if we need to report the rendering speed + // find the element that needs to be updated + let refresh_dt_element_name = NETDATA.dataAttribute(this.element, 'dt-element-name', null); // string - the element to print refresh_dt_ms + + if (refresh_dt_element_name !== null) { + this.refresh_dt_element = document.getElementById(refresh_dt_element_name) || null; + } + else { + this.refresh_dt_element = null; + } + + this.dimensions_visibility = new dimensionsVisibility(that); + + this.netdata_first = 0; // milliseconds - the first timestamp in netdata + this.netdata_last = 0; // milliseconds - the last timestamp in netdata + this.requested_after = null; // milliseconds - the timestamp of the request after param + this.requested_before = null; // milliseconds - the timestamp of the request before param + this.requested_padding = null; + this.view_after = 0; + this.view_before = 0; + + this.refresh_dt_ms = 0; // milliseconds - the time the last refresh took + + // how many retries we have made to load chart data from the server + this.retries_on_data_failures = 0; + + // color management + this.colors = null; + this.colors_assigned = null; + this.colors_available = null; + this.colors_custom = null; + + this.element_message = null; // the element already created by the user + this.element_chart = null; // the element with the chart + this.element_legend = null; // the element with the legend of the chart (if created by us) + this.element_legend_childs = { + content: null, + hidden: null, + title_date: null, + title_time: null, + title_units: null, + perfect_scroller: null, // the container to apply perfect scroller to + series: null + }; + + this.chart_url = null; // string - the url to download chart info + this.chart = null; // object - the chart as downloaded from the server + + const getForeignElementById = (opt) => { + let id = NETDATA.dataAttribute(this.element, opt, null); + if (id === null) { + //this.log('option "' + opt + '" is undefined'); + return null; + } + + let el = document.getElementById(id); + if (typeof el === 'undefined') { + this.log('cannot find an element with name "' + id.toString() + '"'); + return null; + } + + return el; + }; + + this.foreignElementBefore = getForeignElementById('show-before-at'); + this.foreignElementAfter = getForeignElementById('show-after-at'); + this.foreignElementDuration = getForeignElementById('show-duration-at'); + this.foreignElementUpdateEvery = getForeignElementById('show-update-every-at'); + this.foreignElementSelection = getForeignElementById('show-selection-at'); + }; + + const destroyDOM = () => { + if (!this.enabled) { + return; + } + + if (this.debug) { + this.log('destroyDOM()'); + } + + // this.element.className = 'netdata-message icon'; + // this.element.innerHTML = '<i class="fas fa-sync"></i> netdata'; + this.element.innerHTML = ''; + this.element_message = null; + this.element_legend = null; + this.element_chart = null; + this.element_legend_childs.series = null; + + this.chart_created = false; + this.dom_created = false; + + this.tm.last_resized = 0; + this.tm.last_dom_created = 0; + }; + + let createDOM = () => { + if (!this.enabled) { + return; + } + lateInitialization(); + + destroyDOM(); + + if (this.debug) { + this.log('createDOM()'); + } + + this.element_message = document.createElement('div'); + this.element_message.className = 'netdata-message icon hidden'; + this.element.appendChild(this.element_message); + + this.dom_created = true; + this.chart_created = false; + + this.tm.last_dom_created = this.tm.last_resized = Date.now(); + + showLoading(); + }; + + const initDOM = () => { + this.element.className = this.library.container_class(that); + + if (typeof(this.width) === 'string') { + this.element.style.width = this.width; + } else if (typeof(this.width) === 'number') { + this.element.style.width = this.width.toString() + 'px'; + } + + if (typeof(this.library.aspect_ratio) === 'undefined') { + if (typeof(this.height) === 'string') { + this.element.style.height = this.height; + } else if (typeof(this.height) === 'number') { + this.element.style.height = this.height.toString() + 'px'; + } + } + + if (NETDATA.chartDefaults.min_width !== null) { + this.element.style.min_width = NETDATA.chartDefaults.min_width; + } + }; + + const invisibleSearchableText = () => { + return '<span style="position:absolute; opacity: 0; width: 0px;">' + this.id + '</span>'; + }; + + /* init() private + * initialize state variables + * destroy all (possibly) created state elements + * create the basic DOM for a chart + */ + const init = (opt) => { + if (!this.enabled) { + return; + } + + runtimeInit(); + this.element.innerHTML = invisibleSearchableText(); + + this.tm.last_initialized = Date.now(); + this.setMode('auto'); + + if (opt !== 'fast') { + if (this.isVisible(true) || opt === 'force') { + createDOM(); + } + } + }; + + const maxMessageFontSize = () => { + let screenHeight = screen.height; + let el = this.element; + + // normally we want a font size, as tall as the element + let h = el.clientHeight; + + // but give it some air, 20% let's say, or 5 pixels min + let lost = Math.max(h * 0.2, 5); + h -= lost; + + // center the text, vertically + let paddingTop = (lost - 5) / 2; + + // but check the width too + // it should fit 10 characters in it + let w = el.clientWidth / 10; + if (h > w) { + paddingTop += (h - w) / 2; + h = w; + } + + // and don't make it too huge + // 5% of the screen size is good + if (h > screenHeight / 20) { + paddingTop += (h - (screenHeight / 20)) / 2; + h = screenHeight / 20; + } + + // set it + this.element_message.style.fontSize = h.toString() + 'px'; + this.element_message.style.paddingTop = paddingTop.toString() + 'px'; + }; + + const showMessageIcon = (icon) => { + this.element_message.innerHTML = icon; + maxMessageFontSize(); + $(this.element_message).removeClass('hidden'); + this.tmp.___messageHidden___ = undefined; + }; + + const hideMessage = () => { + if (typeof this.tmp.___messageHidden___ === 'undefined') { + this.tmp.___messageHidden___ = true; + $(this.element_message).addClass('hidden'); + } + }; + + const showRendering = () => { + let icon; + if (this.chart !== null) { + if (this.chart.chart_type === 'line') { + icon = NETDATA.icons.lineChart; + } else { + icon = NETDATA.icons.areaChart; + } + } + else { + icon = NETDATA.icons.noChart; + } + + showMessageIcon(icon + ' netdata' + invisibleSearchableText()); + }; + + const showLoading = () => { + if (!this.chart_created) { + showMessageIcon(NETDATA.icons.loading + ' netdata'); + return true; + } + return false; + }; + + const isHidden = () => { + return (typeof this.tmp.___chartIsHidden___ !== 'undefined'); + }; + + // hide the chart, when it is not visible - called from isVisible() + this.hideChart = function () { + // hide it, if it is not already hidden + if (isHidden()) { + return; + } + + if (this.chart_created) { + if (NETDATA.options.current.show_help) { + if (this.element_legend_childs.toolbox !== null) { + if (this.debug) { + this.log('hideChart(): hidding legend popovers'); + } + + $(this.element_legend_childs.toolbox_left).popover('hide'); + $(this.element_legend_childs.toolbox_reset).popover('hide'); + $(this.element_legend_childs.toolbox_right).popover('hide'); + $(this.element_legend_childs.toolbox_zoomin).popover('hide'); + $(this.element_legend_childs.toolbox_zoomout).popover('hide'); + } + + if (this.element_legend_childs.resize_handler !== null) { + $(this.element_legend_childs.resize_handler).popover('hide'); + } + + if (this.element_legend_childs.content !== null) { + $(this.element_legend_childs.content).popover('hide'); + } + } + + if (NETDATA.options.current.destroy_on_hide) { + if (this.debug) { + this.log('hideChart(): initializing chart'); + } + + // we should destroy it + init('force'); + } else { + if (this.debug) { + this.log('hideChart(): hiding chart'); + } + + showRendering(); + this.element_chart.style.display = 'none'; + this.element.style.willChange = 'auto'; + if (this.element_legend !== null) { + this.element_legend.style.display = 'none'; + } + if (this.element_legend_childs.toolbox !== null) { + this.element_legend_childs.toolbox.style.display = 'none'; + } + if (this.element_legend_childs.resize_handler !== null) { + this.element_legend_childs.resize_handler.style.display = 'none'; + } + + this.tm.last_hidden = Date.now(); + + // de-allocate data + // This works, but I not sure there are no corner cases somewhere + // so it is commented - if the user has memory issues he can + // set Destroy on Hide for all charts + // this.data = null; + } + } + + this.tmp.___chartIsHidden___ = true; + }; + + // unhide the chart, when it is visible - called from isVisible() + this.unhideChart = function () { + if (!isHidden()) { + return; + } + + this.tmp.___chartIsHidden___ = undefined; + this.updates_since_last_unhide = 0; + + if (!this.chart_created) { + if (this.debug) { + this.log('unhideChart(): initializing chart'); + } + + // we need to re-initialize it, to show our background + // logo in bootstrap tabs, until the chart loads + init('force'); + } else { + if (this.debug) { + this.log('unhideChart(): unhiding chart'); + } + + this.element.style.willChange = 'transform'; + this.tm.last_unhidden = Date.now(); + this.element_chart.style.display = ''; + if (this.element_legend !== null) { + this.element_legend.style.display = ''; + } + if (this.element_legend_childs.toolbox !== null) { + this.element_legend_childs.toolbox.style.display = ''; + } + if (this.element_legend_childs.resize_handler !== null) { + this.element_legend_childs.resize_handler.style.display = ''; + } + resizeChart(); + hideMessage(); + } + + if (this.__redraw_on_unhide) { + if (this.debug) { + this.log("redrawing chart on unhide"); + } + + this.__redraw_on_unhide = undefined; + this.redrawChart(); + } + }; + + const canBeRendered = (uncached_visibility) => { + if (this.debug) { + this.log('canBeRendered() called'); + } + + if (!NETDATA.options.current.update_only_visible) { + return true; + } + + let ret = ( + ( + NETDATA.options.page_is_visible || + NETDATA.options.current.stop_updates_when_focus_is_lost === false || + this.updates_since_last_unhide === 0 + ) + && isHidden() === false && this.isVisible(uncached_visibility) + ); + + if (this.debug) { + this.log('canBeRendered(): ' + ret); + } + + return ret; + }; + + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers + const callChartLibraryUpdateSafely = (data) => { + let status; + + // we should not do this here + // if we prevent rendering the chart then: + // 1. globalSelectionSync will be wrong + // 2. globalPanAndZoom will be wrong + //if (canBeRendered(true) === false) + // return false; + + if (NETDATA.options.fake_chart_rendering) { + return true; + } + + this.updates_counter++; + this.updates_since_last_unhide++; + this.updates_since_last_creation++; + + if (NETDATA.options.debug.chart_errors) { + status = this.library.update(that, data); + } else { + try { + status = this.library.update(that, data); + } catch (err) { + status = false; + } + } + + if (!status) { + error('chart failed to be updated as ' + this.library_name); + return false; + } + + return true; + }; + + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers + const callChartLibraryCreateSafely = (data) => { + let status; + + // we should not do this here + // if we prevent rendering the chart then: + // 1. globalSelectionSync will be wrong + // 2. globalPanAndZoom will be wrong + //if (canBeRendered(true) === false) + // return false; + + if (NETDATA.options.fake_chart_rendering) { + return true; + } + + this.updates_counter++; + this.updates_since_last_unhide++; + this.updates_since_last_creation++; + + if (NETDATA.options.debug.chart_errors) { + status = this.library.create(that, data); + } else { + try { + status = this.library.create(that, data); + } catch (err) { + status = false; + } + } + + if (!status) { + error('chart failed to be created as ' + this.library_name); + return false; + } + + this.chart_created = true; + this.updates_since_last_creation = 0; + return true; + }; + + // ---------------------------------------------------------------------------------------------------------------- + // Chart Resize + + // resizeChart() - private + // to be called just before the chart library to make sure that + // a properly sized dom is available + const resizeChart = () => { + if (this.tm.last_resized < NETDATA.options.last_page_resize) { + if (!this.chart_created) { + return; + } + + if (this.needsRecreation()) { + if (this.debug) { + this.log('resizeChart(): initializing chart'); + } + + init('force'); + } else if (typeof this.library.resize === 'function') { + if (this.debug) { + this.log('resizeChart(): resizing chart'); + } + + this.library.resize(that); + + if (this.element_legend_childs.perfect_scroller !== null) { + Ps.update(this.element_legend_childs.perfect_scroller); + } + + maxMessageFontSize(); + } + + this.tm.last_resized = Date.now(); + } + }; + + // this is the actual chart resize algorithm + // it will: + // - resize the entire container + // - update the internal states + // - resize the chart as the div changes height + // - update the scrollbar of the legend + const resizeChartToHeight = (h) => { + // console.log(h); + this.element.style.height = h; + + if (this.settings_id !== null) { + NETDATA.localStorageSet('chart_heights.' + this.settings_id, h); + } + + let now = Date.now(); + NETDATA.options.last_page_scroll = now; + NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.stop_updates_while_resizing; + + // force a resize + this.tm.last_resized = 0; + resizeChart(); + }; + + this.resizeForPrint = function () { + if (typeof this.element_legend_childs !== 'undefined' && this.element_legend_childs.perfect_scroller !== null) { + let current = this.element.clientHeight; + let optimal = current + + this.element_legend_childs.perfect_scroller.scrollHeight + - this.element_legend_childs.perfect_scroller.clientHeight; + + if (optimal > current) { + // this.log('resized'); + this.element.style.height = optimal + 'px'; + this.library.resize(this); + } + } + }; + + this.resizeHandler = function (e) { + e.preventDefault(); + + if (typeof this.event_resize === 'undefined' + || this.event_resize.chart_original_w === 'undefined' + || this.event_resize.chart_original_h === 'undefined') { + this.event_resize = { + chart_original_w: this.element.clientWidth, + chart_original_h: this.element.clientHeight, + last: 0 + }; + } + + if (e.type === 'touchstart') { + this.event_resize.mouse_start_x = e.touches.item(0).pageX; + this.event_resize.mouse_start_y = e.touches.item(0).pageY; + } else { + this.event_resize.mouse_start_x = e.clientX; + this.event_resize.mouse_start_y = e.clientY; + } + + this.event_resize.chart_start_w = this.element.clientWidth; + this.event_resize.chart_start_h = this.element.clientHeight; + this.event_resize.chart_last_w = this.element.clientWidth; + this.event_resize.chart_last_h = this.element.clientHeight; + + let now = Date.now(); + if (now - this.event_resize.last <= NETDATA.options.current.double_click_speed && this.element_legend_childs.perfect_scroller !== null) { + // double click / double tap event + + // console.dir(this.element_legend_childs.content); + // console.dir(this.element_legend_childs.perfect_scroller); + + // the optimal height of the chart + // showing the entire legend + let optimal = this.event_resize.chart_last_h + + this.element_legend_childs.perfect_scroller.scrollHeight + - this.element_legend_childs.perfect_scroller.clientHeight; + + // if we are not optimal, be optimal + if (this.event_resize.chart_last_h !== optimal) { + // this.log('resize to optimal, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(optimal.toString() + 'px'); + } + + // else if the current height is not the original/saved height + // reset to the original/saved height + else if (this.event_resize.chart_last_h !== this.event_resize.chart_original_h) { + // this.log('resize to original, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(this.event_resize.chart_original_h.toString() + 'px'); + } + + // else if the current height is not the internal default height + // reset to the internal default height + else if ((this.event_resize.chart_last_h.toString() + 'px') !== this.height_original) { + // this.log('resize to internal default, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(this.height_original.toString()); + } + + // else if the current height is not the firstchild's clientheight + // resize to it + else if (typeof this.element_legend_childs.perfect_scroller.firstChild !== 'undefined') { + let parent_rect = this.element.getBoundingClientRect(); + let content_rect = this.element_legend_childs.perfect_scroller.firstElementChild.getBoundingClientRect(); + let wanted = content_rect.top - parent_rect.top + this.element_legend_childs.perfect_scroller.firstChild.clientHeight + 18; // 15 = toolbox + 3 space + + // console.log(parent_rect); + // console.log(content_rect); + // console.log(wanted); + + // this.log('resize to firstChild, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString() + 'px, firstChild = ' + wanted.toString() + 'px' ); + if (this.event_resize.chart_last_h !== wanted) { + resizeChartToHeight(wanted.toString() + 'px'); + } + } + } else { + this.event_resize.last = now; + + // process movement event + document.onmousemove = + document.ontouchmove = + this.element_legend_childs.resize_handler.onmousemove = + this.element_legend_childs.resize_handler.ontouchmove = + function (e) { + let y = null; + + switch (e.type) { + case 'mousemove': + y = e.clientY; + break; + case 'touchmove': + y = e.touches.item(e.touches - 1).pageY; + break; + } + + if (y !== null) { + let newH = that.event_resize.chart_start_h + y - that.event_resize.mouse_start_y; + + if (newH >= 70 && newH !== that.event_resize.chart_last_h) { + resizeChartToHeight(newH.toString() + 'px'); + that.event_resize.chart_last_h = newH; + } + } + }; + + // process end event + document.onmouseup = + document.ontouchend = + this.element_legend_childs.resize_handler.onmouseup = + this.element_legend_childs.resize_handler.ontouchend = + function (e) { + void(e); + + // remove all the hooks + document.onmouseup = + document.onmousemove = + document.ontouchmove = + document.ontouchend = + that.element_legend_childs.resize_handler.onmousemove = + that.element_legend_childs.resize_handler.ontouchmove = + that.element_legend_childs.resize_handler.onmouseout = + that.element_legend_childs.resize_handler.onmouseup = + that.element_legend_childs.resize_handler.ontouchend = + null; + + // allow auto-refreshes + NETDATA.options.auto_refresher_stop_until = 0; + }; + } + }; + + const noDataToShow = () => { + showMessageIcon(NETDATA.icons.noData + ' empty'); + this.legendUpdateDOM(); + this.tm.last_autorefreshed = Date.now(); + // this.data_update_every = 30 * 1000; + //this.element_chart.style.display = 'none'; + //if (this.element_legend !== null) this.element_legend.style.display = 'none'; + //this.tmp.___chartIsHidden___ = true; + }; + + // ============================================================================================================ + // PUBLIC FUNCTIONS + + this.error = function (msg) { + error(msg); + }; + + this.setMode = function (m) { + if (this.current !== null && this.current.name === m) { + return; + } + + if (m === 'auto') { + this.current = this.auto; + } else if (m === 'pan') { + this.current = this.pan; + } else if (m === 'zoom') { + this.current = this.zoom; + } else { + this.current = this.auto; + } + + this.current.force_update_at = 0; + this.current.force_before_ms = null; + this.current.force_after_ms = null; + + this.tm.last_mode_switch = Date.now(); + }; + + // ---------------------------------------------------------------------------------------------------------------- + // global selection sync for slaves + + // can the chart participate to the global selection sync as a slave? + this.globalSelectionSyncIsEligible = function () { + return ( + this.enabled && + this.library !== null && + typeof this.library.setSelection === 'function' && + this.isVisible() && + this.chart_created + ); + }; + + this.setSelection = function (t) { + if (typeof this.library.setSelection === 'function') { + // this.selected = this.library.setSelection(this, t) === true; + this.selected = this.library.setSelection(this, t); + } else { + this.selected = true; + } + + if (this.selected && this.debug) { + this.log('selection set to ' + t.toString()); + } + + if (this.foreignElementSelection !== null) { + this.foreignElementSelection.innerText = NETDATA.dateTime.localeDateString(t) + ' ' + NETDATA.dateTime.localeTimeString(t); + } + + return this.selected; + }; + + this.clearSelection = function () { + if (this.selected) { + if (typeof this.library.clearSelection === 'function') { + this.selected = (this.library.clearSelection(this) !== true); + } else { + this.selected = false; + } + + if (this.selected === false && this.debug) { + this.log('selection cleared'); + } + + if (this.foreignElementSelection !== null) { + this.foreignElementSelection.innerText = ''; + } + + this.legendReset(); + } + + return this.selected; + }; + + // ---------------------------------------------------------------------------------------------------------------- + + // find if a timestamp (ms) is shown in the current chart + this.timeIsVisible = function (t) { + return (t >= this.data_after && t <= this.data_before); + }; + + this.calculateRowForTime = function (t) { + if (!this.timeIsVisible(t)) { + return -1; + } + return Math.floor((t - this.data_after) / this.data_update_every); + }; + + // ---------------------------------------------------------------------------------------------------------------- + + this.pauseChart = function () { + if (!this.paused) { + if (this.debug) { + this.log('pauseChart()'); + } + + this.paused = true; + } + }; + + this.unpauseChart = function () { + if (this.paused) { + if (this.debug) { + this.log('unpauseChart()'); + } + + this.paused = false; + } + }; + + this.resetChart = function (dontClearMaster, dontUpdate) { + if (this.debug) { + this.log('resetChart(' + dontClearMaster + ', ' + dontUpdate + ') called'); + } + + if (typeof dontClearMaster === 'undefined') { + dontClearMaster = false; + } + + if (typeof dontUpdate === 'undefined') { + dontUpdate = false; + } + + if (dontClearMaster !== true && NETDATA.globalPanAndZoom.isMaster(this)) { + if (this.debug) { + this.log('resetChart() diverting to clearMaster().'); + } + // this will call us back with master === true + NETDATA.globalPanAndZoom.clearMaster(); + return; + } + + this.clearSelection(); + + this.tm.pan_and_zoom_seq = 0; + + this.setMode('auto'); + this.current.force_update_at = 0; + this.current.force_before_ms = null; + this.current.force_after_ms = null; + this.tm.last_autorefreshed = 0; + this.paused = false; + this.selected = false; + this.enabled = true; + // this.debug = false; + + // do not update the chart here + // or the chart will flip-flop when it is the master + // of a selection sync and another chart becomes + // the new master + + if (dontUpdate !== true && this.isVisible()) { + this.updateChart(); + } + }; + + this.updateChartPanOrZoom = function (after, before, callback) { + let logme = 'updateChartPanOrZoom(' + after + ', ' + before + '): '; + let ret = true; + + NETDATA.globalPanAndZoom.delay(); + NETDATA.globalSelectionSync.delay(); + + if (this.debug) { + this.log(logme); + } + + if (before < after) { + if (this.debug) { + this.log(logme + 'flipped parameters, rejecting it.'); + } + return false; + } + + if (typeof this.fixed_min_duration === 'undefined') { + this.fixed_min_duration = Math.round((this.chartWidth() / 30) * this.chart.update_every * 1000); + } + + let min_duration = this.fixed_min_duration; + let current_duration = Math.round(this.view_before - this.view_after); + + // round the numbers + after = Math.round(after); + before = Math.round(before); + + // align them to update_every + // stretching them further away + after -= after % this.data_update_every; + before += this.data_update_every - (before % this.data_update_every); + + // the final wanted duration + let wanted_duration = before - after; + + // to allow panning, accept just a point below our minimum + if ((current_duration - this.data_update_every) < min_duration) { + min_duration = current_duration - this.data_update_every; + } + + // we do it, but we adjust to minimum size and return false + // when the wanted size is below the current and the minimum + // and we zoom + if (wanted_duration < current_duration && wanted_duration < min_duration) { + if (this.debug) { + this.log(logme + 'too small: min_duration: ' + (min_duration / 1000).toString() + ', wanted: ' + (wanted_duration / 1000).toString()); + } + + min_duration = this.fixed_min_duration; + + let dt = (min_duration - wanted_duration) / 2; + before += dt; + after -= dt; + wanted_duration = before - after; + ret = false; + } + + let tolerance = this.data_update_every * 2; + let movement = Math.abs(before - this.view_before); + + if (Math.abs(current_duration - wanted_duration) <= tolerance && movement <= tolerance && ret) { + if (this.debug) { + this.log(logme + 'REJECTING UPDATE: current/min duration: ' + (current_duration / 1000).toString() + '/' + (this.fixed_min_duration / 1000).toString() + ', wanted duration: ' + (wanted_duration / 1000).toString() + ', duration diff: ' + (Math.round(Math.abs(current_duration - wanted_duration) / 1000)).toString() + ', movement: ' + (movement / 1000).toString() + ', tolerance: ' + (tolerance / 1000).toString() + ', returning: ' + false); + } + return false; + } + + if (this.current.name === 'auto') { + this.log(logme + 'caller called me with mode: ' + this.current.name); + this.setMode('pan'); + } + + if (this.debug) { + this.log(logme + 'ACCEPTING UPDATE: current/min duration: ' + (current_duration / 1000).toString() + '/' + (this.fixed_min_duration / 1000).toString() + ', wanted duration: ' + (wanted_duration / 1000).toString() + ', duration diff: ' + (Math.round(Math.abs(current_duration - wanted_duration) / 1000)).toString() + ', movement: ' + (movement / 1000).toString() + ', tolerance: ' + (tolerance / 1000).toString() + ', returning: ' + ret); + } + + this.current.force_update_at = Date.now() + NETDATA.options.current.pan_and_zoom_delay; + this.current.force_after_ms = after; + this.current.force_before_ms = before; + NETDATA.globalPanAndZoom.setMaster(this, after, before); + + if (ret && typeof callback === 'function') { + callback(); + } + + return ret; + }; + + this.updateChartPanOrZoomAsyncTimeOutId = undefined; + this.updateChartPanOrZoomAsync = function (after, before, callback) { + NETDATA.globalPanAndZoom.delay(); + NETDATA.globalSelectionSync.delay(); + + if (!NETDATA.globalPanAndZoom.isMaster(this)) { + this.pauseChart(); + NETDATA.globalPanAndZoom.setMaster(this, after, before); + // NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.setMaster(this); + } + + if (this.updateChartPanOrZoomAsyncTimeOutId) { + NETDATA.timeout.clear(this.updateChartPanOrZoomAsyncTimeOutId); + } + + NETDATA.timeout.set(function () { + that.updateChartPanOrZoomAsyncTimeOutId = undefined; + that.updateChartPanOrZoom(after, before, callback); + }, 0); + }; + + let _unitsConversionLastUnits = undefined; + let _unitsConversionLastUnitsDesired = undefined; + let _unitsConversionLastMin = undefined; + let _unitsConversionLastMax = undefined; + let _unitsConversion = function (value) { + return value; + }; + this.unitsConversionSetup = function (min, max) { + if (this.units !== _unitsConversionLastUnits + || this.units_desired !== _unitsConversionLastUnitsDesired + || min !== _unitsConversionLastMin + || max !== _unitsConversionLastMax) { + + _unitsConversionLastUnits = this.units; + _unitsConversionLastUnitsDesired = this.units_desired; + _unitsConversionLastMin = min; + _unitsConversionLastMax = max; + + _unitsConversion = NETDATA.unitsConversion.get(this.uuid, min, max, this.units, this.units_desired, this.units_common, function (units) { + // console.log('switching units from ' + that.units.toString() + ' to ' + units.toString()); + that.units_current = units; + that.legendSetUnitsString(that.units_current); + }); + } + }; + + let _legendFormatValueChartDecimalsLastMin = undefined; + let _legendFormatValueChartDecimalsLastMax = undefined; + let _legendFormatValueChartDecimals = -1; + let _intlNumberFormat = null; + this.legendFormatValueDecimalsFromMinMax = function (min, max) { + if (min === _legendFormatValueChartDecimalsLastMin && max === _legendFormatValueChartDecimalsLastMax) { + return; + } + + this.unitsConversionSetup(min, max); + if (_unitsConversion !== null) { + min = _unitsConversion(min); + max = _unitsConversion(max); + + if (typeof min !== 'number' || typeof max !== 'number') { + return; + } + } + + _legendFormatValueChartDecimalsLastMin = min; + _legendFormatValueChartDecimalsLastMax = max; + + let old = _legendFormatValueChartDecimals; + + if (this.data !== null && this.data.min === this.data.max) + // it is a fixed number, let the visualizer decide based on the value + { + _legendFormatValueChartDecimals = -1; + } else if (this.value_decimal_detail !== -1) + // there is an override + { + _legendFormatValueChartDecimals = this.value_decimal_detail; + } else { + // ok, let's calculate the proper number of decimal points + let delta; + + if (min === max) { + delta = Math.abs(min); + } else { + delta = Math.abs(max - min); + } + + if (delta > 1000) { + _legendFormatValueChartDecimals = 0; + } else if (delta > 10) { + _legendFormatValueChartDecimals = 1; + } else if (delta > 1) { + _legendFormatValueChartDecimals = 2; + } else if (delta > 0.1) { + _legendFormatValueChartDecimals = 2; + } else if (delta > 0.01) { + _legendFormatValueChartDecimals = 4; + } else if (delta > 0.001) { + _legendFormatValueChartDecimals = 5; + } else if (delta > 0.0001) { + _legendFormatValueChartDecimals = 6; + } else { + _legendFormatValueChartDecimals = 7; + } + } + + if (_legendFormatValueChartDecimals !== old) { + if (_legendFormatValueChartDecimals < 0) { + _intlNumberFormat = null; + } else { + _intlNumberFormat = NETDATA.fastNumberFormat.get( + _legendFormatValueChartDecimals, + _legendFormatValueChartDecimals + ); + } + } + }; + + this.legendFormatValue = function (value) { + if (typeof value !== 'number') { + return '-'; + } + + value = _unitsConversion(value); + + if (typeof value !== 'number') { + return value; + } + + if (_intlNumberFormat !== null) { + return _intlNumberFormat.format(value); + } + + let dmin, dmax; + if (this.value_decimal_detail !== -1) { + dmin = dmax = this.value_decimal_detail; + } else { + dmin = 0; + let abs = (value < 0) ? -value : value; + if (abs > 1000) { + dmax = 0; + } else if (abs > 10) { + dmax = 1; + } else if (abs > 1) { + dmax = 2; + } else if (abs > 0.1) { + dmax = 2; + } else if (abs > 0.01) { + dmax = 4; + } else if (abs > 0.001) { + dmax = 5; + } else if (abs > 0.0001) { + dmax = 6; + } else { + dmax = 7; + } + } + + return NETDATA.fastNumberFormat.get(dmin, dmax).format(value); + }; + + this.legendSetLabelValue = function (label, value) { + let series = this.element_legend_childs.series[label]; + if (typeof series === 'undefined') { + return; + } + if (series.value === null && series.user === null) { + return; + } + + /* + // this slows down firefox and edge significantly + // since it requires to use innerHTML(), instead of innerText() + + // if the value has not changed, skip DOM update + //if (series.last === value) return; + + let s, r; + if (typeof value === 'number') { + let v = Math.abs(value); + s = r = this.legendFormatValue(value); + + if (typeof series.last === 'number') { + if (v > series.last) s += '<i class="fas fa-angle-up" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + else if (v < series.last) s += '<i class="fas fa-angle-down" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + else s += '<i class="fas fa-angle-left" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + } + else s += '<i class="fas fa-angle-right" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + + series.last = v; + } + else { + if (value === null) + s = r = ''; + else + s = r = value; + + series.last = value; + } + */ + + let s = this.legendFormatValue(value); + + // caching: do not update the update to show the same value again + if (s === series.last_shown_value) { + return; + } + series.last_shown_value = s; + + if (series.value !== null) { + series.value.innerText = s; + } + if (series.user !== null) { + series.user.innerText = s; + } + }; + + this.legendSetDateString = function (date) { + if (this.element_legend_childs.title_date !== null && date !== this.tmp.__last_shown_legend_date) { + this.element_legend_childs.title_date.innerText = date; + this.tmp.__last_shown_legend_date = date; + } + }; + + this.legendSetTimeString = function (time) { + if (this.element_legend_childs.title_time !== null && time !== this.tmp.__last_shown_legend_time) { + this.element_legend_childs.title_time.innerText = time; + this.tmp.__last_shown_legend_time = time; + } + }; + + this.legendSetUnitsString = function (units) { + if (this.element_legend_childs.title_units !== null && units !== this.tmp.__last_shown_legend_units) { + this.element_legend_childs.title_units.innerText = units; + this.tmp.__last_shown_legend_units = units; + } + }; + + this.legendSetDateLast = { + ms: 0, + date: undefined, + time: undefined + }; + + this.legendSetDate = function (ms) { + if (typeof ms !== 'number') { + this.legendShowUndefined(); + return; + } + + if (this.legendSetDateLast.ms !== ms) { + let d = new Date(ms); + this.legendSetDateLast.ms = ms; + this.legendSetDateLast.date = NETDATA.dateTime.localeDateString(d); + this.legendSetDateLast.time = NETDATA.dateTime.localeTimeString(d); + } + + this.legendSetDateString(this.legendSetDateLast.date); + this.legendSetTimeString(this.legendSetDateLast.time); + this.legendSetUnitsString(this.units_current) + }; + + this.legendShowUndefined = function () { + this.legendSetDateString(this.legendPluginModuleString(false)); + this.legendSetTimeString(this.chart.context.toString()); + // this.legendSetUnitsString(' '); + + if (this.data && this.element_legend_childs.series !== null) { + let labels = this.data.dimension_names; + let i = labels.length; + while (i--) { + let label = labels[i]; + + if (typeof label === 'undefined' || typeof this.element_legend_childs.series[label] === 'undefined') { + continue; + } + this.legendSetLabelValue(label, null); + } + } + }; + + this.legendShowLatestValues = function () { + if (this.chart === null) { + return; + } + if (this.selected) { + return; + } + + if (this.data === null || this.element_legend_childs.series === null) { + this.legendShowUndefined(); + return; + } + + let show_undefined = true; + if (Math.abs(this.netdata_last - this.view_before) <= this.data_update_every) { + show_undefined = false; + } + + if (show_undefined) { + this.legendShowUndefined(); + return; + } + + this.legendSetDate(this.view_before); + + let labels = this.data.dimension_names; + let i = labels.length; + while (i--) { + let label = labels[i]; + + if (typeof label === 'undefined') { + continue; + } + if (typeof this.element_legend_childs.series[label] === 'undefined') { + continue; + } + + this.legendSetLabelValue(label, this.data.view_latest_values[i]); + } + }; + + this.legendReset = function () { + this.legendShowLatestValues(); + }; + + // this should be called just ONCE per dimension per chart + this.__chartDimensionColor = function (label) { + let c = NETDATA.commonColors.get(this, label); + + // it is important to maintain a list of colors + // for this chart only, since the chart library + // uses this to assign colors to dimensions in the same + // order the dimension are given to it + this.colors.push(c); + + return c; + }; + + this.chartPrepareColorPalette = function () { + NETDATA.commonColors.refill(this); + }; + + // get the ordered list of chart colors + // this includes user defined colors + this.chartCustomColors = function () { + this.chartPrepareColorPalette(); + + let colors; + if (this.colors_custom.length) { + colors = this.colors_custom; + } else { + colors = this.colors; + } + + if (this.debug) { + this.log("chartCustomColors() returns:"); + this.log(colors); + } + + return colors; + }; + + // get the ordered list of chart ASSIGNED colors + // (this returns only the colors that have been + // assigned to dimensions, prepended with any + // custom colors defined) + this.chartColors = function () { + this.chartPrepareColorPalette(); + + if (this.debug) { + this.log("chartColors() returns:"); + this.log(this.colors); + } + + return this.colors; + }; + + this.legendPluginModuleString = function (withContext) { + let str = ' '; + let context = ''; + + if (typeof this.chart !== 'undefined') { + if (withContext && typeof this.chart.context === 'string') { + context = this.chart.context; + } + + if (typeof this.chart.plugin === 'string' && this.chart.plugin !== '') { + str = this.chart.plugin; + + if (str.endsWith(".plugin")) { + str = str.substring(0, str.length - 7); + } + + if (typeof this.chart.module === 'string' && this.chart.module !== '') { + str += ':' + this.chart.module; + } + + if (withContext && context !== '') { + str += ', ' + context; + } + } + else if (withContext && context !== '') { + str = context; + } + } + + return str; + }; + + this.legendResolutionTooltip = function () { + if (!this.chart) { + return ''; + } + + let collected = this.chart.update_every; + let viewed = (this.data) ? this.data.view_update_every : collected; + + if (collected === viewed) { + return "resolution " + NETDATA.seconds4human(collected); + } + + return "resolution " + NETDATA.seconds4human(viewed) + ", collected every " + NETDATA.seconds4human(collected); + }; + + this.legendUpdateDOM = function () { + let needed = false, dim, keys, len; + + // check that the legend DOM is up to date for the downloaded dimensions + if (typeof this.element_legend_childs.series !== 'object' || this.element_legend_childs.series === null) { + // this.log('the legend does not have any series - requesting legend update'); + needed = true; + } else if (this.data === null) { + // this.log('the chart does not have any data - requesting legend update'); + needed = true; + } else if (typeof this.element_legend_childs.series.labels_key === 'undefined') { + needed = true; + } else { + let labels = this.data.dimension_names.toString(); + if (labels !== this.element_legend_childs.series.labels_key) { + needed = true; + + if (this.debug) { + this.log('NEW LABELS: "' + labels + '" NOT EQUAL OLD LABELS: "' + this.element_legend_childs.series.labels_key + '"'); + } + } + } + + if (!needed) { + // make sure colors available + this.chartPrepareColorPalette(); + + // do we have to update the current values? + // we do this, only when the visible chart is current + if (Math.abs(this.netdata_last - this.view_before) <= this.data_update_every) { + if (this.debug) { + this.log('chart is in latest position... updating values on legend...'); + } + + //let labels = this.data.dimension_names; + //let i = labels.length; + //while (i--) + // this.legendSetLabelValue(labels[i], this.data.view_latest_values[i]); + } + return; + } + + if (this.colors === null) { + // this is the first time we update the chart + // let's assign colors to all dimensions + if (this.library.track_colors()) { + this.colors = []; + keys = Object.keys(this.chart.dimensions); + len = keys.length; + for (let i = 0; i < len; i++) { + NETDATA.commonColors.get(this, this.chart.dimensions[keys[i]].name); + } + } + } + + // we will re-generate the colors for the chart + // based on the dimensions this result has data for + this.colors = []; + + if (this.debug) { + this.log('updating Legend DOM'); + } + + // mark all dimensions as invalid + this.dimensions_visibility.invalidateAll(); + + const genLabel = function (state, parent, dim, name, count) { + let color = state.__chartDimensionColor(name); + + let user_element = null; + let user_id = NETDATA.dataAttribute(state.element, 'show-value-of-' + name.toLowerCase() + '-at', null); + if (user_id === null) { + user_id = NETDATA.dataAttribute(state.element, 'show-value-of-' + dim.toLowerCase() + '-at', null); + } + if (user_id !== null) { + user_element = document.getElementById(user_id) || null; + if (user_element === null) { + state.log('Cannot find element with id: ' + user_id); + } + } + + state.element_legend_childs.series[name] = { + name: document.createElement('span'), + value: document.createElement('span'), + user: user_element, + last: null, + last_shown_value: null + }; + + let label = state.element_legend_childs.series[name]; + + // create the dimension visibility tracking for this label + state.dimensions_visibility.dimensionAdd(name, label.name, label.value, color); + + let rgb = NETDATA.colorHex2Rgb(color); + label.name.innerHTML = '<table class="netdata-legend-name-table-' + + state.chart.chart_type + + '" style="background-color: ' + + 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + NETDATA.options.current['color_fill_opacity_' + state.chart.chart_type] + ') !important' + + '"><tr class="netdata-legend-name-tr"><td class="netdata-legend-name-td"></td></tr></table>'; + + let text = document.createTextNode(' ' + name); + label.name.appendChild(text); + + if (count > 0) { + parent.appendChild(document.createElement('br')); + } + + parent.appendChild(label.name); + parent.appendChild(label.value); + }; + + let content = document.createElement('div'); + + if (this.element_chart === null) { + this.element_chart = document.createElement('div'); + this.element_chart.id = this.library_name + '-' + this.uuid + '-chart'; + this.element.appendChild(this.element_chart); + + if (this.hasLegend()) { + this.element_chart.className = 'netdata-chart-with-legend-right netdata-' + this.library_name + '-chart-with-legend-right'; + } else { + this.element_chart.className = ' netdata-chart netdata-' + this.library_name + '-chart'; + } + } + + if (this.hasLegend()) { + if (this.element_legend === null) { + this.element_legend = document.createElement('div'); + this.element_legend.className = 'netdata-chart-legend netdata-' + this.library_name + '-legend'; + this.element.appendChild(this.element_legend); + } else { + this.element_legend.innerHTML = ''; + } + + this.element_legend_childs = { + content: content, + resize_handler: null, + toolbox: null, + toolbox_left: null, + toolbox_right: null, + toolbox_reset: null, + toolbox_zoomin: null, + toolbox_zoomout: null, + toolbox_volume: null, + title_date: document.createElement('span'), + title_time: document.createElement('span'), + title_units: document.createElement('span'), + perfect_scroller: document.createElement('div'), + series: {} + }; + + if (NETDATA.options.current.legend_toolbox && this.library.toolboxPanAndZoom !== null) { + this.element_legend_childs.toolbox = document.createElement('div'); + this.element_legend_childs.toolbox_left = document.createElement('div'); + this.element_legend_childs.toolbox_right = document.createElement('div'); + this.element_legend_childs.toolbox_reset = document.createElement('div'); + this.element_legend_childs.toolbox_zoomin = document.createElement('div'); + this.element_legend_childs.toolbox_zoomout = document.createElement('div'); + this.element_legend_childs.toolbox_volume = document.createElement('div'); + + const getPanAndZoomStep = function (event) { + if (event.ctrlKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_control; + } else if (event.shiftKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_shift; + } else if (event.altKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_alt; + } else { + return NETDATA.options.current.pan_and_zoom_factor; + } + }; + + this.element_legend_childs.toolbox.className += ' netdata-legend-toolbox'; + this.element.appendChild(this.element_legend_childs.toolbox); + + this.element_legend_childs.toolbox_left.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_left.innerHTML = NETDATA.icons.left; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_left); + this.element_legend_childs.toolbox_left.onclick = function (e) { + e.preventDefault(); + + let step = (that.view_before - that.view_after) * getPanAndZoomStep(e); + let before = that.view_before - step; + let after = that.view_after - step; + if (after >= that.netdata_first) { + that.library.toolboxPanAndZoom(that, after, before); + } + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_left).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Pan Left', + content: 'Pan the chart to the left. You can also <b>drag it</b> with your mouse or your finger (on touch devices).<br/><small>Help can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_reset.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_reset.innerHTML = NETDATA.icons.reset; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_reset); + this.element_legend_childs.toolbox_reset.onclick = function (e) { + e.preventDefault(); + NETDATA.resetAllCharts(that); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_reset).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Reset', + content: 'Reset all the charts to their default auto-refreshing state. You can also <b>double click</b> the chart contents with your mouse or your finger (on touch devices).<br/><small>Help can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_right.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_right.innerHTML = NETDATA.icons.right; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_right); + this.element_legend_childs.toolbox_right.onclick = function (e) { + e.preventDefault(); + let step = (that.view_before - that.view_after) * getPanAndZoomStep(e); + let before = that.view_before + step; + let after = that.view_after + step; + if (before <= that.netdata_last) { + that.library.toolboxPanAndZoom(that, after, before); + } + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_right).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Pan Right', + content: 'Pan the chart to the right. You can also <b>drag it</b> with your mouse or your finger (on touch devices).<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_zoomin.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_zoomin.innerHTML = NETDATA.icons.zoomIn; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_zoomin); + this.element_legend_childs.toolbox_zoomin.onclick = function (e) { + e.preventDefault(); + let dt = ((that.view_before - that.view_after) * (getPanAndZoomStep(e) * 0.8) / 2); + let before = that.view_before - dt; + let after = that.view_after + dt; + that.library.toolboxPanAndZoom(that, after, before); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_zoomin).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Zoom In', + content: 'Zoom in the chart. You can also press SHIFT and select an area of the chart, or press SHIFT or ALT and use the mouse wheel or 2-finger touchpad scroll to zoom in or out.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_zoomout.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_zoomout.innerHTML = NETDATA.icons.zoomOut; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_zoomout); + this.element_legend_childs.toolbox_zoomout.onclick = function (e) { + e.preventDefault(); + let dt = (((that.view_before - that.view_after) / (1.0 - (getPanAndZoomStep(e) * 0.8)) - (that.view_before - that.view_after)) / 2); + let before = that.view_before + dt; + let after = that.view_after - dt; + + that.library.toolboxPanAndZoom(that, after, before); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_zoomout).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Zoom Out', + content: 'Zoom out the chart. You can also press SHIFT or ALT and use the mouse wheel, or 2-finger touchpad scroll to zoom in or out.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + //this.element_legend_childs.toolbox_volume.className += ' netdata-legend-toolbox-button'; + //this.element_legend_childs.toolbox_volume.innerHTML = '<i class="fas fa-sort-amount-down"></i>'; + //this.element_legend_childs.toolbox_volume.title = 'Visible Volume'; + //this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_volume); + //this.element_legend_childs.toolbox_volume.onclick = function(e) { + //e.preventDefault(); + //alert('clicked toolbox_volume on ' + that.id); + //} + } + + if (NETDATA.options.current.resize_charts) { + this.element_legend_childs.resize_handler = document.createElement('div'); + + this.element_legend_childs.resize_handler.className += " netdata-legend-resize-handler"; + this.element_legend_childs.resize_handler.innerHTML = NETDATA.icons.resize; + this.element.appendChild(this.element_legend_childs.resize_handler); + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.resize_handler).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Resize', + content: 'Drag this point with your mouse or your finger (on touch devices), to resize the chart vertically. You can also <b>double click it</b> or <b>double tap it</b> to reset between 2 states: the default and the one that fits all the values.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + // mousedown event + this.element_legend_childs.resize_handler.onmousedown = + function (e) { + that.resizeHandler(e); + }; + + // touchstart event + this.element_legend_childs.resize_handler.addEventListener('touchstart', function (e) { + that.resizeHandler(e); + }, false); + } + + if (this.chart) { + this.element_legend_childs.title_date.title = this.legendPluginModuleString(true); + this.element_legend_childs.title_time.title = this.legendResolutionTooltip(); + } + + this.element_legend_childs.title_date.className += " netdata-legend-title-date"; + this.element_legend.appendChild(this.element_legend_childs.title_date); + this.tmp.__last_shown_legend_date = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.title_time.className += " netdata-legend-title-time"; + this.element_legend.appendChild(this.element_legend_childs.title_time); + this.tmp.__last_shown_legend_time = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.title_units.className += " netdata-legend-title-units"; + this.element_legend_childs.title_units.innerText = this.units_current; + this.element_legend.appendChild(this.element_legend_childs.title_units); + this.tmp.__last_shown_legend_units = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.perfect_scroller.className = 'netdata-legend-series'; + this.element_legend.appendChild(this.element_legend_childs.perfect_scroller); + + content.className = 'netdata-legend-series-content'; + this.element_legend_childs.perfect_scroller.appendChild(content); + + this.element_legend_childs.content = content; + + if (NETDATA.options.current.show_help) { + $(content).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + title: 'Chart Legend', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + content: 'You can click or tap on the values or the labels to select dimensions. By pressing SHIFT or CONTROL, you can enable or disable multiple dimensions.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + } else { + this.element_legend_childs = { + content: content, + resize_handler: null, + toolbox: null, + toolbox_left: null, + toolbox_right: null, + toolbox_reset: null, + toolbox_zoomin: null, + toolbox_zoomout: null, + toolbox_volume: null, + title_date: null, + title_time: null, + title_units: null, + perfect_scroller: null, + series: {} + }; + } + + if (this.data) { + this.element_legend_childs.series.labels_key = this.data.dimension_names.toString(); + if (this.debug) { + this.log('labels from data: "' + this.element_legend_childs.series.labels_key + '"'); + } + + for (let i = 0, len = this.data.dimension_names.length; i < len; i++) { + genLabel(this, content, this.data.dimension_ids[i], this.data.dimension_names[i], i); + } + } else { + let tmp = []; + keys = Object.keys(this.chart.dimensions); + for (let i = 0, len = keys.length; i < len; i++) { + dim = keys[i]; + tmp.push(this.chart.dimensions[dim].name); + genLabel(this, content, dim, this.chart.dimensions[dim].name, i); + } + this.element_legend_childs.series.labels_key = tmp.toString(); + if (this.debug) { + this.log('labels from chart: "' + this.element_legend_childs.series.labels_key + '"'); + } + } + + // create a hidden div to be used for hidding + // the original legend of the chart library + let el = document.createElement('div'); + if (this.element_legend !== null) { + this.element_legend.appendChild(el); + } + el.style.display = 'none'; + + this.element_legend_childs.hidden = document.createElement('div'); + el.appendChild(this.element_legend_childs.hidden); + + if (this.element_legend_childs.perfect_scroller !== null) { + Ps.initialize(this.element_legend_childs.perfect_scroller, { + wheelSpeed: 0.2, + wheelPropagation: true, + swipePropagation: true, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + Ps.update(this.element_legend_childs.perfect_scroller); + } + + this.legendShowLatestValues(); + }; + + this.hasLegend = function () { + if (typeof this.tmp.___hasLegendCache___ !== 'undefined') { + return this.tmp.___hasLegendCache___; + } + + let leg = false; + if (this.library && this.library.legend(this) === 'right-side') { + leg = true; + } + + this.tmp.___hasLegendCache___ = leg; + return leg; + }; + + this.legendWidth = function () { + return (this.hasLegend()) ? 140 : 0; + }; + + this.legendHeight = function () { + return $(this.element).height(); + }; + + this.chartWidth = function () { + return $(this.element).width() - this.legendWidth(); + }; + + this.chartHeight = function () { + return $(this.element).height(); + }; + + this.chartPixelsPerPoint = function () { + // force an options provided detail + let px = this.pixels_per_point; + + if (this.library && px < this.library.pixels_per_point(this)) { + px = this.library.pixels_per_point(this); + } + + if (px < NETDATA.options.current.pixels_per_point) { + px = NETDATA.options.current.pixels_per_point; + } + + return px; + }; + + this.needsRecreation = function () { + let ret = ( + this.chart_created && + this.library && + this.library.autoresize() === false && + this.tm.last_resized < NETDATA.options.last_page_resize + ); + + if (this.debug) { + this.log('needsRecreation(): ' + ret.toString() + ', chart_created = ' + this.chart_created.toString()); + } + + return ret; + }; + + this.chartDataUniqueID = function () { + return this.id + ',' + this.library_name + ',' + this.dimensions + ',' + this.chartURLOptions(); + }; + + this.chartURLOptions = function () { + let ret = ''; + + if (this.override_options !== null) { + ret = this.override_options.toString(); + } else { + ret = this.library.options(this); + } + + if (this.append_options !== null) { + ret += '%7C' + this.append_options.toString(); + } + + ret += '%7C' + 'jsonwrap'; + + if (NETDATA.options.current.eliminate_zero_dimensions) { + ret += '%7C' + 'nonzero'; + } + + return ret; + }; + + this.chartURL = function () { + let after, before, points_multiplier = 1; + if (NETDATA.globalPanAndZoom.isActive()) { + if (this.current.force_before_ms !== null && this.current.force_after_ms !== null) { + this.tm.pan_and_zoom_seq = 0; + + before = Math.round(this.current.force_before_ms / 1000); + after = Math.round(this.current.force_after_ms / 1000); + this.view_after = after * 1000; + this.view_before = before * 1000; + + if (NETDATA.options.current.pan_and_zoom_data_padding) { + this.requested_padding = Math.round((before - after) / 2); + after -= this.requested_padding; + before += this.requested_padding; + this.requested_padding *= 1000; + points_multiplier = 2; + } + + this.current.force_before_ms = null; + this.current.force_after_ms = null; + } else { + this.tm.pan_and_zoom_seq = NETDATA.globalPanAndZoom.seq; + + after = Math.round(NETDATA.globalPanAndZoom.force_after_ms / 1000); + before = Math.round(NETDATA.globalPanAndZoom.force_before_ms / 1000); + this.view_after = after * 1000; + this.view_before = before * 1000; + + this.requested_padding = null; + points_multiplier = 1; + } + } else { + this.tm.pan_and_zoom_seq = 0; + + before = this.before; + after = this.after; + this.view_after = after * 1000; + this.view_before = before * 1000; + + this.requested_padding = null; + points_multiplier = 1; + } + + this.requested_after = after * 1000; + this.requested_before = before * 1000; + + let data_points; + if (NETDATA.options.force_data_points !== 0) { + data_points = NETDATA.options.force_data_points; + this.data_points = data_points; + } else { + this.data_points = this.points || Math.round(this.chartWidth() / this.chartPixelsPerPoint()); + data_points = this.data_points * points_multiplier; + } + + // build the data URL + this.data_url = this.host + this.chart.data_url; + this.data_url += "&format=" + this.library.format(); + this.data_url += "&points=" + (data_points).toString(); + this.data_url += "&group=" + this.method; + this.data_url += ">ime=" + this.gtime; + this.data_url += "&options=" + this.chartURLOptions(); + + if (after) { + this.data_url += "&after=" + after.toString(); + } + + if (before) { + this.data_url += "&before=" + before.toString(); + } + + if (this.dimensions) { + this.data_url += "&dimensions=" + this.dimensions; + } + + if (NETDATA.options.debug.chart_data_url || this.debug) { + this.log('chartURL(): ' + this.data_url + ' WxH:' + this.chartWidth() + 'x' + this.chartHeight() + ' points: ' + data_points.toString() + ' library: ' + this.library_name); + } + }; + + this.redrawChart = function () { + if (this.data !== null) { + this.updateChartWithData(this.data); + } + }; + + this.updateChartWithData = function (data) { + if (this.debug) { + this.log('updateChartWithData() called.'); + } + + // this may force the chart to be re-created + resizeChart(); + + this.data = data; + + let started = Date.now(); + let view_update_every = data.view_update_every * 1000; + + if (this.data_update_every !== view_update_every) { + if (this.element_legend_childs.title_time) { + this.element_legend_childs.title_time.title = this.legendResolutionTooltip(); + } + } + + // if the result is JSON, find the latest update-every + this.data_update_every = view_update_every; + this.data_after = data.after * 1000; + this.data_before = data.before * 1000; + this.netdata_first = data.first_entry * 1000; + this.netdata_last = data.last_entry * 1000; + this.data_points = data.points; + + data.state = this; + + if (NETDATA.options.current.pan_and_zoom_data_padding && this.requested_padding !== null) { + if (this.view_after < this.data_after) { + // console.log('adjusting view_after from ' + this.view_after + ' to ' + this.data_after); + this.view_after = this.data_after; + } + + if (this.view_before > this.data_before) { + // console.log('adjusting view_before from ' + this.view_before + ' to ' + this.data_before); + this.view_before = this.data_before; + } + } else { + this.view_after = this.data_after; + this.view_before = this.data_before; + } + + if (this.debug) { + this.log('UPDATE No ' + this.updates_counter + ' COMPLETED'); + + if (this.current.force_after_ms) { + this.log('STATUS: forced : ' + (this.current.force_after_ms / 1000).toString() + ' - ' + (this.current.force_before_ms / 1000).toString()); + } else { + this.log('STATUS: forced : unset'); + } + + this.log('STATUS: requested : ' + (this.requested_after / 1000).toString() + ' - ' + (this.requested_before / 1000).toString()); + this.log('STATUS: downloaded: ' + (this.data_after / 1000).toString() + ' - ' + (this.data_before / 1000).toString()); + this.log('STATUS: rendered : ' + (this.view_after / 1000).toString() + ' - ' + (this.view_before / 1000).toString()); + this.log('STATUS: points : ' + (this.data_points).toString()); + } + + if (this.data_points === 0) { + noDataToShow(); + return; + } + + if (this.updates_since_last_creation >= this.library.max_updates_to_recreate()) { + if (this.debug) { + this.log('max updates of ' + this.updates_since_last_creation.toString() + ' reached. Forcing re-generation.'); + } + + init('force'); + return; + } + + // check and update the legend + this.legendUpdateDOM(); + + if (this.chart_created && typeof this.library.update === 'function') { + if (this.debug) { + this.log('updating chart...'); + } + + if (!callChartLibraryUpdateSafely(data)) { + return; + } + } else { + if (this.debug) { + this.log('creating chart...'); + } + + if (!callChartLibraryCreateSafely(data)) { + return; + } + } + + if (this.isVisible()) { + hideMessage(); + this.legendShowLatestValues(); + } else { + this.__redraw_on_unhide = true; + + if (this.debug) { + this.log("drawn while not visible"); + } + } + + if (this.selected) { + NETDATA.globalSelectionSync.stop(); + } + + // update the performance counters + let now = Date.now(); + this.tm.last_updated = now; + + // don't update last_autorefreshed if this chart is + // forced to be updated with global PanAndZoom + if (NETDATA.globalPanAndZoom.isActive()) { + this.tm.last_autorefreshed = 0; + } else { + if (NETDATA.options.current.parallel_refresher && NETDATA.options.current.concurrent_refreshes && typeof this.force_update_every !== 'number') { + this.tm.last_autorefreshed = now - (now % this.data_update_every); + } else { + this.tm.last_autorefreshed = now; + } + } + + this.refresh_dt_ms = now - started; + NETDATA.options.auto_refresher_fast_weight += this.refresh_dt_ms; + + if (this.refresh_dt_element !== null) { + this.refresh_dt_element.innerText = this.refresh_dt_ms.toString(); + } + + if (this.foreignElementBefore !== null) { + this.foreignElementBefore.innerText = NETDATA.dateTime.localeDateString(this.view_before) + ' ' + NETDATA.dateTime.localeTimeString(this.view_before); + } + + if (this.foreignElementAfter !== null) { + this.foreignElementAfter.innerText = NETDATA.dateTime.localeDateString(this.view_after) + ' ' + NETDATA.dateTime.localeTimeString(this.view_after); + } + + if (this.foreignElementDuration !== null) { + this.foreignElementDuration.innerText = NETDATA.seconds4human(Math.floor((this.view_before - this.view_after) / 1000) + 1); + } + + if (this.foreignElementUpdateEvery !== null) { + this.foreignElementUpdateEvery.innerText = NETDATA.seconds4human(Math.floor(this.data_update_every / 1000)); + } + }; + + this.getSnapshotData = function (key) { + if (this.debug) { + this.log('updating from snapshot: ' + key); + } + + if (typeof netdataSnapshotData.data[key] === 'undefined') { + this.log('snapshot does not include data for key "' + key + '"'); + return null; + } + + if (typeof netdataSnapshotData.data[key] !== 'string') { + this.log('snapshot data for key "' + key + '" is not string'); + return null; + } + + let uncompressed; + try { + uncompressed = netdataSnapshotData.uncompress(netdataSnapshotData.data[key]); + + if (uncompressed === null) { + this.log('uncompressed snapshot data for key ' + key + ' is null'); + return null; + } + + if (typeof uncompressed === 'undefined') { + this.log('uncompressed snapshot data for key ' + key + ' is undefined'); + return null; + } + } catch (e) { + this.log('decompression of snapshot data for key ' + key + ' failed'); + console.log(e); + uncompressed = null; + } + + if (typeof uncompressed !== 'string') { + this.log('uncompressed snapshot data for key ' + key + ' is not string'); + return null; + } + + let data; + try { + data = JSON.parse(uncompressed); + } catch (e) { + this.log('parsing snapshot data for key ' + key + ' failed'); + console.log(e); + data = null; + } + + return data; + }; + + this.updateChart = function (callback) { + if (this.debug) { + this.log('updateChart()'); + } + + if (this.fetching_data) { + if (this.debug) { + this.log('updateChart(): I am already updating...'); + } + + if (typeof callback === 'function') { + return callback(false, 'already running'); + } + + return; + } + + // due to late initialization of charts and libraries + // we need to check this too + if (!this.enabled) { + if (this.debug) { + this.log('updateChart(): I am not enabled'); + } + + if (typeof callback === 'function') { + return callback(false, 'not enabled'); + } + + return; + } + + if (!canBeRendered()) { + if (this.debug) { + this.log('updateChart(): cannot be rendered'); + } + + if (typeof callback === 'function') { + return callback(false, 'cannot be rendered'); + } + + return; + } + + if (that.dom_created !== true) { + if (this.debug) { + this.log('updateChart(): creating DOM'); + } + + createDOM(); + } + + if (this.chart === null) { + if (this.debug) { + this.log('updateChart(): getting chart'); + } + + return this.getChart(function () { + return that.updateChart(callback); + }); + } + + if (!this.library.initialized) { + if (this.library.enabled) { + if (this.debug) { + this.log('updateChart(): initializing chart library'); + } + + return this.library.initialize(function () { + return that.updateChart(callback); + }); + } else { + error('chart library "' + this.library_name + '" is not available.'); + + if (typeof callback === 'function') { + return callback(false, 'library not available'); + } + + return; + } + } + + this.clearSelection(); + this.chartURL(); + + NETDATA.statistics.refreshes_total++; + NETDATA.statistics.refreshes_active++; + + if (NETDATA.statistics.refreshes_active > NETDATA.statistics.refreshes_active_max) { + NETDATA.statistics.refreshes_active_max = NETDATA.statistics.refreshes_active; + } + + let ok = false; + this.fetching_data = true; + + if (netdataSnapshotData !== null) { + let key = this.chartDataUniqueID(); + let data = this.getSnapshotData(key); + if (data !== null) { + ok = true; + data = NETDATA.xss.checkData('/api/v1/data', data, this.library.xssRegexIgnore); + this.updateChartWithData(data); + } else { + ok = false; + error('cannot get data from snapshot for key: "' + key + '"'); + that.tm.last_autorefreshed = Date.now(); + } + + NETDATA.statistics.refreshes_active--; + this.fetching_data = false; + + if (typeof callback === 'function') { + callback(ok, 'snapshot'); + } + + return; + } + + if (this.debug) { + this.log('updating from ' + this.data_url); + } + + this.xhr = $.ajax({ + url: this.data_url, + cache: false, + async: true, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkData('/api/v1/data', data, that.library.xssRegexIgnore); + + that.xhr = undefined; + that.retries_on_data_failures = 0; + ok = true; + + if (that.debug) { + that.log('data received. updating chart.'); + } + + that.updateChartWithData(data); + }) + .fail(function (msg) { + that.xhr = undefined; + + if (msg.statusText !== 'abort') { + that.retries_on_data_failures++; + if (that.retries_on_data_failures > NETDATA.options.current.retries_on_data_failures) { + // that.log('failed ' + that.retries_on_data_failures.toString() + ' times - giving up'); + that.retries_on_data_failures = 0; + error('data download failed for url: ' + that.data_url); + } + else { + that.tm.last_autorefreshed = Date.now(); + // that.log('failed ' + that.retries_on_data_failures.toString() + ' times, but I will retry'); + } + } + }) + .always(function () { + that.xhr = undefined; + + NETDATA.statistics.refreshes_active--; + that.fetching_data = false; + + if (typeof callback === 'function') { + return callback(ok, 'download'); + } + }); + }; + + const __isVisible = function () { + let ret = true; + + if (NETDATA.options.current.update_only_visible !== false) { + // tolerance is the number of pixels a chart can be off-screen + // to consider it as visible and refresh it as if was visible + let tolerance = 0; + + that.tm.last_visible_check = Date.now(); + + let rect = that.element.getBoundingClientRect(); + + let screenTop = window.scrollY; + let screenBottom = screenTop + window.innerHeight; + + let chartTop = rect.top + screenTop; + let chartBottom = chartTop + rect.height; + + ret = !(rect.width === 0 || rect.height === 0 || chartBottom + tolerance < screenTop || chartTop - tolerance > screenBottom); + } + + if (that.debug) { + that.log('__isVisible(): ' + ret); + } + + return ret; + }; + + this.isVisible = function (nocache) { + // this.log('last_visible_check: ' + this.tm.last_visible_check + ', last_page_scroll: ' + NETDATA.options.last_page_scroll); + + // caching - we do not evaluate the charts visibility + // if the page has not been scrolled since the last check + if ((typeof nocache !== 'undefined' && nocache) + || typeof this.tmp.___isVisible___ === 'undefined' + || this.tm.last_visible_check <= NETDATA.options.last_page_scroll) { + this.tmp.___isVisible___ = __isVisible(); + if (this.tmp.___isVisible___) { + this.unhideChart(); + } else { + this.hideChart(); + } + } + + if (this.debug) { + this.log('isVisible(' + nocache + '): ' + this.tmp.___isVisible___); + } + + return this.tmp.___isVisible___; + }; + + this.isAutoRefreshable = function () { + return (this.current.autorefresh); + }; + + this.canBeAutoRefreshed = function () { + if (!this.enabled) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> not enabled'); + } + + return false; + } + + if (this.running) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> already running'); + } + + return false; + } + + if (this.library === null || this.library.enabled === false) { + error('charting library "' + this.library_name + '" is not available'); + if (this.debug) { + this.log('canBeAutoRefreshed() -> chart library ' + this.library_name + ' is not available'); + } + + return false; + } + + if (!this.isVisible()) { + if (NETDATA.options.debug.visibility || this.debug) { + this.log('canBeAutoRefreshed() -> not visible'); + } + + return false; + } + + let now = Date.now(); + + if (this.current.force_update_at !== 0 && this.current.force_update_at < now) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> timed force update - allowing this update'); + } + + this.current.force_update_at = 0; + return true; + } + + if (!this.isAutoRefreshable()) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> not auto-refreshable'); + } + + return false; + } + + // allow the first update, even if the page is not visible + if (NETDATA.options.page_is_visible === false && this.updates_counter && this.updates_since_last_unhide) { + if (NETDATA.options.debug.focus || this.debug) { + this.log('canBeAutoRefreshed() -> not the first update, and page does not have focus'); + } + + return false; + } + + if (this.needsRecreation()) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> needs re-creation.'); + } + + return true; + } + + if (NETDATA.options.auto_refresher_stop_until >= now) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> stopped until is in future.'); + } + + return false; + } + + // options valid only for autoRefresh() + if (NETDATA.globalPanAndZoom.isActive()) { + if (NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this)) { + if (this.debug) { + this.log('canBeAutoRefreshed(): global panning: I need an update.'); + } + + return true; + } + else { + if (this.debug) { + this.log('canBeAutoRefreshed(): global panning: I am already up to date.'); + } + + return false; + } + } + + if (this.selected) { + if (this.debug) { + this.log('canBeAutoRefreshed(): I have a selection in place.'); + } + + return false; + } + + if (this.paused) { + if (this.debug) { + this.log('canBeAutoRefreshed(): I am paused.'); + } + + return false; + } + + let data_update_every = this.data_update_every; + if (typeof this.force_update_every === 'number') { + data_update_every = this.force_update_every; + } + + if (now - this.tm.last_autorefreshed >= data_update_every) { + if (this.debug) { + this.log('canBeAutoRefreshed(): It is time to update me. Now: ' + now.toString() + ', last_autorefreshed: ' + this.tm.last_autorefreshed + ', data_update_every: ' + data_update_every + ', delta: ' + (now - this.tm.last_autorefreshed).toString()); + } + + return true; + } + + return false; + }; + + this.autoRefresh = function (callback) { + let state = that; + + if (state.canBeAutoRefreshed() && state.running === false) { + state.running = true; + state.updateChart(function () { + state.running = false; + + if (typeof callback === 'function') { + return callback(); + } + }); + } else { + if (typeof callback === 'function') { + return callback(); + } + } + }; + + this.__defaultsFromDownloadedChart = function (chart) { + this.chart = chart; + this.chart_url = chart.url; + this.data_update_every = chart.update_every * 1000; + this.data_points = Math.round(this.chartWidth() / this.chartPixelsPerPoint()); + this.tm.last_info_downloaded = Date.now(); + + if (this.title === null) { + this.title = chart.title; + } + + if (this.units === null) { + this.units = chart.units; + this.units_current = this.units; + } + }; + + // fetch the chart description from the netdata server + this.getChart = function (callback) { + this.chart = NETDATA.chartRegistry.get(this.host, this.id); + if (this.chart) { + this.__defaultsFromDownloadedChart(this.chart); + + if (typeof callback === 'function') { + return callback(); + } + } else if (netdataSnapshotData !== null) { + // console.log(this); + // console.log(NETDATA.chartRegistry); + NETDATA.error(404, 'host: ' + this.host + ', chart: ' + this.id); + error('chart not found in snapshot'); + + if (typeof callback === 'function') { + return callback(); + } + } else { + this.chart_url = "/api/v1/chart?chart=" + this.id; + + if (this.debug) { + this.log('downloading ' + this.chart_url); + } + + $.ajax({ + url: this.host + this.chart_url, + cache: false, + async: true, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (chart) { + chart = NETDATA.xss.checkOptional('/api/v1/chart', chart); + + chart.url = that.chart_url; + that.__defaultsFromDownloadedChart(chart); + NETDATA.chartRegistry.add(that.host, that.id, chart); + }) + .fail(function () { + NETDATA.error(404, that.chart_url); + error('chart not found on url "' + that.chart_url + '"'); + }) + .always(function () { + if (typeof callback === 'function') { + return callback(); + } + }); + } + }; + + // ============================================================================================================ + // INITIALIZATION + + initDOM(); + init('fast'); +}; + +NETDATA.resetAllCharts = function (state) { + // first clear the global selection sync + // to make sure no chart is in selected state + NETDATA.globalSelectionSync.stop(); + + // there are 2 possibilities here + // a. state is the global Pan and Zoom master + // b. state is not the global Pan and Zoom master + + // let master = true; + // if (NETDATA.globalPanAndZoom.isMaster(state) === false) { + // master = false; + // } + const master = NETDATA.globalPanAndZoom.isMaster(state) + + // clear the global Pan and Zoom + // this will also refresh the master + // and unblock any charts currently mirroring the master + NETDATA.globalPanAndZoom.clearMaster(); + + // if we were not the master, reset our status too + // this is required because most probably the mouse + // is over this chart, blocking it from auto-refreshing + if (master === false && (state.paused || state.selected)) { + state.resetChart(); + } +}; + +// get or create a chart state, given a DOM element +NETDATA.chartState = function (element) { + let self = $(element); + + let state = self.data('netdata-state-object') || null; + if (state === null) { + state = new chartState(element); + self.data('netdata-state-object', state); + } + return state; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// Library functions + +// Load a script without jquery +// This is used to load jquery - after it is loaded, we use jquery +NETDATA._loadjQuery = function (callback) { + if (typeof jQuery === 'undefined') { + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.jQuery); + } + + let script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = true; + script.src = NETDATA.jQuery; + + // script.onabort = onError; + script.onerror = function () { + NETDATA.error(101, NETDATA.jQuery); + }; + if (typeof callback === "function") { + script.onload = function () { + $ = jQuery; + return callback(); + }; + } + + let s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(script, s); + } + else if (typeof callback === "function") { + $ = jQuery; + return callback(); + } +}; + +NETDATA._loadCSS = function (filename) { + // don't use jQuery here + // styles are loaded before jQuery + // to eliminate showing an unstyled page to the user + + let fileref = document.createElement("link"); + fileref.setAttribute("rel", "stylesheet"); + fileref.setAttribute("type", "text/css"); + fileref.setAttribute("href", filename); + + if (typeof fileref !== 'undefined') { + document.getElementsByTagName("head")[0].appendChild(fileref); + } +}; + +// user function to signal us the DOM has been +// updated. +NETDATA.updatedDom = function () { + NETDATA.options.updated_dom = true; +}; + +NETDATA.ready = function (callback) { + NETDATA.options.pauseCallback = callback; +}; + +NETDATA.pause = function (callback) { + if (typeof callback === 'function') { + if (NETDATA.options.pause) { + return callback(); + } else { + NETDATA.options.pauseCallback = callback; + } + } +}; + +NETDATA.unpause = function () { + NETDATA.options.pauseCallback = null; + NETDATA.options.updated_dom = true; + NETDATA.options.pause = false; +}; + +// ---------------------------------------------------------------------------------------------------------------- + +// this is purely sequential charts refresher +// it is meant to be autonomous +NETDATA.chartRefresherNoParallel = function (index, callback) { + let targets = NETDATA.intersectionObserver.targets(); + + if (NETDATA.options.debug.main_loop) { + console.log('NETDATA.chartRefresherNoParallel(' + index + ')'); + } + + if (NETDATA.options.updated_dom) { + // the dom has been updated + // get the dom parts again + NETDATA.parseDom(callback); + return; + } + if (index >= targets.length) { + if (NETDATA.options.debug.main_loop) { + console.log('waiting to restart main loop...'); + } + + NETDATA.options.auto_refresher_fast_weight = 0; + callback(); + } else { + let state = targets[index]; + + if (NETDATA.options.auto_refresher_fast_weight < NETDATA.options.current.fast_render_timeframe) { + if (NETDATA.options.debug.main_loop) { + console.log('fast rendering...'); + } + + if (state.isVisible()) { + NETDATA.timeout.set(function () { + state.autoRefresh(function () { + NETDATA.chartRefresherNoParallel(++index, callback); + }); + }, 0); + } else { + NETDATA.chartRefresherNoParallel(++index, callback); + } + } else { + if (NETDATA.options.debug.main_loop) { + console.log('waiting for next refresh...'); + } + NETDATA.options.auto_refresher_fast_weight = 0; + + NETDATA.timeout.set(function () { + state.autoRefresh(function () { + NETDATA.chartRefresherNoParallel(++index, callback); + }); + }, NETDATA.options.current.idle_between_charts); + } + } +}; + +NETDATA.chartRefresherWaitTime = function () { + return NETDATA.options.current.idle_parallel_loops; +}; + +// the default refresher +NETDATA.chartRefresherLastRun = 0; +NETDATA.chartRefresherRunsAfterParseDom = 0; +NETDATA.chartRefresherTimeoutId = undefined; + +NETDATA.chartRefresherReschedule = function () { + if (NETDATA.options.current.async_on_scroll) { + if (NETDATA.chartRefresherTimeoutId) { + NETDATA.timeout.clear(NETDATA.chartRefresherTimeoutId); + } + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set(NETDATA.chartRefresher, NETDATA.options.current.onscroll_worker_duration_threshold); + //console.log('chartRefresherReschedule()'); + } +}; + +NETDATA.chartRefresher = function () { + // console.log('chartRefresher() begin ' + (Date.now() - NETDATA.chartRefresherLastRun).toString() + ' ms since last run'); + + if (NETDATA.options.page_is_visible === false + && NETDATA.options.current.stop_updates_when_focus_is_lost + && NETDATA.chartRefresherLastRun > NETDATA.options.last_page_resize + && NETDATA.chartRefresherLastRun > NETDATA.options.last_page_scroll + && NETDATA.chartRefresherRunsAfterParseDom > 10 + ) { + setTimeout( + NETDATA.chartRefresher, + NETDATA.options.current.idle_lost_focus + ); + + // console.log('chartRefresher() page without focus, will run in ' + NETDATA.options.current.idle_lost_focus.toString() + ' ms, ' + NETDATA.chartRefresherRunsAfterParseDom.toString()); + return; + } + NETDATA.chartRefresherRunsAfterParseDom++; + + let now = Date.now(); + NETDATA.chartRefresherLastRun = now; + + if (now < NETDATA.options.on_scroll_refresher_stop_until) { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end1 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (now < NETDATA.options.auto_refresher_stop_until) { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end2 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (NETDATA.options.pause) { + // console.log('auto-refresher is paused'); + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end3 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (typeof NETDATA.options.pauseCallback === 'function') { + // console.log('auto-refresher is calling pauseCallback'); + + NETDATA.options.pause = true; + NETDATA.options.pauseCallback(); + NETDATA.chartRefresher(); + + // console.log('chartRefresher() end4 (nested)'); + return; + } + + if (!NETDATA.options.current.parallel_refresher) { + // console.log('auto-refresher is calling chartRefresherNoParallel(0)'); + NETDATA.chartRefresherNoParallel(0, function () { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.options.current.idle_between_loops + ); + }); + // console.log('chartRefresher() end5 (no parallel, nested)'); + return; + } + + if (NETDATA.options.updated_dom) { + // the dom has been updated + // get the dom parts again + // console.log('auto-refresher is calling parseDom()'); + NETDATA.parseDom(NETDATA.chartRefresher); + // console.log('chartRefresher() end6 (parseDom)'); + return; + } + + if (!NETDATA.globalSelectionSync.active()) { + let parallel = []; + let targets = NETDATA.intersectionObserver.targets(); + let len = targets.length; + let state; + while (len--) { + state = targets[len]; + if (state.running || state.isVisible() === false) { + continue; + } + + if (!state.library.initialized) { + if (state.library.enabled) { + state.library.initialize(NETDATA.chartRefresher); + //console.log('chartRefresher() end6 (library init)'); + return; + } + else { + state.error('chart library "' + state.library_name + '" is not enabled.'); + } + } + + if (NETDATA.scrollUp) { + parallel.unshift(state); + } else { + parallel.push(state); + } + } + + len = parallel.length; + while (len--) { + state = parallel[len]; + // console.log('auto-refresher executing in parallel for ' + parallel.length.toString() + ' charts'); + // this will execute the jobs in parallel + + if (!state.running) { + NETDATA.timeout.set(state.autoRefresh, 0); + } + } + //else { + // console.log('auto-refresher nothing to do'); + //} + } + + // run the next refresh iteration + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + //console.log('chartRefresher() completed in ' + (Date.now() - now).toString() + ' ms'); +}; + +NETDATA.parseDom = function (callback) { + //console.log('parseDom()'); + + NETDATA.options.last_page_scroll = Date.now(); + NETDATA.options.updated_dom = false; + NETDATA.chartRefresherRunsAfterParseDom = 0; + + let targets = $('div[data-netdata]'); //.filter(':visible'); + + if (NETDATA.options.debug.main_loop) { + console.log('DOM updated - there are ' + targets.length + ' charts on page.'); + } + + NETDATA.intersectionObserver.globalReset(); + NETDATA.options.targets = []; + let len = targets.length; + while (len--) { + // the initialization will take care of sizing + // and the "loading..." message + let state = NETDATA.chartState(targets[len]); + NETDATA.options.targets.push(state); + NETDATA.intersectionObserver.observe(state); + } + + if (NETDATA.globalChartUnderlay.isActive()) { + NETDATA.globalChartUnderlay.setup(); + } else { + NETDATA.globalChartUnderlay.clear(); + } + + if (typeof callback === 'function') { + return callback(); + } +}; + +// this is the main function - where everything starts +NETDATA.started = false; +NETDATA.start = function () { + // this should be called only once + + if (NETDATA.started) { + console.log('netdata is already started'); + return; + } + + NETDATA.started = true; + NETDATA.options.page_is_visible = true; + + $(window).blur(function () { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = false; + if (NETDATA.options.debug.focus) { + console.log('Lost Focus!'); + } + } + }); + + $(window).focus(function () { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = true; + if (NETDATA.options.debug.focus) { + console.log('Focus restored!'); + } + } + }); + + if (typeof document.hasFocus === 'function' && !document.hasFocus()) { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = false; + if (NETDATA.options.debug.focus) { + console.log('Document has no focus!'); + } + } + } + + // bootstrap tab switching + $('a[data-toggle="tab"]').on('shown.bs.tab', NETDATA.onscroll); + + // bootstrap modal switching + let $modal = $('.modal'); + $modal.on('hidden.bs.modal', NETDATA.onscroll); + $modal.on('shown.bs.modal', NETDATA.onscroll); + + // bootstrap collapse switching + let $collapse = $('.collapse'); + $collapse.on('hidden.bs.collapse', NETDATA.onscroll); + $collapse.on('shown.bs.collapse', NETDATA.onscroll); + + NETDATA.parseDom(NETDATA.chartRefresher); + + // Alarms initialization + setTimeout(NETDATA.alarms.init, 1000); + + // Registry initialization + setTimeout(NETDATA.registry.init, netdataRegistryAfterMs); + + if (typeof netdataCallback === 'function') { + netdataCallback(); + } +}; + +NETDATA.globalReset = function () { + NETDATA.intersectionObserver.globalReset(); + NETDATA.globalSelectionSync.globalReset(); + NETDATA.globalPanAndZoom.globalReset(); + NETDATA.chartRegistry.globalReset(); + NETDATA.commonMin.globalReset(); + NETDATA.commonMax.globalReset(); + NETDATA.commonColors.globalReset(); + NETDATA.unitsConversion.globalReset(); + NETDATA.options.targets = []; + NETDATA.parseDom(); + NETDATA.unpause(); +}; + +// Registry of netdata hosts + +NETDATA.alarms = { + onclick: null, // the callback to handle the click - it will be called with the alarm log entry + chart_div_offset: -50, // give that space above the chart when scrolling to it + chart_div_id_prefix: 'chart_', // the chart DIV IDs have this prefix (they should be NETDATA.name2id(chart.id)) + chart_div_animation_duration: 0,// the duration of the animation while scrolling to a chart + + ms_penalty: 0, // the time penalty of the next alarm + ms_between_notifications: 500, // firefox moves the alarms off-screen (above, outside the top of the screen) + // if alarms are shown faster than: one per 500ms + + update_every: 10000, // the time in ms between alarm checks + + notifications: false, // when true, the browser supports notifications (may not be granted though) + last_notification_id: 0, // the id of the last alarm_log we have raised an alarm for + first_notification_id: 0, // the id of the first alarm_log entry for this session + // this is used to prevent CLEAR notifications for past events + // notifications_shown: [], + + server: null, // the server to connect to for fetching alarms + current: null, // the list of raised alarms - updated in the background + + // a callback function to call every time the list of raised alarms is refreshed + callback: (typeof netdataAlarmsActiveCallback === 'function') ? netdataAlarmsActiveCallback : null, + + // a callback function to call every time a notification is shown + // the return value is used to decide if the notification will be shown + notificationCallback: (typeof netdataAlarmsNotifCallback === 'function') ? netdataAlarmsNotifCallback : null, + + recipients: null, // the list (array) of recipients to show alarms for, or null + + recipientMatches: function (to_string, wanted_array) { + if (typeof wanted_array === 'undefined' || wanted_array === null || Array.isArray(wanted_array) === false) { + return true; + } + + let r = ' ' + to_string.toString() + ' '; + let len = wanted_array.length; + while (len--) { + if (r.indexOf(' ' + wanted_array[len] + ' ') >= 0) { + return true; + } + } + + return false; + }, + + activeForRecipients: function () { + let active = {}; + let data = NETDATA.alarms.current; + + if (typeof data === 'undefined' || data === null) { + return active; + } + + for (let x in data.alarms) { + if (!data.alarms.hasOwnProperty(x)) { + continue; + } + + let alarm = data.alarms[x]; + if ((alarm.status === 'WARNING' || alarm.status === 'CRITICAL') && NETDATA.alarms.recipientMatches(alarm.recipient, NETDATA.alarms.recipients)) { + active[x] = alarm; + } + } + + return active; + }, + + notify: function (entry) { + // console.log('alarm ' + entry.unique_id); + + if (entry.updated) { + // console.log('alarm ' + entry.unique_id + ' has been updated by another alarm'); + return; + } + + let value_string = entry.value_string; + + if (NETDATA.alarms.current !== null) { + // get the current value_string + let t = NETDATA.alarms.current.alarms[entry.chart + '.' + entry.name]; + if (typeof t !== 'undefined' && entry.status === t.status && typeof t.value_string !== 'undefined') { + value_string = t.value_string; + } + } + + let name = entry.name.replace(/_/g, ' '); + let status = entry.status.toLowerCase(); + let title = name + ' = ' + value_string.toString(); + let tag = entry.alarm_id; + let icon = 'images/banner-icon-144x144.png'; + let interaction = false; + let data = entry; + let show = true; + + // console.log('alarm ' + entry.unique_id + ' ' + entry.chart + '.' + entry.name + ' is ' + entry.status); + + switch (entry.status) { + case 'REMOVED': + show = false; + break; + + case 'UNDEFINED': + return; + + case 'UNINITIALIZED': + return; + + case 'CLEAR': + if (entry.unique_id < NETDATA.alarms.first_notification_id) { + // console.log('alarm ' + entry.unique_id + ' is not current'); + return; + } + if (entry.old_status === 'UNINITIALIZED' || entry.old_status === 'UNDEFINED') { + // console.log('alarm' + entry.unique_id + ' switch to CLEAR from ' + entry.old_status); + return; + } + if (entry.no_clear_notification) { + // console.log('alarm' + entry.unique_id + ' is CLEAR but has no_clear_notification flag'); + return; + } + title = name + ' back to normal (' + value_string.toString() + ')'; + icon = 'images/check-mark-2-128-green.png'; + interaction = false; + break; + + case 'WARNING': + if (entry.old_status === 'CRITICAL') { + status = 'demoted to ' + entry.status.toLowerCase(); + } + + icon = 'images/alert-128-orange.png'; + interaction = false; + break; + + case 'CRITICAL': + if (entry.old_status === 'WARNING') { + status = 'escalated to ' + entry.status.toLowerCase(); + } + + icon = 'images/alert-128-red.png'; + interaction = true; + break; + + default: + console.log('invalid alarm status ' + entry.status); + return; + } + + // filter recipients + if (show) { + show = NETDATA.alarms.recipientMatches(entry.recipient, NETDATA.alarms.recipients); + } + + /* + // cleanup old notifications with the same alarm_id as this one + // it does not seem to work on any web browser - so notifications cannot be removed + + let len = NETDATA.alarms.notifications_shown.length; + while (len--) { + let n = NETDATA.alarms.notifications_shown[len]; + if (n.data.alarm_id === entry.alarm_id) { + console.log('removing old alarm ' + n.data.unique_id); + + // close the notification + n.close.bind(n); + + // remove it from the array + NETDATA.alarms.notifications_shown.splice(len, 1); + len = NETDATA.alarms.notifications_shown.length; + } + } + */ + + if (show) { + if (typeof NETDATA.alarms.notificationCallback === 'function') { + show = NETDATA.alarms.notificationCallback(entry); + } + + if (show) { + setTimeout(function () { + // show this notification + // console.log('new notification: ' + title); + let n = new Notification(title, { + body: entry.hostname + ' - ' + entry.chart + ' (' + entry.family + ') - ' + status + ': ' + entry.info, + tag: tag, + requireInteraction: interaction, + icon: NETDATA.serverStatic + icon, + data: data + }); + + n.onclick = function (event) { + event.preventDefault(); + NETDATA.alarms.onclick(event.target.data); + }; + + // console.log(n); + // NETDATA.alarms.notifications_shown.push(n); + // console.log(entry); + }, NETDATA.alarms.ms_penalty); + + NETDATA.alarms.ms_penalty += NETDATA.alarms.ms_between_notifications; + } + } + }, + + scrollToChart: function (chart_id) { + if (typeof chart_id === 'string') { + let offset = $('#' + NETDATA.alarms.chart_div_id_prefix + NETDATA.name2id(chart_id)).offset(); + if (typeof offset !== 'undefined') { + $('html, body').animate({scrollTop: offset.top + NETDATA.alarms.chart_div_offset}, NETDATA.alarms.chart_div_animation_duration); + return true; + } + } + return false; + }, + + scrollToAlarm: function (alarm) { + if (typeof alarm === 'object') { + let ret = NETDATA.alarms.scrollToChart(alarm.chart); + + if (ret && NETDATA.options.page_is_visible === false) { + window.focus(); + } + // alert('netdata dashboard will now scroll to chart: ' + alarm.chart + '\n\nThis alarm opened to bring the browser window in front of the screen. Click on the dashboard to prevent it from appearing again.'); + } + + }, + + notifyAll: function () { + // console.log('FETCHING ALARM LOG'); + NETDATA.alarms.get_log(NETDATA.alarms.last_notification_id, function (data) { + // console.log('ALARM LOG FETCHED'); + + if (data === null || typeof data !== 'object') { + console.log('invalid alarms log response'); + return; + } + + if (data.length === 0) { + console.log('received empty alarm log'); + return; + } + + // console.log('received alarm log of ' + data.length + ' entries, from ' + data[data.length - 1].unique_id.toString() + ' to ' + data[0].unique_id.toString()); + + data.sort(function (a, b) { + if (a.unique_id > b.unique_id) { + return -1; + } + if (a.unique_id < b.unique_id) { + return 1; + } + return 0; + }); + + NETDATA.alarms.ms_penalty = 0; + + let len = data.length; + while (len--) { + if (data[len].unique_id > NETDATA.alarms.last_notification_id) { + NETDATA.alarms.notify(data[len]); + } + //else + // console.log('ignoring alarm (older) with id ' + data[len].unique_id.toString()); + } + + NETDATA.alarms.last_notification_id = data[0].unique_id; + + if (typeof netdataAlarmsRemember === 'undefined' || netdataAlarmsRemember) { + NETDATA.localStorageSet('last_notification_id', NETDATA.alarms.last_notification_id, null); + } + // console.log('last notification id = ' + NETDATA.alarms.last_notification_id); + }) + }, + + check_notifications: function () { + // returns true if we should fire 1+ notifications + + if (NETDATA.alarms.notifications !== true) { + // console.log('web notifications are not available'); + return false; + } + + if (Notification.permission !== 'granted') { + // console.log('web notifications are not granted'); + return false; + } + + if (typeof NETDATA.alarms.current !== 'undefined' && typeof NETDATA.alarms.current.alarms === 'object') { + // console.log('can do alarms: old id = ' + NETDATA.alarms.last_notification_id + ' new id = ' + NETDATA.alarms.current.latest_alarm_log_unique_id); + + if (NETDATA.alarms.current.latest_alarm_log_unique_id > NETDATA.alarms.last_notification_id) { + // console.log('new alarms detected'); + return true; + } + //else console.log('no new alarms'); + } + // else console.log('cannot process alarms'); + + return false; + }, + + get: function (what, callback) { + $.ajax({ + url: NETDATA.alarms.server + '/api/v1/alarms?' + what.toString(), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/alarms', data /*, '.*\.(calc|calc_parsed|warn|warn_parsed|crit|crit_parsed)$' */); + + if (NETDATA.alarms.first_notification_id === 0 && typeof data.latest_alarm_log_unique_id === 'number') { + NETDATA.alarms.first_notification_id = data.latest_alarm_log_unique_id; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(415, NETDATA.alarms.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + update_forever: function () { + if (netdataShowAlarms !== true || netdataSnapshotData !== null) { + return; + } + + NETDATA.alarms.get('active', function (data) { + if (data !== null) { + NETDATA.alarms.current = data; + + if (NETDATA.alarms.check_notifications()) { + NETDATA.alarms.notifyAll(); + } + + if (typeof NETDATA.alarms.callback === 'function') { + NETDATA.alarms.callback(data); + } + + // Health monitoring is disabled on this netdata + if (data.status === false) { + return; + } + } + + setTimeout(NETDATA.alarms.update_forever, NETDATA.alarms.update_every); + }); + }, + + get_log: function (last_id, callback) { + // console.log('fetching all log after ' + last_id.toString()); + $.ajax({ + url: NETDATA.alarms.server + '/api/v1/alarm_log?after=' + last_id.toString(), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/alarm_log', data); + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(416, NETDATA.alarms.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + init: function () { + NETDATA.alarms.server = NETDATA.fixHost(NETDATA.serverDefault); + + if (typeof netdataAlarmsRemember === 'undefined' || netdataAlarmsRemember) { + NETDATA.alarms.last_notification_id = + NETDATA.localStorageGet('last_notification_id', NETDATA.alarms.last_notification_id, null); + } + + if (NETDATA.alarms.onclick === null) { + NETDATA.alarms.onclick = NETDATA.alarms.scrollToAlarm; + } + + if (typeof netdataAlarmsRecipients !== 'undefined' && Array.isArray(netdataAlarmsRecipients)) { + NETDATA.alarms.recipients = netdataAlarmsRecipients; + } + + if (netdataShowAlarms) { + NETDATA.alarms.update_forever(); + + if ('Notification' in window) { + // console.log('notifications available'); + NETDATA.alarms.notifications = true; + + if (Notification.permission === 'default') { + Notification.requestPermission(); + } + } + } + } +}; + +// Registry of netdata hosts + +NETDATA.registry = { + server: null, // the netdata registry server + isCloudEnabled: false,// is netdata.cloud functionality enabled? + cloudBaseURL: null, // the netdata cloud base url + person_guid: null, // the unique ID of this browser / user + machine_guid: null, // the unique ID the netdata server that served dashboard.js + hostname: 'unknown', // the hostname of the netdata server that served dashboard.js + machines: null, // the user's other URLs + machines_array: null, // the user's other URLs in an array + person_urls: null, + + MASKED_DATA: "***", + + isUsingGlobalRegistry: function() { + return NETDATA.registry.server == "https://registry.my-netdata.io"; + }, + + isRegistryEnabled: function() { + return !(NETDATA.registry.isUsingGlobalRegistry() || isSignedIn()) + }, + + parsePersonUrls: function (person_urls) { + NETDATA.registry.person_urls = person_urls; + + if (person_urls) { + NETDATA.registry.machines = {}; + NETDATA.registry.machines_array = []; + + let apu = person_urls; + let i = apu.length; + while (i--) { + if (typeof NETDATA.registry.machines[apu[i][0]] === 'undefined') { + // console.log('adding: ' + apu[i][4] + ', ' + ((now - apu[i][2]) / 1000).toString()); + + let obj = { + guid: apu[i][0], + url: apu[i][1], + last_t: apu[i][2], + accesses: apu[i][3], + name: apu[i][4], + alternate_urls: [] + }; + obj.alternate_urls.push(apu[i][1]); + + NETDATA.registry.machines[apu[i][0]] = obj; + NETDATA.registry.machines_array.push(obj); + } else { + // console.log('appending: ' + apu[i][4] + ', ' + ((now - apu[i][2]) / 1000).toString()); + + let pu = NETDATA.registry.machines[apu[i][0]]; + if (pu.last_t < apu[i][2]) { + pu.url = apu[i][1]; + pu.last_t = apu[i][2]; + pu.name = apu[i][4]; + } + pu.accesses += apu[i][3]; + pu.alternate_urls.push(apu[i][1]); + } + } + } + + if (typeof netdataRegistryCallback === 'function') { + netdataRegistryCallback(NETDATA.registry.machines_array); + } + }, + + init: function () { + if (netdataRegistry !== true) { + return; + } + + NETDATA.registry.hello(NETDATA.serverDefault, function (data) { + if (data) { + NETDATA.registry.server = data.registry; + if (data.cloud_base_url != "") { + NETDATA.registry.isCloudEnabled = true; + NETDATA.registry.cloudBaseURL = data.cloud_base_url; + } else { + NETDATA.registry.isCloudEnabled = false; + NETDATA.registry.cloudBaseURL = ""; + } + NETDATA.registry.machine_guid = data.machine_guid; + NETDATA.registry.hostname = data.hostname; + if (dataLayer) { + if (data.anonymous_statistics) dataLayer.push({"anonymous_statistics" : "true", "machine_guid" : data.machine_guid}); + } + NETDATA.registry.access(2, function (person_urls) { + NETDATA.registry.parsePersonUrls(person_urls); + }); + } + }); + }, + + hello: function (host, callback) { + host = NETDATA.fixHost(host); + + // send HELLO to a netdata server: + // 1. verifies the server is reachable + // 2. responds with the registry URL, the machine GUID of this netdata server and its hostname + $.ajax({ + url: host + '/api/v1/registry?action=hello', + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/registry?action=hello', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(408, host + ' response: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(407, host); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + access: function (max_redirects, callback) { + let name = NETDATA.registry.MASKED_DATA; + let url = NETDATA.registry.MASKED_DATA; + + if (!NETDATA.registry.isUsingGlobalRegistry()) { + // If the user is using a private registry keep sending identifiable + // data. + name = NETDATA.registry.hostname; + url = NETDATA.serverDefault; + } + + console.log("ACCESS", name, url); + + // send ACCESS to a netdata registry: + // 1. it lets it know we are accessing a netdata server (its machine GUID and its URL) + // 2. it responds with a list of netdata servers we know + // the registry identifies us using a cookie it sets the first time we access it + // the registry may respond with a redirect URL to send us to another registry + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=access&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(name) + '&url=' + encodeURIComponent(url), // + '&visible_url=' + encodeURIComponent(document.location), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=access', data); + + let redirect = null; + if (typeof data.registry === 'string') { + redirect = data.registry; + } + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(409, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (data === null) { + if (redirect !== null && max_redirects > 0) { + NETDATA.registry.server = redirect; + NETDATA.registry.access(max_redirects - 1, callback); + } + else { + if (typeof callback === 'function') { + return callback(null); + } + } + } else { + if (typeof data.person_guid === 'string') { + NETDATA.registry.person_guid = data.person_guid; + } + + if (typeof callback === 'function') { + const urls = data.urls.filter((u) => u[1] !== NETDATA.registry.MASKED_DATA); + return callback(urls); + } + } + }) + .fail(function () { + NETDATA.error(410, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + delete: function (delete_url, callback) { + // send DELETE to a netdata registry: + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=delete&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&delete_url=' + encodeURIComponent(delete_url), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=delete', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(411, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(412, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + search: function (machine_guid, callback) { + // SEARCH for the URLs of a machine: + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=search&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&for=' + machine_guid, + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=search', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(417, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(418, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + switch: function (new_person_guid, callback) { + // impersonate + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=switch&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&to=' + new_person_guid, + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=switch', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(413, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(414, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + } +}; + +// Load required JS libraries and CSS + +NETDATA.requiredJs = [ + { + url: NETDATA.serverStatic + 'lib/bootstrap-3.3.7.min.js', + async: false, + isAlreadyLoaded: function () { + // check if bootstrap is loaded + if (typeof $().emulateTransitionEnd === 'function') { + return true; + } else { + return typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap; + } + } + }, + { + url: NETDATA.serverStatic + 'lib/fontawesome-all-5.0.1.min.js', + async: true, + isAlreadyLoaded: function () { + return typeof netdataNoFontAwesome !== 'undefined' && netdataNoFontAwesome; + } + }, + { + url: NETDATA.serverStatic + 'lib/perfect-scrollbar-0.6.15.min.js', + isAlreadyLoaded: function () { + return false; + } + } +]; + +NETDATA.requiredCSS = [ + { + url: NETDATA.themes.current.bootstrap_css, + isAlreadyLoaded: function () { + return typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap; + } + }, + { + url: NETDATA.themes.current.dashboard_css, + isAlreadyLoaded: function () { + return false; + } + } +]; + +NETDATA.loadedRequiredJs = 0; +NETDATA.loadRequiredJs = function (index, callback) { + if (index >= NETDATA.requiredJs.length) { + if (typeof callback === 'function') { + return callback(); + } + return; + } + + if (NETDATA.requiredJs[index].isAlreadyLoaded()) { + NETDATA.loadedRequiredJs++; + NETDATA.loadRequiredJs(++index, callback); + return; + } + + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.requiredJs[index].url); + } + + let async = true; + if (typeof NETDATA.requiredJs[index].async !== 'undefined' && NETDATA.requiredJs[index].async === false) { + async = false; + } + + $.ajax({ + url: NETDATA.requiredJs[index].url, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + if (NETDATA.options.debug.main_loop) { + console.log('loaded ' + NETDATA.requiredJs[index].url); + } + }) + .fail(function () { + alert('Cannot load required JS library: ' + NETDATA.requiredJs[index].url); + }) + .always(function () { + NETDATA.loadedRequiredJs++; + + // if (async === false) + if (!async) { + NETDATA.loadRequiredJs(++index, callback); + } + }); + + // if (async === true) + if (async) { + NETDATA.loadRequiredJs(++index, callback); + } +}; + +NETDATA.loadRequiredCSS = function (index) { + if (index >= NETDATA.requiredCSS.length) { + return; + } + + if (NETDATA.requiredCSS[index].isAlreadyLoaded()) { + NETDATA.loadRequiredCSS(++index); + return; + } + + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.requiredCSS[index].url); + } + + NETDATA._loadCSS(NETDATA.requiredCSS[index].url); + NETDATA.loadRequiredCSS(++index); +}; + +// Boot it! + +if (typeof netdataPrepCallback === 'function') { + netdataPrepCallback(); +} + +NETDATA.errorReset(); +NETDATA.loadRequiredCSS(0); + +NETDATA._loadjQuery(function () { + NETDATA.loadRequiredJs(0, function () { + if (typeof $().emulateTransitionEnd !== 'function') { + // bootstrap is not available + NETDATA.options.current.show_help = false; + } + + if (typeof netdataDontStart === 'undefined' || !netdataDontStart) { + if (NETDATA.options.debug.main_loop) { + console.log('starting chart refresh thread'); + } + + NETDATA.start(); + } + }); +}); +})(window, document, (typeof jQuery === 'function')?jQuery:undefined); diff --git a/web/gui/dashboard.slate.css b/web/gui/dashboard.slate.css new file mode 100644 index 0000000..f1c9c41 --- /dev/null +++ b/web/gui/dashboard.slate.css @@ -0,0 +1,757 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +html, +body { + /*font-family: Calibri,"Segoe UI","Helvetica Neue",Helvetica,Arial,sans-serif;*/ + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-style: normal; + font-variant: normal; + color: #878b90; +} + +/* fixes for default slate theme */ +code { + color: #bbb; /*#c7254e;*/ + background-color: #555; /* #f9f2f4; */ +} + +.dashboard-sidebar .nav > .active > a, +.dashboard-sidebar .nav > .active:hover > a, +.dashboard-sidebar .nav > .active:focus > a { + color: #765d9c; + border-left: 2px solid #765d9c; +} + +.morelink { + color: #765d9c; + text-decoration: none; +} + +.morelink:hover { + color: #563d7c; + text-decoration: none; +} + +.morelink:focus { + color: #765d9c; + text-decoration: none; +} + +.netdata-chart-alignment { + margin-left: 55px; +} + +.netdata-chart-row { + width: 100%; + text-align: center; + display: flex; + display: -webkit-flex; + display: -moz-flex; + align-items: flex-end; + -moz-align-items: flex-end; + -webkit-align-items: flex-end; + justify-content: center; + -moz--webkit-justify-content: center; + -moz-justify-content: center; + padding-top: 10px; +} + +.netdata-container { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-gauge { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-gauge:after { + padding-top: 60%; + display: block; + content: ''; +} + +.netdata-container-easypiechart { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-container-easypiechart:after { + padding-top: 100%; + display: block; + content: ''; +} + +.netdata-aspect { + position: relative; + width: 100%; + padding: 0px; + margin: 0px; +} + +.netdata-container-with-legend { + display: inline-block; + overflow: hidden; + + transform: translate3d(0,0,0); + + /* fix minimum scrollbar issue in firefox */ + min-height: 99px; + + /* required for child elements to have absolute position */ + position: relative; + + /* width and height is given per chart with data-width and data-height */ +} + +.netdata-legend-resize-handler { + display: block; + position: absolute; + bottom: 0px; + right: 0px; + height: 15px; + width: 20px; + background-color: #272b30; + font-size: 15px; + vertical-align: middle; + line-height: 15px; + cursor: ns-resize; + color: #373b40; + text-align: center; + overflow: hidden; + z-index: 20; + padding: 0px; + margin: 0px; +} + +.netdata-legend-toolbox { + display: block; + position: absolute; + bottom: 0px; + right: 30px; + height: 15px; + width: 110px; + background-color: #272b30; + font-size: 12px; + vertical-align: middle; + line-height: 15px; + color: #373b40; + text-align: center; + overflow: hidden; + z-index: 20; + padding: 0px; + margin: 0px; + + /* prevent text selection after double click */ + -webkit-user-select: none; /* webkit (safari, chrome) browsers */ + -moz-user-select: none; /* mozilla browsers */ + -khtml-user-select: none; /* webkit (konqueror) browsers */ + -ms-user-select: none; /* IE10+ */ +} + +.netdata-legend-toolbox-button { + display: inline-block; + position: relative; + height: 15px; + width: 18px; + background-color: #272b30; + font-size: 12px; + vertical-align: middle; + line-height: 15px; + color: #474b50; + text-align: center; + overflow: hidden; + z-index: 21; + padding: 0px; + margin: 0px; + cursor: pointer; + + /* prevent text selection after double click */ + -webkit-user-select: none; /* webkit (safari, chrome) browsers */ + -moz-user-select: none; /* mozilla browsers */ + -khtml-user-select: none; /* webkit (konqueror) browsers */ + -ms-user-select: none; /* IE10+ */ +} + +.netdata-message { + display: inline-block; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + text-align: left; + vertical-align: top; + font-weight: bold; + font-size: x-small; + overflow: hidden; + background: inherit; + z-index: 0; +} + +.netdata-message.hidden { + display: none; +} + +.netdata-message.icon { + color: #2f3338; + text-align: center; + vertical-align: middle; +} + +.netdata-chart-legend { + position: absolute; /* within .netdata-container */ + top: 0; + right: 0; + overflow: hidden; + text-overflow: ellipsis; + line-height: 14px; + display: block; + width: 140px; /* --legend-width */ + height: calc(100% - 15px); /* 10px for the resize handler and 5px for the top margin */ + font-size: 10px; + margin-top: 5px; + text-align: left; + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-legend-title-date { + font-size: 10px; + font-weight: normal; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-title-time { + font-size: 11px; + font-weight: bold; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-title-units { + position: absolute; + right: 10px; + float: right; + font-size: 11px; + vertical-align: top; + font-weight: normal; + margin-top: 0px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.netdata-legend-series { + position: absolute; + width: 140px; /* legend-width */ + height: calc(100% - 50px); + overflow: hidden; + text-overflow: ellipsis; + line-height: 14.5px; /* line spacing at the legend */ + display: block; + font-size: 10px; + margin-top: 0px; +} + +.netdata-legend-name-table-line { + display: inline-block; + width: 13px; + height: 4px; + border-width: 0px; + border-bottom-width: 2px; + border-bottom-style: solid; + border-bottom-color: #272b30; +} + +.netdata-legend-name-table-area { + display: inline-block; + width: 13px; + height: 5px; + border-width: 1px; + border-top-width: 1px; + border-top-style: solid; + border-top-color: inherit; +} + +.netdata-legend-name-table-stacked { + display: inline-block; + width: 13px; + height: 5px; + border-width: 1px; + border-top-width: 1px; + border-top-style: solid; + border-top-color: inherit; +} + +.netdata-legend-name-tr { +} + +.netdata-legend-name-td { +} + +.netdata-legend-name { + text-align: left; + font-size: 11px; /* legend: dimension name size */ + font-weight: bold; + vertical-align: bottom; + margin-top: 0px; + z-index: 9; + padding: 0px; + width: 80px !important; + max-width: 80px !important; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + display: inline-block; + cursor: pointer; + -webkit-print-color-adjust: exact; +} + +.netdata-legend-value { + /*margin-left: 14px;*/ + position: absolute; + right: 10px; + float: right; + text-align: right; + font-size: 11px; /* legend: dimension value size */ + font-weight: bold; + vertical-align: bottom; + background-color: #272b30; + margin-top: 0px; + z-index: 10; + padding: 0px; + padding-left: 15px; + cursor: pointer; + /* -webkit-font-smoothing: none; */ +} + +.netdata-legend-name.not-selected { + font-weight: normal; + opacity: 0.3; +} + +.netdata-chart { + position: absolute; /* within .netdata-container */ + top: 0; /* within .netdata-container */ + left: 0; /* within .netdata-container */ + display: inline-block; + overflow: hidden; + width: 100%; + height: 100%; + z-index: 5; + + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-chart-with-legend-right { + position: absolute; /* within .netdata-container */ + top: 0; /* within .netdata-container */ + left: 0; /* within .netdata-container */ + display: block; + overflow: hidden; + margin-right: 140px; /* --legend-width */ + width: calc(100% - 140px); /* --legend-width */ + height: 100%; + z-index: 5; + flex-grow: 1; + + /* width and height is calculated (depends on the appearance of the legend) */ +} + +.netdata-peity-chart { + +} + +.netdata-sparkline-chart { + +} + +.netdata-dygraph-chart { + +} + +.netdata-morris-chart { + +} + +.netdata-google-chart { + +} + +.dygraph-ylabel { +} + +.dygraph-axis-label-x { + overflow-x: hidden; +} + +.dygraph-axis-label { + color: #6c7075; +} + +.dygraph-label-rotate-left { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(90deg); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -o-transform: rotate(90deg); + -ms-transform: rotate(90deg); +} + +/* For y2-axis label */ +.dygraph-label-rotate-right { + text-align: center; + /* See http://caniuse.com/#feat=transforms2d */ + transform: rotate(-90deg); + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg); +} + +.dygraph-title { + text-indent: 56px; + text-align: left; + position: absolute; + left: 0px; + top: 4px; + font-size: 11px; + font-weight: bold; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +/* fix for sparkline tooltip under bootstrap */ +.jqstooltip { + width: auto !important; + height: auto !important; +} + +.easyPieChart { + position: relative; + text-align: center; +} + +.easyPieChart canvas { + position: absolute; + top: 0; + left: 0; +} + +.easyPieChartLabel { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #BBB; + font-weight: normal; + text-shadow: #272b30 0px 0px 1px; + /* -webkit-font-smoothing: none; */ +} + +.easyPieChartTitle { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 64%; + margin-left: 18% !important; + text-align: center; + color: #676b70; + font-weight: bold; +} + +.easyPieChartUnits { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 60%; + margin-left: 20% !important; + text-align: center; + color: #676b70; + font-weight: normal; +} + +.gaugeChart { + position: relative; + text-align: center; +} + +.gaugeChart canvas { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + z-index: 0; +} + +.gaugeChartLabel { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #BBB; + font-weight: bold; + z-index: 1; + text-shadow: #272b30 0px 0px 1px; + /* text-shadow: #CCC 1px 1px 0px, #CCC -1px -1px 0px, #CCC 1px -1px 0px, #CCC -1px 1px 0px; */ + /* -webkit-text-stroke: 1px #777; */ + /* -webkit-font-smoothing: none; */ +} + +.gaugeChartTitle { + display: inline-block; + position: absolute; + float: left; + left: 0; + width: 100%; + text-align: center; + color: #676b70; + font-weight: bold; +} + +.gaugeChartUnits { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 0; + width: 100%; + text-align: left; + margin-left: 5%; + color: #676b70; + font-weight: normal; +} + +.gaugeChartMin { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 8%; + width: 92%; + margin-left: 8%; + text-align: left; + color: #676b70; + font-weight: normal; +} + +.gaugeChartMax { + display: inline-block; + position: absolute; + float: left; + left: 0; + bottom: 8%; + width: 95%; + margin-right: 5%; + text-align: right; + color: #676b70; + font-weight: normal; +} + +.popover-title { + font-weight: bold; + font-size: 12px; +} + +.popover-content { + font-size: 11px; +} + +/* ---------------------------------------------------------------------------- + perfect-scrollbar settings + */ + +.ps-container { + -ms-touch-action: auto; + touch-action: auto; + overflow: hidden !important; + -ms-overflow-style: none; +} + +@supports (-ms-overflow-style: none) { + .ps-container { + overflow: auto !important; + } +} + +@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { + .ps-container { + overflow: auto !important; + } +} + +.ps-container.ps-active-x > .ps-scrollbar-x-rail, +.ps-container.ps-active-y > .ps-scrollbar-y-rail { + display: block; + background-color: transparent; +} + +.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { + background-color: transparent; /* background color when dragged away */ + opacity: 0.9; +} + +.ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { + background-color: #aaa; /* scrollbar color when dragged away */ + height: 5px; +} + +.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { + background-color: transparent; /* background color when dragged away */ + opacity: 0.9; +} + +.ps-container.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { + background-color: #aaa; /* scrollbar color when dragged away */ + width: 5px; +} + +.ps-container > .ps-scrollbar-x-rail { + display: none; + position: absolute; + /* please don't change 'position' */ + opacity: 0.2; /* the opacity when not on hover of the content */ + -webkit-transition: background-color .2s linear, opacity .2s linear; + -o-transition: background-color .2s linear, opacity .2s linear; + -moz-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + bottom: 0px; + /* there must be 'bottom' for ps-scrollbar-x-rail */ + height: 15px; +} + +.ps-container > .ps-scrollbar-x-rail > .ps-scrollbar-x { + position: absolute; + /* please don't change 'position' */ + background-color: #666; /* #aaa; the color on content hover */ + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + bottom: 2px; + /* there must be 'bottom' for ps-scrollbar-x */ + height: 5px; /* the width of the scrollbar */ +} + +.ps-container > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x, .ps-container > .ps-scrollbar-x-rail:active > .ps-scrollbar-x { + height: 5px; +} + +.ps-container > .ps-scrollbar-y-rail { + display: none; + position: absolute; + /* please don't change 'position' */ + opacity: 0.2; /* the opacity when not on hover of the content */ + -webkit-transition: background-color .2s linear, opacity .2s linear; + -o-transition: background-color .2s linear, opacity .2s linear; + -moz-transition: background-color .2s linear, opacity .2s linear; + transition: background-color .2s linear, opacity .2s linear; + right: 0; + /* there must be 'right' for ps-scrollbar-y-rail */ + width: 15px; +} + +.ps-container > .ps-scrollbar-y-rail > .ps-scrollbar-y { + position: absolute; + /* please don't change 'position' */ + background-color: #666; /* #aaa; the color on content hover */ + -webkit-border-radius: 6px; + -moz-border-radius: 6px; + border-radius: 6px; + -webkit-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, -webkit-border-radius .2s ease-in-out; + -o-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + -moz-transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out; + transition: background-color .2s linear, height .2s linear, width .2s ease-in-out, border-radius .2s ease-in-out, -webkit-border-radius .2s ease-in-out, -moz-border-radius .2s ease-in-out; + right: 2px; + /* there must be 'right' for ps-scrollbar-y */ + width: 5px; /* the width of the scrollbar */ +} + +.ps-container > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y, .ps-container > .ps-scrollbar-y-rail:active > .ps-scrollbar-y { + width: 5px; +} + +.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail { + background-color: transparent; /* background color when dragged */ + opacity: 0.9; +} + +.ps-container:hover.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail > .ps-scrollbar-x { + background-color: #bbb; /* scrollbar color when dragged */ + height: 5px; +} + +.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail { + background-color: transparent; /* background color when dragged */ + opacity: 0.9; +} + +.ps-container:hover.ps-in-scrolling.ps-y > .ps-scrollbar-y-rail > .ps-scrollbar-y { + background-color: #bbb; /* scrollbar color when dragged */ + width: 5px; +} + +.ps-container:hover > .ps-scrollbar-x-rail, +.ps-container:hover > .ps-scrollbar-y-rail { + opacity: 0.6; +} + +.ps-container:hover > .ps-scrollbar-x-rail:hover { + background-color: transparent; /* the background color on hover of the scrollbar */ + opacity: 0.9; +} + +.ps-container:hover > .ps-scrollbar-x-rail:hover > .ps-scrollbar-x { + background-color: #999; /* scrollbar color on hover */ +} + +.ps-container:hover > .ps-scrollbar-y-rail:hover { + background-color: transparent; /* the background color on hover of the scrollbar */ + opacity: 0.9; +} + +.ps-container:hover > .ps-scrollbar-y-rail:hover > .ps-scrollbar-y { + background-color: #999; /* scrollbar color on hover */ +} diff --git a/web/gui/dashboard_info.js b/web/gui/dashboard_info.js new file mode 100644 index 0000000..00cac63 --- /dev/null +++ b/web/gui/dashboard_info.js @@ -0,0 +1,2343 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +// Codacy declarations +/* global NETDATA */ + +var netdataDashboard = window.netdataDashboard || {}; + +// Informational content for the various sections of the GUI (menus, sections, charts, etc.) + +// ---------------------------------------------------------------------------- +// Menus + +netdataDashboard.menu = { + 'system': { + title: 'System Overview', + icon: '<i class="fas fa-bookmark"></i>', + info: 'Overview of the key system metrics.' + }, + + 'services': { + title: 'systemd Services', + icon: '<i class="fas fa-cogs"></i>', + info: 'Resources utilization of systemd services. netdata monitors all systemd services via CGROUPS ' + + '(the resources accounting used by containers). ' + }, + + 'ap': { + title: 'Access Points', + icon: '<i class="fas fa-wifi"></i>', + info: 'Performance metrics for the access points (i.e. wireless interfaces in AP mode) found on the system.' + }, + + 'tc': { + title: 'Quality of Service', + icon: '<i class="fas fa-globe"></i>', + info: 'Netdata collects and visualizes <code>tc</code> class utilization using its ' + + '<a href="https://github.com/netdata/netdata/blob/master/collectors/tc.plugin/tc-qos-helper.sh.in" target="_blank">tc-helper plugin</a>. ' + + 'If you also use <a href="http://firehol.org/#fireqos" target="_blank">FireQOS</a> for setting up QoS, ' + + 'netdata automatically collects interface and class names. If your QoS configuration includes overheads ' + + 'calculation, the values shown here will include these overheads (the total bandwidth for the same ' + + 'interface as reported in the Network Interfaces section, will be lower than the total bandwidth ' + + 'reported here). QoS data collection may have a slight time difference compared to the interface ' + + '(QoS data collection uses a BASH script, so a shift in data collection of a few milliseconds ' + + 'should be justified).' + }, + + 'net': { + title: 'Network Interfaces', + icon: '<i class="fas fa-sitemap"></i>', + info: 'Performance metrics for network interfaces.' + }, + + 'ip': { + title: 'Networking Stack', + icon: '<i class="fas fa-cloud"></i>', + info: function (os) { + if(os === "linux") + return 'Metrics for the networking stack of the system. These metrics are collected from <code>/proc/net/netstat</code>, apply to both IPv4 and IPv6 traffic and are related to operation of the kernel networking stack.'; + else + return 'Metrics for the networking stack of the system.'; + } + }, + + 'ipv4': { + title: 'IPv4 Networking', + icon: '<i class="fas fa-cloud"></i>', + info: 'Metrics for the IPv4 stack of the system. ' + + '<a href="https://en.wikipedia.org/wiki/IPv4" target="_blank">Internet Protocol version 4 (IPv4)</a> is ' + + 'the fourth version of the Internet Protocol (IP). It is one of the core protocols of standards-based ' + + 'internetworking methods in the Internet. IPv4 is a connectionless protocol for use on packet-switched ' + + 'networks. It operates on a best effort delivery model, in that it does not guarantee delivery, nor does ' + + 'it assure proper sequencing or avoidance of duplicate delivery. These aspects, including data integrity, ' + + 'are addressed by an upper layer transport protocol, such as the Transmission Control Protocol (TCP).' + }, + + 'ipv6': { + title: 'IPv6 Networking', + icon: '<i class="fas fa-cloud"></i>', + info: 'Metrics for the IPv6 stack of the system. <a href="https://en.wikipedia.org/wiki/IPv6" target="_blank">Internet Protocol version 6 (IPv6)</a> is the most recent version of the Internet Protocol (IP), the communications protocol that provides an identification and location system for computers on networks and routes traffic across the Internet. IPv6 was developed by the Internet Engineering Task Force (IETF) to deal with the long-anticipated problem of IPv4 address exhaustion. IPv6 is intended to replace IPv4.' + }, + + 'sctp': { + title: 'SCTP Networking', + icon: '<i class="fas fa-cloud"></i>', + info: '<a href="https://en.wikipedia.org/wiki/Stream_Control_Transmission_Protocol" target="_blank">Stream Control Transmission Protocol (SCTP)</a> is a computer network protocol which operates at the transport layer and serves a role similar to the popular protocols TCP and UDP. SCTP provides some of the features of both UDP and TCP: it is message-oriented like UDP and ensures reliable, in-sequence transport of messages with congestion control like TCP. It differs from those protocols by providing multi-homing and redundant paths to increase resilience and reliability.' + }, + + 'ipvs': { + title: 'IP Virtual Server', + icon: '<i class="fas fa-eye"></i>', + info: '<a href="http://www.linuxvirtualserver.org/software/ipvs.html" target="_blank">IPVS (IP Virtual Server)</a> implements transport-layer load balancing inside the Linux kernel, so called Layer-4 switching. IPVS running on a host acts as a load balancer at the front of a cluster of real servers, it can direct requests for TCP/UDP based services to the real servers, and makes services of the real servers to appear as a virtual service on a single IP address.' + }, + + 'netfilter': { + title: 'Firewall (netfilter)', + icon: '<i class="fas fa-shield-alt"></i>', + info: 'Performance metrics of the netfilter components.' + }, + + 'ipfw': { + title: 'Firewall (ipfw)', + icon: '<i class="fas fa-shield-alt"></i>', + info: 'Counters and memory usage for the ipfw rules.' + }, + + 'cpu': { + title: 'CPUs', + icon: '<i class="fas fa-bolt"></i>', + info: 'Detailed information for each CPU of the system. A summary of the system for all CPUs can be found at the <a href="#menu_system">System Overview</a> section.' + }, + + 'mem': { + title: 'Memory', + icon: '<i class="fas fa-microchip"></i>', + info: 'Detailed information about the memory management of the system.' + }, + + 'disk': { + title: 'Disks', + icon: '<i class="fas fa-hdd"></i>', + info: 'Charts with performance information for all the system disks. Special care has been given to present disk performance metrics in a way compatible with <code>iostat -x</code>. netdata by default prevents rendering performance charts for individual partitions and unmounted virtual disks. Disabled charts can still be enabled by configuring the relative settings in the netdata configuration file.' + }, + + 'sensors': { + title: 'Sensors', + icon: '<i class="fas fa-leaf"></i>', + info: 'Readings of the configured system sensors.' + }, + + 'ipmi': { + title: 'IPMI', + icon: '<i class="fas fa-leaf"></i>', + info: 'The Intelligent Platform Management Interface (IPMI) is a set of computer interface specifications for an autonomous computer subsystem that provides management and monitoring capabilities independently of the host system\'s CPU, firmware (BIOS or UEFI) and operating system.' + }, + + 'samba': { + title: 'Samba', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Performance metrics of the Samba file share operations of this system. Samba is a implementation of Windows services, including Windows SMB protocol file shares.' + }, + + 'nfsd': { + title: 'NFS Server', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Performance metrics of the Network File Server. NFS is a distributed file system protocol, allowing a user on a client computer to access files over a network, much like local storage is accessed. NFS, like many other protocols, builds on the Open Network Computing Remote Procedure Call (ONC RPC) system. The NFS is an open standard defined in Request for Comments (RFC).' + }, + + 'nfs': { + title: 'NFS Client', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Performance metrics of the NFS operations of this system, acting as an NFS client.' + }, + + 'zfs': { + title: 'ZFS filesystem', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Performance metrics of the ZFS filesystem. The following charts visualize all metrics reported by <a href="https://github.com/zfsonlinux/zfs/blob/master/cmd/arcstat/arcstat.py" target="_blank">arcstat.py</a> and <a href="https://github.com/zfsonlinux/zfs/blob/master/cmd/arc_summary/arc_summary.py" target="_blank">arc_summary.py</a>.' + }, + + 'btrfs': { + title: 'BTRFS filesystem', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Disk space metrics for the BTRFS filesystem.' + }, + + 'apps': { + title: 'Applications', + icon: '<i class="fas fa-heartbeat"></i>', + info: 'Per application statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through all processes and aggregates statistics for applications of interest, defined in <code>/etc/netdata/apps_groups.conf</code>, which can be edited by running <code>$ /etc/netdata/edit-config apps_groups.conf</code> (the default is <a href="https://github.com/netdata/netdata/blob/master/collectors/apps.plugin/apps_groups.conf" target="_blank">here</a>). The plugin internally builds a process tree (much like <code>ps fax</code> does), and groups processes together (evaluating both child and parent processes) so that the result is always a chart with a predefined set of dimensions (of course, only application groups found running are reported). The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'users': { + title: 'Users', + icon: '<i class="fas fa-user"></i>', + info: 'Per user statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through all processes and aggregates statistics per user. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'groups': { + title: 'User Groups', + icon: '<i class="fas fa-users"></i>', + info: 'Per user group statistics are collected using netdata\'s <code>apps.plugin</code>. This plugin walks through all processes and aggregates statistics per user group. The reported values are compatible with <code>top</code>, although the netdata plugin counts also the resources of exited children (unlike <code>top</code> which shows only the resources of the currently running processes). So for processes like shell scripts, the reported values include the resources used by the commands these scripts run within each timeframe.', + height: 1.5 + }, + + 'netdata': { + title: 'Netdata Monitoring', + icon: '<i class="fas fa-chart-bar"></i>', + info: 'Performance metrics for the operation of netdata itself and its plugins.' + }, + + 'example': { + title: 'Example Charts', + info: 'Example charts, demonstrating the external plugin architecture.' + }, + + 'cgroup': { + title: '', + icon: '<i class="fas fa-th"></i>', + info: 'Container resource utilization metrics. Netdata reads this information from <b>cgroups</b> (abbreviated from <b>control groups</b>), a Linux kernel feature that limits and accounts resource usage (CPU, memory, disk I/O, network, etc.) of a collection of processes. <b>cgroups</b> together with <b>namespaces</b> (that offer isolation between processes) provide what we usually call: <b>containers</b>.' + }, + + 'cgqemu': { + title: '', + icon: '<i class="fas fa-th-large"></i>', + info: 'QEMU virtual machine resource utilization metrics. QEMU (short for Quick Emulator) is a free and open-source hosted hypervisor that performs hardware virtualization.' + }, + + 'fping': { + title: 'fping', + icon: '<i class="fas fa-exchange-alt"></i>', + info: 'Network latency statistics, via <b>fping</b>. <b>fping</b> is a program to send ICMP echo probes to network hosts, similar to <code>ping</code>, but much better performing when pinging multiple hosts. fping versions after 3.15 can be directly used as netdata plugins.' + }, + + 'httpcheck': { + title: 'Http Check', + icon: '<i class="fas fa-heartbeat"></i>', + info: 'Web Service availability and latency monitoring using HTTP checks. This plugin is a specialized version of the port check plugin.' + }, + + 'memcached': { + title: 'memcached', + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b>memcached</b>. Memcached is a general-purpose distributed memory caching system. It is often used to speed up dynamic database-driven websites by caching data and objects in RAM to reduce the number of times an external data source (such as a database or API) must be read.' + }, + + 'monit': { + title: 'monit', + icon: '<i class="fas fa-database"></i>', + info: 'Statuses of checks in <b>monit</b>. Monit is a utility for managing and monitoring processes, programs, files, directories and filesystems on a Unix system. Monit conducts automatic maintenance and repair and can execute meaningful causal actions in error situations.' + }, + + 'mysql': { + title: 'MySQL', + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b>mysql</b>, the open-source relational database management system (RDBMS).' + }, + + 'postgres': { + title: 'Postgres', + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b>PostgresSQL</b>, the object-relational database (ORDBMS).' + }, + + 'redis': { + title: 'Redis', + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b>redis</b>. Redis (REmote DIctionary Server) is a software project that implements data structure servers. It is open-source, networked, in-memory, and stores keys with optional durability.' + }, + + 'rethinkdbs': { + title: 'RethinkDB', + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b>rethinkdb</b>. RethinkDB is the first open-source scalable database built for realtime applications' + }, + + 'retroshare': { + title: 'RetroShare', + icon: '<i class="fas fa-share-alt"></i>', + info: 'Performance metrics for <b>RetroShare</b>. RetroShare is open source software for encrypted filesharing, serverless email, instant messaging, online chat, and BBS, based on a friend-to-friend network built on GNU Privacy Guard (GPG).' + }, + + 'ipfs': { + title: 'IPFS', + icon: '<i class="fas fa-folder-open"></i>', + info: 'Performance metrics for the InterPlanetary File System (IPFS), a content-addressable, peer-to-peer hypermedia distribution protocol.' + }, + + 'phpfpm': { + title: 'PHP-FPM', + icon: '<i class="fas fa-eye"></i>', + info: 'Performance metrics for <b>PHP-FPM</b>, an alternative FastCGI implementation for PHP.' + }, + + 'portcheck': { + title: 'Port Check', + icon: '<i class="fas fa-heartbeat"></i>', + info: 'Service availability and latency monitoring using port checks.' + }, + + 'postfix': { + title: 'postfix', + icon: '<i class="fas fa-envelope"></i>', + info: undefined + }, + + 'dovecot': { + title: 'Dovecot', + icon: '<i class="fas fa-envelope"></i>', + info: undefined + }, + + 'hddtemp': { + title: 'HDD Temp', + icon: '<i class="fas fa-thermometer-half"></i>', + info: undefined + }, + + 'nginx': { + title: 'nginx', + icon: '<i class="fas fa-eye"></i>', + info: undefined + }, + + 'apache': { + title: 'Apache', + icon: '<i class="fas fa-eye"></i>', + info: undefined + }, + + 'lighttpd': { + title: 'Lighttpd', + icon: '<i class="fas fa-eye"></i>', + info: undefined + }, + + 'web_log': { + title: undefined, + icon: '<i class="fas fa-file-alt"></i>', + info: 'Information extracted from a server log file. <code>web_log</code> plugin incrementally parses the server log file to provide, in real-time, a break down of key server performance metrics. For web servers, an extended log file format may optionally be used (for <code>nginx</code> and <code>apache</code>) offering timing information and bandwidth for both requests and responses. <code>web_log</code> plugin may also be configured to provide a break down of requests per URL pattern (check <a href="https://github.com/netdata/netdata/blob/master/conf.d/python.d/web_log.conf" target="_blank"><code>/etc/netdata/python.d/web_log.conf</code></a>).' + }, + + 'named': { + title: 'named', + icon: '<i class="fas fa-tag"></i>', + info: undefined + }, + + 'squid': { + title: 'squid', + icon: '<i class="fas fa-exchange-alt"></i>', + info: undefined + }, + + 'nut': { + title: 'UPS', + icon: '<i class="fas fa-battery-half"></i>', + info: undefined + }, + + 'apcupsd': { + title: 'UPS', + icon: '<i class="fas fa-battery-half"></i>', + info: undefined + }, + + 'smawebbox': { + title: 'Solar Power', + icon: '<i class="fas fa-sun"></i>', + info: undefined + }, + + 'fronius': { + title: 'Fronius', + icon: '<i class="fas fa-sun"></i>', + info: undefined + }, + + 'stiebeleltron': { + title: 'Stiebel Eltron', + icon: '<i class="fas fa-thermometer-half"></i>', + info: undefined + }, + + 'snmp': { + title: 'SNMP', + icon: '<i class="fas fa-random"></i>', + info: undefined + }, + + 'go_expvar': { + title: 'Go - expvars', + icon: '<i class="fas fa-eye"></i>', + info: 'Statistics about running Go applications exposed by the <a href="https://golang.org/pkg/expvar/" target="_blank">expvar package</a>.' + }, + + 'chrony': { + icon: '<i class="fas fa-clock"></i>', + info: 'chronyd parameters about the system’s clock performance.' + }, + + 'couchdb': { + icon: '<i class="fas fa-database"></i>', + info: 'Performance metrics for <b><a href="https://couchdb.apache.org/">CouchDB</a></b>, the open-source, JSON document-based database with an HTTP API and multi-master replication.' + }, + + 'beanstalk': { + title: 'Beanstalkd', + icon: '<i class="fas fa-tasks"></i>', + info: 'Provides statistics on the <b><a href="http://kr.github.io/beanstalkd/">beanstalkd</a></b> server and any tubes available on that server using data pulled from beanstalkc' + }, + + 'rabbitmq': { + title: 'RabbitMQ', + icon: '<i class="fas fa-comments"></i>', + info: 'Performance data for the <b><a href="https://www.rabbitmq.com/">RabbitMQ</a></b> open-source message broker.' + }, + + 'ceph': { + title: 'Ceph', + icon: '<i class="fas fa-database"></i>', + info: 'Provides statistics on the <b><a href="http://ceph.com/">ceph</a></b> cluster server, the open-source distributed storage system.' + }, + + 'ntpd': { + title: 'ntpd', + icon: '<i class="fas fa-clock"></i>', + info: 'Provides statistics for the internal variables of the Network Time Protocol daemon <b><a href="http://www.ntp.org/">ntpd</a></b> and optional including the configured peers (if enabled in the module configuration). The module presents the performance metrics as shown by <b><a href="http://doc.ntp.org/current-stable/ntpq.html">ntpq</a></b> (the standard NTP query program) using NTP mode 6 UDP packets to communicate with the NTP server.' + }, + + 'spigotmc': { + title: 'Spigot MC', + icon: '<i class="fas fa-eye"></i>', + info: 'Provides basic performance statistics for the <b><a href="https://www.spigotmc.org/">Spigot Minecraft</a></b> server.' + }, + + 'unbound': { + title: 'Unbound', + icon: '<i class="fas fa-tag"></i>', + info: undefined + }, + + 'boinc': { + title: 'BOINC', + icon: '<i class="fas fa-microchip"></i>', + info: 'Provides task counts for <b><a href="http://boinc.berkeley.edu/">BOINC</a></b> distributed computing clients.' + }, + + 'w1sensor': { + title: '1-Wire Sensors', + icon: '<i class="fas fa-thermometer-half"></i>', + info: 'Data derived from <a href="https://en.wikipedia.org/wiki/1-Wire">1-Wire</a> sensors. Currently temperature sensors are automatically detected.' + }, + + 'logind': { + title: 'Logind', + icon: '<i class="fas fa-user"></i>', + info: undefined + }, + + 'powersupply': { + title: 'Power Supply', + icon: '<i class="fas fa-battery-half"></i>', + info: 'Statistics for the various system power supplies. Data collected from <a href="https://www.kernel.org/doc/Documentation/power/power_supply_class.txt">Linux power supply class</a>.' + } +}; + + +// ---------------------------------------------------------------------------- +// submenus + +// information to be shown, just below each submenu + +// information about the submenus +netdataDashboard.submenu = { + 'web_log.squid_bandwidth': { + title: 'bandwidth', + info: 'Bandwidth of responses (<code>sent</code>) by squid. This chart may present unusual spikes, since the bandwidth is accounted at the time the log line is saved by the server, even if the time needed to serve it spans across a longer duration. We suggest to use QoS (e.g. <a href="http://firehol.org/#fireqos" target="_blank">FireQOS</a>) for accurate accounting of the server bandwidth.' + }, + + 'web_log.squid_responses': { + title: 'responses', + info: 'Information related to the responses sent by squid.' + }, + + 'web_log.squid_requests': { + title: 'requests', + info: 'Information related to the requests squid has received.' + }, + + 'web_log.squid_hierarchy': { + title: 'hierarchy', + info: 'Performance metrics for the squid hierarchy used to serve the requests.' + }, + + 'web_log.squid_squid_transport': { + title: 'transport' + }, + + 'web_log.squid_squid_cache': { + title: 'cache', + info: 'Performance metrics for the performance of the squid cache.' + }, + + 'web_log.squid_timings': { + title: 'timings', + info: 'Duration of squid requests. Unrealistic spikes may be reported, since squid logs the total time of the requests, when they complete. Especially for HTTPS, the clients get a tunnel from the proxy and exchange requests directly with the upstream servers, so squid cannot evaluate the individual requests and reports the total time the tunnel was open.' + }, + + 'web_log.squid_clients': { + title: 'clients' + }, + + 'web_log.bandwidth': { + info: 'Bandwidth of requests (<code>received</code>) and responses (<code>sent</code>). <code>received</code> requires an extended log format (without it, the web server log does not have this information). This chart may present unusual spikes, since the bandwidth is accounted at the time the log line is saved by the web server, even if the time needed to serve it spans across a longer duration. We suggest to use QoS (e.g. <a href="http://firehol.org/#fireqos" target="_blank">FireQOS</a>) for accurate accounting of the web server bandwidth.' + }, + + 'web_log.urls': { + info: 'Number of requests for each <code>URL pattern</code> defined in <a href="https://github.com/netdata/netdata/blob/master/conf.d/python.d/web_log.conf" target="_blank"><code>/etc/netdata/python.d/web_log.conf</code></a>. This chart counts all requests matching the URL patterns defined, independently of the web server response codes (i.e. both successful and unsuccessful).' + }, + + 'web_log.clients': { + info: 'Charts showing the number of unique client IPs, accessing the web server.' + }, + + 'web_log.timings': { + info: 'Web server response timings - the time the web server needed to prepare and respond to requests. This requires an extended log format and its meaning is web server specific. For most web servers this accounts the time from the reception of a complete request, to the dispatch of the last byte of the response. So, it includes the network delays of responses, but it does not include the network delays of requests.' + }, + + 'mem.ksm': { + title: 'deduper (ksm)', + info: 'Kernel Same-page Merging (KSM) performance monitoring, read from several files in <code>/sys/kernel/mm/ksm/</code>. KSM is a memory-saving de-duplication feature in the Linux kernel (since version 2.6.32). The KSM daemon ksmd periodically scans those areas of user memory which have been registered with it, looking for pages of identical content which can be replaced by a single write-protected page (which is automatically copied if a process later wants to update its content). KSM was originally developed for use with KVM (where it was known as Kernel Shared Memory), to fit more virtual machines into physical memory, by sharing the data common between them. But it can be useful to any application which generates many instances of the same data.' + }, + + 'mem.hugepages': { + info: 'Hugepages is a feature that allows the kernel to utilize the multiple page size capabilities of modern hardware architectures. The kernel creates multiple pages of virtual memory, mapped from both physical RAM and swap. There is a mechanism in the CPU architecture called "Translation Lookaside Buffers" (TLB) to manage the mapping of virtual memory pages to actual physical memory addresses. The TLB is a limited hardware resource, so utilizing a large amount of physical memory with the default page size consumes the TLB and adds processing overhead. By utilizing Huge Pages, the kernel is able to create pages of much larger sizes, each page consuming a single resource in the TLB. Huge Pages are pinned to physical RAM and cannot be swapped/paged out.' + }, + + 'mem.numa': { + info: 'Non-Uniform Memory Access (NUMA) is a hierarchical memory design the memory access time is dependent on locality. Under NUMA, a processor can access its own local memory faster than non-local memory (memory local to another processor or memory shared between processors). The individual metrics are described in the <a href="https://www.kernel.org/doc/Documentation/numastat.txt" target="_blank">Linux kernel documentation</a>.' + }, + + 'ip.ecn': { + info: '<a href="https://en.wikipedia.org/wiki/Explicit_Congestion_Notification" target="_blank">Explicit Congestion Notification (ECN)</a> is a TCP extension that allows end-to-end notification of network congestion without dropping packets. ECN is an optional feature that may be used between two ECN-enabled endpoints when the underlying network infrastructure also supports it.' + }, + + 'netfilter.conntrack': { + title: 'connection tracker', + info: 'Netfilter Connection Tracker performance metrics. The connection tracker keeps track of all connections of the machine, inbound and outbound. It works by keeping a database with all open connections, tracking network and address translation and connection expectations.' + }, + + 'netfilter.nfacct': { + title: 'bandwidth accounting', + info: 'The following information is read using the <code>nfacct.plugin</code>.' + }, + + 'netfilter.synproxy': { + title: 'DDoS protection', + info: 'DDoS protection performance metrics. <a href="https://github.com/firehol/firehol/wiki/Working-with-SYNPROXY" target="_blank">SYNPROXY</a> is a TCP SYN packets proxy. It is used to protect any TCP server (like a web server) from SYN floods and similar DDoS attacks. It is a netfilter module, in the Linux kernel (since version 3.12). It is optimized to handle millions of packets per second utilizing all CPUs available without any concurrency locking between the connections. It can be used for any kind of TCP traffic (even encrypted), since it does not interfere with the content itself.' + }, + + 'ipfw.dynamic_rules': { + title: 'dynamic rules', + info: 'Number of dynamic rules, created by correspondent stateful firewall rules.' + }, + + 'system.softnet_stat': { + title: 'softnet', + info: function (os) { + if (os === 'linux') + return 'Statistics for CPUs SoftIRQs related to network receive work. Break down per CPU core can be found at <a href="#menu_cpu_submenu_softnet_stat">CPU / softnet statistics</a>. <b>processed</b> states the number of packets processed, <b>dropped</b> is the number packets dropped because the network device backlog was full (to fix them on Linux use <code>sysctl</code> to increase <code>net.core.netdev_max_backlog</code>), <b>squeezed</b> is the number of packets dropped because the network device budget ran out (to fix them on Linux use <code>sysctl</code> to increase <code>net.core.netdev_budget</code> and/or <code>net.core.netdev_budget_usecs</code>). More information about identifying and troubleshooting network driver related issues can be found at <a href="https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf" target="_blank">Red Hat Enterprise Linux Network Performance Tuning Guide</a>.'; + else + return 'Statistics for CPUs SoftIRQs related to network receive work.'; + } + }, + + 'cpu.softnet_stat': { + title: 'softnet', + info: function (os) { + if (os === 'linux') + return 'Statistics for per CPUs core SoftIRQs related to network receive work. Total for all CPU cores can be found at <a href="#menu_system_submenu_softnet_stat">System / softnet statistics</a>. <b>processed</b> states the number of packets processed, <b>dropped</b> is the number packets dropped because the network device backlog was full (to fix them on Linux use <code>sysctl</code> to increase <code>net.core.netdev_max_backlog</code>), <b>squeezed</b> is the number of packets dropped because the network device budget ran out (to fix them on Linux use <code>sysctl</code> to increase <code>net.core.netdev_budget</code> and/or <code>net.core.netdev_budget_usecs</code>). More information about identifying and troubleshooting network driver related issues can be found at <a href="https://access.redhat.com/sites/default/files/attachments/20150325_network_performance_tuning.pdf" target="_blank">Red Hat Enterprise Linux Network Performance Tuning Guide</a>.'; + else + return 'Statistics for per CPUs core SoftIRQs related to network receive work. Total for all CPU cores can be found at <a href="#menu_system_submenu_softnet_stat">System / softnet statistics</a>.'; + } + }, + + 'go_expvar.memstats': { + title: 'memory statistics', + info: 'Go runtime memory statistics. See <a href="https://golang.org/pkg/runtime/#MemStats" target="_blank">runtime.MemStats</a> documentation for more info about each chart and the values.' + }, + + 'couchdb.dbactivity': { + title: 'db activity', + info: 'Overall database reads and writes for the entire server. This includes any external HTTP traffic, as well as internal replication traffic performed in a cluster to ensure node consistency.' + }, + + 'couchdb.httptraffic': { + title: 'http traffic breakdown', + info: 'All HTTP traffic, broken down by type of request (<tt>GET</tt>, <tt>PUT</tt>, <tt>POST</tt>, etc.) and response status code (<tt>200</tt>, <tt>201</tt>, <tt>4xx</tt>, etc.)<br/><br/>Any <tt>5xx</tt> errors here indicate a likely CouchDB bug; check the logfile for further information.' + }, + + 'couchdb.ops': { + title: 'server operations' + }, + + 'couchdb.perdbstats': { + title: 'per db statistics', + info: 'Statistics per database. This includes <a href="http://docs.couchdb.org/en/latest/api/database/common.html#get--db">3 size graphs per database</a>: active (the size of live data in the database), external (the uncompressed size of the database contents), and file (the size of the file on disk, exclusive of any views and indexes). It also includes the number of documents and number of deleted documents per database.' + }, + + 'couchdb.erlang': { + title: 'erlang statistics', + info: 'Detailed information about the status of the Erlang VM that hosts CouchDB. These are intended for advanced users only. High values of the peak message queue (>10e6) generally indicate an overload condition.' + }, + + 'ntpd.system': { + title: 'system', + info: 'Statistics of the system variables as shown by the readlist billboard <code>ntpq -c rl</code>. System variables are assigned an association ID of zero and can also be shown in the readvar billboard <code>ntpq -c "rv 0"</code>. These variables are used in the <a href="http://doc.ntp.org/current-stable/discipline.html">Clock Discipline Algorithm</a>, to calculate the lowest and most stable offset.' + }, + + 'ntpd.peers': { + title: 'peers', + info: 'Statistics of the peer variables for each peer configured in <code>/etc/ntp.conf</code> as shown by the readvar billboard <code>ntpq -c "rv <association>"</code>, while each peer is assigned a nonzero association ID as shown by <code>ntpq -c "apeers"</code>. The module periodically scans for new/changed peers (default: every 60s). <b>ntpd</b> selects the best possible peer from the available peers to synchronize the clock. A minimum of at least 3 peers is required to properly identify the best possible peer.' + } +}; + + +// ---------------------------------------------------------------------------- +// chart + +// information works on the context of a chart +// Its purpose is to set: +// +// info: the text above the charts +// heads: the representation of the chart at the top the subsection (second level menu) +// mainheads: the representation of the chart at the top of the section (first level menu) +// colors: the dimension colors of the chart (the default colors are appended) +// height: the ratio of the chart height relative to the default +// +netdataDashboard.context = { + 'system.cpu': { + info: function (os) { + void(os); + return 'Total CPU utilization (all cores). 100% here means there is no CPU idle time at all. You can get per core usage at the <a href="#menu_cpu">CPUs</a> section and per application usage at the <a href="#menu_apps">Applications Monitoring</a> section.' + + netdataDashboard.sparkline('<br/>Keep an eye on <b>iowait</b> ', 'system.cpu', 'iowait', '%', '. If it is constantly high, your disks are a bottleneck and they slow your system down.') + + netdataDashboard.sparkline('<br/>An important metric worth monitoring, is <b>softirq</b> ', 'system.cpu', 'softirq', '%', '. A constantly high percentage of softirq may indicate network driver issues.'); + }, + valueRange: "[0, 100]" + }, + + 'system.load': { + info: 'Current system load, i.e. the number of processes using CPU or waiting for system resources (usually CPU and disk). The 3 metrics refer to 1, 5 and 15 minute averages. The system calculates this once every 5 seconds. For more information check <a href="https://en.wikipedia.org/wiki/Load_(computing)" target="_blank">this wikipedia article</a>', + height: 0.7 + }, + + 'system.io': { + info: function (os) { + var s = 'Total Disk I/O, for all physical disks. You can get detailed information about each disk at the <a href="#menu_disk">Disks</a> section and per application Disk usage at the <a href="#menu_apps">Applications Monitoring</a> section.'; + + if (os === 'linux') + return s + ' Physical are all the disks that are listed in <code>/sys/block</code>, but do not exist in <code>/sys/devices/virtual/block</code>.'; + else + return s; + } + }, + + 'system.pgpgio': { + info: 'Memory paged from/to disk. This is usually the total disk I/O of the system.' + }, + + 'system.swapio': { + info: 'Total Swap I/O. (netdata measures both <code>in</code> and <code>out</code>. If either of the metrics <code>in</code> or <code>out</code> is not shown in the chart, the reason is that the metric is zero. - you can change the page settings to always render all the available dimensions on all charts).' + }, + + 'system.pgfaults': { + info: 'Total page faults. <b>Major page faults</b> indicates that the system is using its swap. You can find which applications use the swap at the <a href="#menu_apps">Applications Monitoring</a> section.' + }, + + 'system.entropy': { + colors: '#CC22AA', + info: '<a href="https://en.wikipedia.org/wiki/Entropy_(computing)" target="_blank">Entropy</a>, is a pool of random numbers (<a href="https://en.wikipedia.org/wiki//dev/random" target="_blank">/dev/random</a>) that is mainly used in cryptography. If the pool of entropy gets empty, processes requiring random numbers may run a lot slower (it depends on the interface each program uses), waiting for the pool to be replenished. Ideally a system with high entropy demands should have a hardware device for that purpose (TPM is one such device). There are also several software-only options you may install, like <code>haveged</code>, although these are generally useful only in servers.' + }, + + 'system.forks': { + colors: '#5555DD', + info: 'Number of new processes created.' + }, + + 'system.intr': { + colors: '#DD5555', + info: 'Total number of CPU interrupts. Check <code>system.interrupts</code> that gives more detail about each interrupt and also the <a href="#menu_cpu">CPUs</a> section where interrupts are analyzed per CPU core.' + }, + + 'system.interrupts': { + info: 'CPU interrupts in detail. At the <a href="#menu_cpu">CPUs</a> section, interrupts are analyzed per CPU core.' + }, + + 'system.softirqs': { + info: 'CPU softirqs in detail. At the <a href="#menu_cpu">CPUs</a> section, softirqs are analyzed per CPU core.' + }, + + 'system.processes': { + info: 'System processes. <b>Running</b> are the processes in the CPU. <b>Blocked</b> are processes that are willing to enter the CPU, but they cannot, e.g. because they wait for disk activity.' + }, + + 'system.active_processes': { + info: 'All system processes.' + }, + + 'system.ctxt': { + info: '<a href="https://en.wikipedia.org/wiki/Context_switch" target="_blank">Context Switches</a>, is the switching of the CPU from one process, task or thread to another. If there are many processes or threads willing to execute and very few CPU cores available to handle them, the system is making more context switching to balance the CPU resources among them. The whole process is computationally intensive. The more the context switches, the slower the system gets.' + }, + + 'system.idlejitter': { + info: 'Idle jitter is calculated by netdata. A thread is spawned that requests to sleep for a few microseconds. When the system wakes it up, it measures how many microseconds have passed. The difference between the requested and the actual duration of the sleep, is the <b>idle jitter</b>. This number is useful in real-time environments, where CPU jitter can affect the quality of the service (like VoIP media gateways).' + }, + + 'system.net': { + info: function (os) { + var s = 'Total bandwidth of all physical network interfaces. This does not include <code>lo</code>, VPNs, network bridges, IFB devices, bond interfaces, etc. Only the bandwidth of physical network interfaces is aggregated.'; + + if (os === 'linux') + return s + ' Physical are all the network interfaces that are listed in <code>/proc/net/dev</code>, but do not exist in <code>/sys/devices/virtual/net</code>.'; + else + return s; + } + }, + + 'system.ip': { + info: 'Total IP traffic in the system.' + }, + + 'system.ipv4': { + info: 'Total IPv4 Traffic.' + }, + + 'system.ipv6': { + info: 'Total IPv6 Traffic.' + }, + + 'system.ram': { + info: 'System Random Access Memory (i.e. physical memory) usage.' + }, + + 'system.swap': { + info: 'System swap memory usage. Swap space is used when the amount of physical memory (RAM) is full. When the system needs more memory resources and the RAM is full, inactive pages in memory are moved to the swap space (usually a disk, a disk partition or a file).' + }, + + // ------------------------------------------------------------------------ + // CPU charts + + 'cpu.cpu': { + commonMin: true, + commonMax: true, + valueRange: "[0, 100]" + }, + + 'cpu.interrupts': { + commonMin: true, + commonMax: true + }, + + 'cpu.softirqs': { + commonMin: true, + commonMax: true + }, + + 'cpu.softnet_stat': { + commonMin: true, + commonMax: true + }, + + // ------------------------------------------------------------------------ + // MEMORY + + 'mem.ksm_savings': { + heads: [ + netdataDashboard.gaugeChart('Saved', '12%', 'savings', '#0099CC') + ] + }, + + 'mem.ksm_ratios': { + heads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-gauge-max-value="100"' + + ' data-chart-library="gauge"' + + ' data-title="Savings"' + + ' data-units="percentage %"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' role="application"></div>'; + } + ] + }, + + 'mem.pgfaults': { + info: 'A <a href="https://en.wikipedia.org/wiki/Page_fault" target="_blank">page fault</a> is a type of interrupt, called trap, raised by computer hardware when a running program accesses a memory page that is mapped into the virtual address space, but not actually loaded into main memory. If the page is loaded in memory at the time the fault is generated, but is not marked in the memory management unit as being loaded in memory, then it is called a <b>minor</b> or soft page fault. A <b>major</b> page fault is generated when the system needs to load the memory page from disk or swap memory.' + }, + + 'mem.committed': { + colors: NETDATA.colors[3], + info: 'Committed Memory, is the sum of all memory which has been allocated by processes.' + }, + + 'mem.available': { + info: 'Available Memory is estimated by the kernel, as the amount of RAM that can be used by userspace processes, without causing swapping.' + }, + + 'mem.writeback': { + info: '<b>Dirty</b> is the amount of memory waiting to be written to disk. <b>Writeback</b> is how much memory is actively being written to disk.' + }, + + 'mem.kernel': { + info: 'The total amount of memory being used by the kernel. <b>Slab</b> is the amount of memory used by the kernel to cache data structures for its own use. <b>KernelStack</b> is the amount of memory allocated for each task done by the kernel. <b>PageTables</b> is the amount of memory decicated to the lowest level of page tables (A page table is used to turn a virtual address into a physical memory address). <b>VmallocUsed</b> is the amount of memory being used as virtual address space.' + }, + + 'mem.slab': { + info: '<b>Reclaimable</b> is the amount of memory which the kernel can reuse. <b>Unreclaimable</b> can not be reused even when the kernel is lacking memory.' + }, + + 'mem.hugepages': { + info: 'Dedicated (or Direct) HugePages is memory reserved for applications configured to utilize huge pages. Hugepages are <b>used</b> memory, even if there are free hugepages available.' + }, + + 'mem.transparent_hugepages': { + info: 'Transparent HugePages (THP) is backing virtual memory with huge pages, supporting automatic promotion and demotion of page sizes. It works for all applications for anonymous memory mappings and tmpfs/shmem.' + }, + + // ------------------------------------------------------------------------ + // network interfaces + + 'net.drops': { + info: 'Packets that have been dropped at the network interface level. These are the same counters reported by <code>ifconfig</code> as <code>RX dropped</code> (inbound) and <code>TX dropped</code> (outbound). <b>inbound</b> packets can be dropped at the network interface level due to <a href="#menu_system_submenu_softnet_stat">softnet backlog</a> overflow, bad / unintented VLAN tags, unknown or unregistered protocols, IPv6 frames when the server is not configured for IPv6. Check <a href="https://www.novell.com/support/kb/doc.php?id=7007165" target="_blank">this document</a> for more information.' + }, + + // ------------------------------------------------------------------------ + // IP + + 'ip.inerrors': { + info: 'Errors encountered during the reception of IP packets. ' + + '<code>noroutes</code> (<code>InNoRoutes</code>) counts packets that were dropped because there was no route to send them. ' + + '<code>truncated</code> (<code>InTruncatedPkts</code>) counts packets which is being discarded because the datagram frame didn\'t carry enough data. ' + + '<code>checksum</code> (<code>InCsumErrors</code>) counts packets that were dropped because they had wrong checksum. ' + }, + + 'ip.tcpmemorypressures': { + info: 'Number of times a socket was put in <b>memory pressure</b> due to a non fatal memory allocation failure (the kernel attempts to work around this situation by reducing the send buffers, etc).' + }, + + 'ip.tcpconnaborts': { + info: 'TCP connection aborts. <b>baddata</b> (<code>TCPAbortOnData</code>) happens while the connection is on <code>FIN_WAIT1</code> and the kernel receives a packet with a sequence number beyond the last one for this connection - the kernel responds with <code>RST</code> (closes the connection). <b>userclosed</b> (<code>TCPAbortOnClose</code>) happens when the kernel receives data on an already closed connection and responds with <code>RST</code>. <b>nomemory</b> (<code>TCPAbortOnMemory</code> happens when there are too many orphaned sockets (not attached to an fd) and the kernel has to drop a connection - sometimes it will send an <code>RST</code>, sometimes it won\'t. <b>timeout</b> (<code>TCPAbortOnTimeout</code>) happens when a connection times out. <b>linger</b> (<code>TCPAbortOnLinger</code>) happens when the kernel killed a socket that was already closed by the application and lingered around for long enough. <b>failed</b> (<code>TCPAbortFailed</code>) happens when the kernel attempted to send an <code>RST</code> but failed because there was no memory available.' + }, + + 'ip.tcp_syn_queue': { + info: 'The <b>SYN queue</b> of the kernel tracks TCP handshakes until connections get fully established. ' + + 'It overflows when too many incoming TCP connection requests hang in the half-open state and the server ' + + 'is not configured to fall back to SYN cookies*. Overflows are usually caused by SYN flood DoS attacks ' + + '(i.e. someone sends lots of SYN packets and never completes the handshakes). ' + + '<b>drops</b> (or <code>TcpExtTCPReqQFullDrop</code>) is the number of connections dropped because the ' + + 'SYN queue was full and SYN cookies were disabled. ' + + '<b>cookies</b> (or <code>TcpExtTCPReqQFullDoCookies</code>) is the number of SYN cookies sent because the ' + + 'SYN queue was full.' + }, + + 'ip.tcp_accept_queue': { + info: 'The <b>accept queue</b> of the kernel holds the fully established TCP connections, waiting to be handled ' + + 'by the listening application. <b>overflows</b> (or <code>ListenOverflows</code>) is the number of ' + + 'established connections that could not be handled because the receive queue of the listening application ' + + 'was full. <b>drops</b> (or <code>ListenDrops</code>) is the number of incoming ' + + 'connections that could not be handled, including SYN floods, overflows, out of memory, security issues, ' + + 'no route to destination, reception of related ICMP messages, socket is broadcast or multicast.' + }, + + + // ------------------------------------------------------------------------ + // IPv4 + + 'ipv4.tcpsock': { + info: 'The number of established TCP connections (known as <code>CurrEstab</code>). This is a snapshot of the established connections at the time of measurement (i.e. a connection established and a connection disconnected within the same iteration will not affect this metric).' + }, + + 'ipv4.tcpopens': { + info: '<b>active</b> or <code>ActiveOpens</code> is the number of outgoing TCP <b>connections attempted</b> by this host.' + + ' <b>passive</b> or <code>PassiveOpens</code> is the number of incoming TCP <b>connections accepted</b> by this host.' + }, + + 'ipv4.tcperrors': { + info: '<code>InErrs</code> is the number of TCP segments received in error (including header too small, checksum errors, sequence errors, bad packets - for both IPv4 and IPv6).' + + ' <code>InCsumErrors</code> is the number of TCP segments received with checksum errors (for both IPv4 and IPv6).' + + ' <code>RetransSegs</code> is the number of TCP segments retransmitted.' + }, + + 'ipv4.tcphandshake': { + info: '<code>EstabResets</code> is the number of established connections resets (i.e. connections that made a direct transition from <code>ESTABLISHED</code> or <code>CLOSE_WAIT</code> to <code>CLOSED</code>).' + + ' <code>OutRsts</code> is the number of TCP segments sent, with the <code>RST</code> flag set (for both IPv4 and IPv6).' + + ' <code>AttemptFails</code> is the number of times TCP connections made a direct transition from either <code>SYN_SENT</code> or <code>SYN_RECV</code> to <code>CLOSED</code>, plus the number of times TCP connections made a direct transition from the <code>SYN_RECV</code> to <code>LISTEN</code>.' + + ' <code>TCPSynRetrans</code> shows retries for new outbound TCP connections, which can indicate general connectivity issues or backlog on the remote host.' + }, + + // ------------------------------------------------------------------------ + // APPS + + 'apps.cpu': { + height: 2.0 + }, + + 'apps.mem': { + info: 'Real memory (RAM) used by applications. This does not include shared memory.' + }, + + 'apps.vmem': { + info: 'Virtual memory allocated by applications. Please check <a href="https://github.com/netdata/netdata/tree/master/daemon#virtual-memory" target="_blank">this article</a> for more information.' + }, + + 'apps.preads': { + height: 2.0 + }, + + 'apps.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // USERS + + 'users.cpu': { + height: 2.0 + }, + + 'users.mem': { + info: 'Real memory (RAM) used per user. This does not include shared memory.' + }, + + 'users.vmem': { + info: 'Virtual memory allocated per user. Please check <a href="https://github.com/netdata/netdata/tree/master/daemon#virtual-memory" target="_blank">this article</a> for more information.' + }, + + 'users.preads': { + height: 2.0 + }, + + 'users.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // GROUPS + + 'groups.cpu': { + height: 2.0 + }, + + 'groups.mem': { + info: 'Real memory (RAM) used per user group. This does not include shared memory.' + }, + + 'groups.vmem': { + info: 'Virtual memory allocated per user group. Please check <a href="https://github.com/netdata/netdata/tree/master/daemon#virtual-memory" target="_blank">this article</a> for more information.' + }, + + 'groups.preads': { + height: 2.0 + }, + + 'groups.pwrites': { + height: 2.0 + }, + + // ------------------------------------------------------------------------ + // NETWORK QoS + + 'tc.qos': { + heads: [ + function (os, id) { + void(os); + + if (id.match(/.*-ifb$/)) + return netdataDashboard.gaugeChart('Inbound', '12%', '', '#5555AA'); + else + return netdataDashboard.gaugeChart('Outbound', '12%', '', '#AA9900'); + } + ] + }, + + // ------------------------------------------------------------------------ + // NETWORK INTERFACES + + 'net.net': { + mainheads: [ + function (os, id) { + void(os); + if (id.match(/^cgroup_.*/)) { + var iface; + try { + iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length); + } + catch (e) { + iface = ''; + } + return netdataDashboard.gaugeChart('Received' + iface, '12%', 'received'); + } + else + return ''; + }, + function (os, id) { + void(os); + if (id.match(/^cgroup_.*/)) { + var iface; + try { + iface = ' ' + id.substring(id.lastIndexOf('.net_') + 5, id.length); + } + catch (e) { + iface = ''; + } + return netdataDashboard.gaugeChart('Sent' + iface, '12%', 'sent'); + } + else + return ''; + } + ], + heads: [ + function (os, id) { + void(os); + if (!id.match(/^cgroup_.*/)) + return netdataDashboard.gaugeChart('Received', '12%', 'received'); + else + return ''; + }, + function (os, id) { + void(os); + if (!id.match(/^cgroup_.*/)) + return netdataDashboard.gaugeChart('Sent', '12%', 'sent'); + else + return ''; + } + ] + }, + + // ------------------------------------------------------------------------ + // NETFILTER + + 'netfilter.sockets': { + colors: '#88AA00', + heads: [ + netdataDashboard.gaugeChart('Active Connections', '12%', '', '#88AA00') + ] + }, + + 'netfilter.new': { + heads: [ + netdataDashboard.gaugeChart('New Connections', '12%', 'new', '#5555AA') + ] + }, + + // ------------------------------------------------------------------------ + // DISKS + + 'disk.util': { + colors: '#FF5588', + heads: [ + netdataDashboard.gaugeChart('Utilization', '12%', '', '#FF5588') + ], + info: 'Disk Utilization measures the amount of time the disk was busy with something. This is not related to its performance. 100% means that the system always had an outstanding operation on the disk. Keep in mind that depending on the underlying technology of the disk, 100% here may or may not be an indication of congestion.' + }, + + 'disk.backlog': { + colors: '#0099CC', + info: 'Backlog is an indication of the duration of pending disk operations. On every I/O event the system is multiplying the time spent doing I/O since the last update of this field with the number of pending operations. While not accurate, this metric can provide an indication of the expected completion time of the operations in progress.' + }, + + 'disk.io': { + heads: [ + netdataDashboard.gaugeChart('Read', '12%', 'reads'), + netdataDashboard.gaugeChart('Write', '12%', 'writes') + ], + info: 'Amount of data transferred to and from disk.' + }, + + 'disk.ops': { + info: 'Completed disk I/O operations. Keep in mind the number of operations requested might be higher, since the system is able to merge adjacent to each other (see merged operations chart).' + }, + + 'disk.qops': { + info: 'I/O operations currently in progress. This metric is a snapshot - it is not an average over the last interval.' + }, + + 'disk.iotime': { + height: 0.5, + info: 'The sum of the duration of all completed I/O operations. This number can exceed the interval if the disk is able to execute I/O operations in parallel.' + }, + 'disk.mops': { + height: 0.5, + info: 'The number of merged disk operations. The system is able to merge adjacent I/O operations, for example two 4KB reads can become one 8KB read before given to disk.' + }, + 'disk.svctm': { + height: 0.5, + info: 'The average service time for completed I/O operations. This metric is calculated using the total busy time of the disk and the number of completed operations. If the disk is able to execute multiple parallel operations the reporting average service time will be misleading.' + }, + 'disk.avgsz': { + height: 0.5, + info: 'The average I/O operation size.' + }, + 'disk.await': { + height: 0.5, + info: 'The average time for I/O requests issued to the device to be served. This includes the time spent by the requests in queue and the time spent servicing them.' + }, + + 'disk.space': { + info: 'Disk space utilization. reserved for root is automatically reserved by the system to prevent the root user from getting out of space.' + }, + 'disk.inodes': { + info: 'inodes (or index nodes) are filesystem objects (e.g. files and directories). On many types of file system implementations, the maximum number of inodes is fixed at filesystem creation, limiting the maximum number of files the filesystem can hold. It is possible for a device to run out of inodes. When this happens, new files cannot be created on the device, even though there may be free space available.' + }, + + 'mysql.net': { + info: 'The amount of data sent to mysql clients (<strong>out</strong>) and received from mysql clients (<strong>in</strong>).' + }, + + // ------------------------------------------------------------------------ + // MYSQL + + 'mysql.queries': { + info: 'The number of statements executed by the server.<ul>' + + '<li><strong>queries</strong> counts the statements executed within stored SQL programs.</li>' + + '<li><strong>questions</strong> counts the statements sent to the mysql server by mysql clients.</li>' + + '<li><strong>slow queries</strong> counts the number of statements that took more than <a href="http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_long_query_time" target="_blank">long_query_time</a> seconds to be executed.' + + ' For more information about slow queries check the mysql <a href="http://dev.mysql.com/doc/refman/5.7/en/slow-query-log.html" target="_blank">slow query log</a>.</li>' + + '</ul>' + }, + + 'mysql.handlers': { + info: 'Usage of the internal handlers of mysql. This chart provides very good insights of what the mysql server is actually doing.' + + ' (if the chart is not showing all these dimensions it is because they are zero - set <strong>Which dimensions to show?</strong> to <strong>All</strong> from the dashboard settings, to render even the zero values)<ul>' + + '<li><strong>commit</strong>, the number of internal <a href="http://dev.mysql.com/doc/refman/5.7/en/commit.html" target="_blank">COMMIT</a> statements.</li>' + + '<li><strong>delete</strong>, the number of times that rows have been deleted from tables.</li>' + + '<li><strong>prepare</strong>, a counter for the prepare phase of two-phase commit operations.</li>' + + '<li><strong>read first</strong>, the number of times the first entry in an index was read. A high value suggests that the server is doing a lot of full index scans; e.g. <strong>SELECT col1 FROM foo</strong>, with col1 indexed.</li>' + + '<li><strong>read key</strong>, the number of requests to read a row based on a key. If this value is high, it is a good indication that your tables are properly indexed for your queries.</li>' + + '<li><strong>read next</strong>, the number of requests to read the next row in key order. This value is incremented if you are querying an index column with a range constraint or if you are doing an index scan.</li>' + + '<li><strong>read prev</strong>, the number of requests to read the previous row in key order. This read method is mainly used to optimize <strong>ORDER BY ... DESC</strong>.</li>' + + '<li><strong>read rnd</strong>, the number of requests to read a row based on a fixed position. A high value indicates you are doing a lot of queries that require sorting of the result. You probably have a lot of queries that require MySQL to scan entire tables or you have joins that do not use keys properly.</li>' + + '<li><strong>read rnd next</strong>, the number of requests to read the next row in the data file. This value is high if you are doing a lot of table scans. Generally this suggests that your tables are not properly indexed or that your queries are not written to take advantage of the indexes you have.</li>' + + '<li><strong>rollback</strong>, the number of requests for a storage engine to perform a rollback operation.</li>' + + '<li><strong>savepoint</strong>, the number of requests for a storage engine to place a savepoint.</li>' + + '<li><strong>savepoint rollback</strong>, the number of requests for a storage engine to roll back to a savepoint.</li>' + + '<li><strong>update</strong>, the number of requests to update a row in a table.</li>' + + '<li><strong>write</strong>, the number of requests to insert a row in a table.</li>' + + '</ul>' + }, + + 'mysql.table_locks': { + info: 'MySQL table locks counters: <ul>' + + '<li><strong>immediate</strong>, the number of times that a request for a table lock could be granted immediately.</li>' + + '<li><strong>waited</strong>, the number of times that a request for a table lock could not be granted immediately and a wait was needed. If this is high and you have performance problems, you should first optimize your queries, and then either split your table or tables or use replication.</li>' + + '</ul>' + }, + + // ------------------------------------------------------------------------ + // POSTGRESQL + + + 'postgres.db_stat_blks': { + info: 'Blocks reads from disk or cache.<ul>' + + '<li><strong>blks_read:</strong> number of disk blocks read in this database.</li>' + + '<li><strong>blks_hit:</strong> number of times disk blocks were found already in the buffer cache, so that a read was not necessary (this only includes hits in the PostgreSQL buffer cache, not the operating system's file system cache)</li>' + + '</ul>' + }, + 'postgres.db_stat_tuple_write': { + info: '<ul><li>Number of rows inserted/updated/deleted.</li>' + + '<li><strong>conflicts:</strong> number of queries canceled due to conflicts with recovery in this database. (Conflicts occur only on standby servers; see <a href="https://www.postgresql.org/docs/10/static/monitoring-stats.html#PG-STAT-DATABASE-CONFLICTS-VIEW" target="_blank">pg_stat_database_conflicts</a> for details.)</li>' + + '</ul>' + }, + 'postgres.db_stat_temp_bytes': { + info: 'Temporary files can be created on disk for sorts, hashes, and temporary query results.' + }, + 'postgres.db_stat_temp_files': { + info: '<ul>' + + '<li><strong>files:</strong> number of temporary files created by queries. All temporary files are counted, regardless of why the temporary file was created (e.g., sorting or hashing).</li>' + + '</ul>' + }, + 'postgres.archive_wal': { + info: 'WAL archiving.<ul>' + + '<li><strong>total:</strong> total files.</li>' + + '<li><strong>ready:</strong> WAL waiting to be archived.</li>' + + '<li><strong>done:</strong> WAL successfully archived. ' + + 'Ready WAL can indicate archive_command is in error, see <a href="https://www.postgresql.org/docs/current/static/continuous-archiving.html" target="_blank">Continuous Archiving and Point-in-Time Recovery</a>.</li>' + + '</ul>' + }, + 'postgres.checkpointer': { + info: 'Number of checkpoints.<ul>' + + '<li><strong>scheduled:</strong> when checkpoint_timeout is reached.</li>' + + '<li><strong>requested:</strong> when max_wal_size is reached.</li>' + + '</ul>' + + 'For more information see <a href="https://www.postgresql.org/docs/current/static/wal-configuration.html" target="_blank">WAL Configuration</a>.' + }, + 'postgres.autovacuum': { + info: 'PostgreSQL databases require periodic maintenance known as vacuuming. For many installations, it is sufficient to let vacuuming be performed by the autovacuum daemon. ' + + 'For more information see <a href="https://www.postgresql.org/docs/current/static/routine-vacuuming.html#AUTOVACUUM" target="_blank">The Autovacuum Daemon</a>.' + }, + 'postgres.standby_delta': { + info: 'Streaming replication delta.<ul>' + + '<li><strong>sent_delta:</strong> replication delta sent to standby.</li>' + + '<li><strong>write_delta:</strong> replication delta written to disk by this standby.</li>' + + '<li><strong>flush_delta:</strong> replication delta flushed to disk by this standby server.</li>' + + '<li><strong>replay_delta:</strong> replication delta replayed into the database on this standby server.</li>' + + '</ul>' + + 'For more information see <a href="https://www.postgresql.org/docs/current/static/warm-standby.html#SYNCHRONOUS-REPLICATION" target="_blank">Synchronous Replication</a>.' + }, + 'postgres.replication_slot': { + info: 'Replication slot files.<ul>' + + '<li><strong>wal_keeped:</strong> WAL files retained by each replication slots.</li>' + + '<li><strong>pg_replslot_files:</strong> files present in pg_replslot.</li>' + + '</ul>' + + 'For more information see <a href="https://www.postgresql.org/docs/current/static/warm-standby.html#STREAMING-REPLICATION-SLOTS" target="_blank">Replication Slots</a>.' + }, + + + // ------------------------------------------------------------------------ + // APACHE + + 'apache.connections': { + colors: NETDATA.colors[4], + mainheads: [ + netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) + ] + }, + + 'apache.requests': { + colors: NETDATA.colors[0], + mainheads: [ + netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) + ] + }, + + 'apache.net': { + colors: NETDATA.colors[3], + mainheads: [ + netdataDashboard.gaugeChart('Bandwidth', '12%', '', NETDATA.colors[3]) + ] + }, + + 'apache.workers': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="busy"' + + ' data-append-options="percentage"' + + ' data-gauge-max-value="100"' + + ' data-chart-library="gauge"' + + ' data-title="Workers Utilization"' + + ' data-units="percentage %"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' role="application"></div>'; + } + ] + }, + + 'apache.bytesperreq': { + colors: NETDATA.colors[3], + height: 0.5 + }, + + 'apache.reqpersec': { + colors: NETDATA.colors[4], + height: 0.5 + }, + + 'apache.bytespersec': { + colors: NETDATA.colors[6], + height: 0.5 + }, + + + // ------------------------------------------------------------------------ + // LIGHTTPD + + 'lighttpd.connections': { + colors: NETDATA.colors[4], + mainheads: [ + netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) + ] + }, + + 'lighttpd.requests': { + colors: NETDATA.colors[0], + mainheads: [ + netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) + ] + }, + + 'lighttpd.net': { + colors: NETDATA.colors[3], + mainheads: [ + netdataDashboard.gaugeChart('Bandwidth', '12%', '', NETDATA.colors[3]) + ] + }, + + 'lighttpd.workers': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="busy"' + + ' data-append-options="percentage"' + + ' data-gauge-max-value="100"' + + ' data-chart-library="gauge"' + + ' data-title="Servers Utilization"' + + ' data-units="percentage %"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' role="application"></div>'; + } + ] + }, + + 'lighttpd.bytesperreq': { + colors: NETDATA.colors[3], + height: 0.5 + }, + + 'lighttpd.reqpersec': { + colors: NETDATA.colors[4], + height: 0.5 + }, + + 'lighttpd.bytespersec': { + colors: NETDATA.colors[6], + height: 0.5 + }, + + // ------------------------------------------------------------------------ + // NGINX + + 'nginx.connections': { + colors: NETDATA.colors[4], + mainheads: [ + netdataDashboard.gaugeChart('Connections', '12%', '', NETDATA.colors[4]) + ] + }, + + 'nginx.requests': { + colors: NETDATA.colors[0], + mainheads: [ + netdataDashboard.gaugeChart('Requests', '12%', '', NETDATA.colors[0]) + ] + }, + + // ------------------------------------------------------------------------ + // HTTP check + + 'httpcheck.responsetime': { + info: 'The <code>response time</code> describes the time passed between request and response. ' + + 'Currently, the accuracy of the response time is low and should be used as reference only.' + }, + + 'httpcheck.responselength': { + info: 'The <code>response length</code> counts the number of characters in the response body. For static pages, this should be mostly constant.' + }, + + 'httpcheck.status': { + valueRange: "[0, 1]", + info: 'This chart verifies the response of the webserver. Each status dimension will have a value of <code>1</code> if triggered. ' + + 'Dimension <code>success</code> is <code>1</code> only if all constraints are satisfied. ' + + 'This chart is most useful for alarms or third-party apps.' + }, + + // ------------------------------------------------------------------------ + // NETDATA + + 'netdata.response_time': { + info: 'The netdata API response time measures the time netdata needed to serve requests. This time includes everything, from the reception of the first byte of a request, to the dispatch of the last byte of its reply, therefore it includes all network latencies involved (i.e. a client over a slow network will influence these metrics).' + }, + + // ------------------------------------------------------------------------ + // RETROSHARE + + 'retroshare.bandwidth': { + info: 'RetroShare inbound and outbound traffic.', + mainheads: [ + netdataDashboard.gaugeChart('Received', '12%', 'bandwidth_down_kb'), + netdataDashboard.gaugeChart('Sent', '12%', 'bandwidth_up_kb') + ] + }, + + 'retroshare.peers': { + info: 'Number of (connected) RetroShare friends.', + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="peers_connected"' + + ' data-append-options="friends"' + + ' data-chart-library="easypiechart"' + + ' data-title="connected friends"' + + ' data-units=""' + + ' data-width="8%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' role="application"></div>'; + } + ] + }, + + 'retroshare.dht': { + info: 'Statistics about RetroShare\'s DHT. These values are estimated!' + }, + + // ------------------------------------------------------------------------ + // fping + + 'fping.quality': { + colors: NETDATA.colors[10], + height: 0.5 + }, + + 'fping.packets': { + height: 0.5 + }, + + + // ------------------------------------------------------------------------ + // containers + + 'cgroup.cpu': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-chart-library="gauge"' + + ' data-title="CPU"' + + ' data-units="%"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[4] + '"' + + ' role="application"></div>'; + } + ] + }, + + 'cgroup.mem_usage': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-chart-library="gauge"' + + ' data-title="Memory"' + + ' data-units="MB"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[1] + '"' + + ' role="application"></div>'; + } + ] + }, + + 'cgroup.throttle_io': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="read"' + + ' data-chart-library="gauge"' + + ' data-title="Read Disk I/O"' + + ' data-units="KB/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[2] + '"' + + ' role="application"></div>'; + }, + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="write"' + + ' data-chart-library="gauge"' + + ' data-title="Write Disk I/O"' + + ' data-units="KB/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[3] + '"' + + ' role="application"></div>'; + } + ] + }, + + // ------------------------------------------------------------------------ + // beanstalkd + // system charts + 'beanstalk.cpu_usage': { + info: 'Amount of CPU Time for user and system used by beanstalkd.' + }, + + // This is also a per-tube stat + 'beanstalk.jobs_rate': { + info: 'The rate of jobs processed by the beanstalkd served.' + }, + + 'beanstalk.connections_rate': { + info: 'Tthe rate of connections opened to beanstalkd.' + }, + + 'beanstalk.commands_rate': { + info: 'The rate of commands received by beanstalkd.' + }, + + 'beanstalk.current_tubes': { + info: 'Total number of current tubes on the server including the default tube (which always exists).' + }, + + 'beanstalk.current_jobs': { + info: 'Current number of jobs in all tubes grouped by status: urgent, ready, reserved, delayed and buried.' + }, + + 'beanstalk.current_connections': { + info: 'Current number of connections group by connection type: written, producers, workers, waiting.' + }, + + 'beanstalk.binlog': { + info: 'The rate of records <code>written</code> to binlog and <code>migrated</code> as part of compaction.' + }, + + 'beanstalk.uptime': { + info: 'Total time beanstalkd server has been up for.' + }, + + // tube charts + 'beanstalk.jobs': { + info: 'Number of jobs currently in the tube grouped by status: urgent, ready, reserved, delayed and buried.' + }, + + 'beanstalk.connections': { + info: 'The current number of connections to this tube grouped by connection type; using, waiting and watching.' + }, + + 'beanstalk.commands': { + info: 'The rate of <code>delete</code> and <code>pause</code> commands executed by beanstalkd.' + }, + + 'beanstalk.pause': { + info: 'Shows info on how long the tube has been paused for, and how long is left remaining on the pause.' + }, + + // ------------------------------------------------------------------------ + // ceph + + 'ceph.general_usage': { + info: 'The usage and available space in all ceph cluster.' + }, + + 'ceph.general_objects': { + info: 'Total number of objects storage on ceph cluster.' + }, + + 'ceph.general_bytes': { + info: 'Cluster read and write data per second.' + }, + + 'ceph.general_operations': { + info: 'Number of read and write operations per second.' + }, + + 'ceph.general_latency': { + info: 'Total of apply and commit latency in all OSDs. The apply latency is the total time taken to flush an update to disk. The commit latency is the total time taken to commit an operation to the journal.' + }, + + 'ceph.pool_usage': { + info: 'The usage space in each pool.' + }, + + 'ceph.pool_objects': { + info: 'Number of objects presents in each pool.' + }, + + 'ceph.pool_read_bytes': { + info: 'The rate of read data per second in each pool.' + }, + + 'ceph.pool_write_bytes': { + info: 'The rate of write data per second in each pool.' + }, + + 'ceph.pool_read_objects': { + info: 'Number of read objects per second in each pool.' + }, + + 'ceph.pool_write_objects': { + info: 'Number of write objects per second in each pool.' + }, + + 'ceph.osd_usage': { + info: 'The usage space in each OSD.' + }, + + 'ceph.apply_latency': { + info: 'Time taken to flush an update in each OSD.' + }, + + 'ceph.commit_latency': { + info: 'Time taken to commit an operation to the journal in each OSD.' + }, + + // ------------------------------------------------------------------------ + // web_log + + 'web_log.response_statuses': { + info: 'Web server responses by type. <code>success</code> includes <b>1xx</b>, <b>2xx</b> and <b>304</b>, <code>error</code> includes <b>5xx</b>, <code>redirect</code> includes <b>3xx</b> except <b>304</b>, <code>bad</code> includes <b>4xx</b>, <code>other</code> are all the other responses.', + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="success"' + + ' data-chart-library="gauge"' + + ' data-title="Successful"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[0] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="redirect"' + + ' data-chart-library="gauge"' + + ' data-title="Redirects"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[2] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="bad"' + + ' data-chart-library="gauge"' + + ' data-title="Bad Requests"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[3] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="error"' + + ' data-chart-library="gauge"' + + ' data-title="Server Errors"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[1] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + } + ] + }, + + 'web_log.response_codes': { + info: 'Web server responses by code family. ' + + 'According to the standards <code>1xx</code> are informational responses, ' + + '<code>2xx</code> are successful responses, ' + + '<code>3xx</code> are redirects (although they include <b>304</b> which is used as "<b>not modified</b>"), ' + + '<code>4xx</code> are bad requests, ' + + '<code>5xx</code> are internal server errors, ' + + '<code>other</code> are non-standard responses, ' + + '<code>unmatched</code> counts the lines in the log file that are not matched by the plugin (<a href="https://github.com/netdata/netdata/issues/new?title=web_log%20reports%20unmatched%20lines&body=web_log%20plugin%20reports%20unmatched%20lines.%0A%0AThis%20is%20my%20log:%0A%0A%60%60%60txt%0A%0Aplease%20paste%20your%20web%20server%20log%20here%0A%0A%60%60%60" target="_blank">let us know</a> if you have any unmatched).' + }, + + 'web_log.response_time': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="avg"' + + ' data-chart-library="gauge"' + + ' data-title="Average Response Time"' + + ' data-units="milliseconds"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[4] + '"' + + ' data-decimal-digits="2"' + + ' role="application"></div>'; + } + ] + }, + + 'web_log.detailed_response_codes': { + info: 'Number of responses for each response code individually.' + }, + + 'web_log.requests_per_ipproto': { + info: 'Web server requests received per IP protocol version.' + }, + + 'web_log.clients': { + info: 'Unique client IPs accessing the web server, within each data collection iteration. If data collection is <b>per second</b>, this chart shows <b>unique client IPs per second</b>.' + }, + + 'web_log.clients_all': { + info: 'Unique client IPs accessing the web server since the last restart of netdata. This plugin keeps in memory all the unique IPs that have accessed the web server. On very busy web servers (several millions of unique IPs) you may want to disable this chart (check <a href="https://github.com/netdata/netdata/blob/master/conf.d/python.d/web_log.conf" target="_blank"><code>/etc/netdata/python.d/web_log.conf</code></a>).' + }, + + // ------------------------------------------------------------------------ + // web_log for squid + + 'web_log.squid_response_statuses': { + info: 'Squid responses by type. ' + + '<code>success</code> includes <b>1xx</b>, <b>2xx</b>, <b>000</b>, <b>304</b>, ' + + '<code>error</code> includes <b>5xx</b> and <b>6xx</b>, ' + + '<code>redirect</code> includes <b>3xx</b> except <b>304</b>, ' + + '<code>bad</code> includes <b>4xx</b>, ' + + '<code>other</code> are all the other responses.', + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="success"' + + ' data-chart-library="gauge"' + + ' data-title="Successful"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[0] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="redirect"' + + ' data-chart-library="gauge"' + + ' data-title="Redirects"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[2] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="bad"' + + ' data-chart-library="gauge"' + + ' data-title="Bad Requests"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[3] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + }, + + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="error"' + + ' data-chart-library="gauge"' + + ' data-title="Server Errors"' + + ' data-units="requests/s"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-common-max="' + id + '"' + + ' data-colors="' + NETDATA.colors[1] + '"' + + ' data-decimal-digits="0"' + + ' role="application"></div>'; + } + ] + }, + + 'web_log.squid_response_codes': { + info: 'Web server responses by code family. ' + + 'According to HTTP standards <code>1xx</code> are informational responses, ' + + '<code>2xx</code> are successful responses, ' + + '<code>3xx</code> are redirects (although they include <b>304</b> which is used as "<b>not modified</b>"), ' + + '<code>4xx</code> are bad requests, ' + + '<code>5xx</code> are internal server errors. ' + + 'Squid also defines <code>000</code> mostly for UDP requests, and ' + + '<code>6xx</code> for broken upstream servers sending wrong headers. ' + + 'Finally, <code>other</code> are non-standard responses, and ' + + '<code>unmatched</code> counts the lines in the log file that are not matched by the plugin (<a href="https://github.com/netdata/netdata/issues/new?title=web_log%20reports%20unmatched%20lines&body=web_log%20plugin%20reports%20unmatched%20lines.%0A%0AThis%20is%20my%20log:%0A%0A%60%60%60txt%0A%0Aplease%20paste%20your%20web%20server%20log%20here%0A%0A%60%60%60" target="_blank">let us know</a> if you have any unmatched).' + }, + + 'web_log.squid_duration': { + mainheads: [ + function (os, id) { + void(os); + return '<div data-netdata="' + id + '"' + + ' data-dimensions="avg"' + + ' data-chart-library="gauge"' + + ' data-title="Average Response Time"' + + ' data-units="milliseconds"' + + ' data-gauge-adjust="width"' + + ' data-width="12%"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + NETDATA.colors[4] + '"' + + ' data-decimal-digits="2"' + + ' role="application"></div>'; + } + ] + }, + + 'web_log.squid_detailed_response_codes': { + info: 'Number of responses for each response code individually.' + }, + + 'web_log.squid_clients': { + info: 'Unique client IPs accessing squid, within each data collection iteration. If data collection is <b>per second</b>, this chart shows <b>unique client IPs per second</b>.' + }, + + 'web_log.squid_clients_all': { + info: 'Unique client IPs accessing squid since the last restart of netdata. This plugin keeps in memory all the unique IPs that have accessed the server. On very busy squid servers (several millions of unique IPs) you may want to disable this chart (check <a href="https://github.com/netdata/netdata/blob/master/conf.d/python.d/web_log.conf" target="_blank"><code>/etc/netdata/python.d/web_log.conf</code></a>).' + }, + + 'web_log.squid_transport_methods': { + info: 'Break down per delivery method: <code>TCP</code> are requests on the HTTP port (usually 3128), ' + + '<code>UDP</code> are requests on the ICP port (usually 3130), or HTCP port (usually 4128). ' + + 'If ICP logging was disabled using the log_icp_queries option, no ICP replies will be logged. ' + + '<code>NONE</code> are used to state that squid delivered an unusual response or no response at all. ' + + 'Seen with cachemgr requests and errors, usually when the transaction fails before being classified into one of the above outcomes. ' + + 'Also seen with responses to <code>CONNECT</code> requests.' + }, + + 'web_log.squid_code': { + info: 'These are combined squid result status codes. A break down per component is given in the following charts. ' + + 'Check the <a href="http://wiki.squid-cache.org/SquidFaq/SquidLogs">squid documentation about them</a>.' + }, + + 'web_log.squid_handling_opts': { + info: 'These tags are optional and describe why the particular handling was performed or where the request came from. ' + + '<code>CLIENT</code> means that the client request placed limits affecting the response. Usually seen with client issued a <b>no-cache</b>, or analogous cache control command along with the request. Thus, the cache has to validate the object.' + + '<code>IMS</code> states that the client sent a revalidation (conditional) request. ' + + '<code>ASYNC</code>, is used when the request was generated internally by Squid. Usually this is background fetches for cache information exchanges, background revalidation from stale-while-revalidate cache controls, or ESI sub-objects being loaded. ' + + '<code>SWAPFAIL</code> is assigned when the object was believed to be in the cache, but could not be accessed. A new copy was requested from the server. ' + + '<code>REFRESH</code> when a revalidation (conditional) request was sent to the server. ' + + '<code>SHARED</code> when this request was combined with an existing transaction by collapsed forwarding. NOTE: the existing request is not marked as SHARED. ' + + '<code>REPLY</code> when particular handling was requested in the HTTP reply from server or peer. Usually seen on DENIED due to http_reply_access ACLs preventing delivery of servers response object to the client.' + }, + + 'web_log.squid_object_types': { + info: 'These tags are optional and describe what type of object was produced. ' + + '<code>NEGATIVE</code> is only seen on HIT responses, indicating the response was a cached error response. e.g. <b>404 not found</b>. ' + + '<code>STALE</code> means the object was cached and served stale. This is usually caused by stale-while-revalidate or stale-if-error cache controls. ' + + '<code>OFFLINE</code> when the requested object was retrieved from the cache during offline_mode. The offline mode never validates any object. ' + + '<code>INVALID</code> when an invalid request was received. An error response was delivered indicating what the problem was. ' + + '<code>FAIL</code> is only seen on <code>REFRESH</code> to indicate the revalidation request failed. The response object may be the server provided network error or the stale object which was being revalidated depending on stale-if-error cache control. ' + + '<code>MODIFIED</code> is only seen on <code>REFRESH</code> responses to indicate revalidation produced a new modified object. ' + + '<code>UNMODIFIED</code> is only seen on <code>REFRESH</code> responses to indicate revalidation produced a <b>304</b> (Not Modified) status, which was relayed to the client. ' + + '<code>REDIRECT</code> when squid generated an HTTP redirect response to this request.' + }, + + 'web_log.squid_cache_events': { + info: 'These tags are optional and describe whether the response was loaded from cache, network, or otherwise. ' + + '<code>HIT</code> when the response object delivered was the local cache object. ' + + '<code>MEM</code> when the response object came from memory cache, avoiding disk accesses. Only seen on HIT responses. ' + + '<code>MISS</code> when the response object delivered was the network response object. ' + + '<code>DENIED</code> when the request was denied by access controls. ' + + '<code>NOFETCH</code> an ICP specific type, indicating service is alive, but not to be used for this request (sent during "-Y" startup, or during frequent failures, a cache in hit only mode will return either UDP_HIT or UDP_MISS_NOFETCH. Neighbours will thus only fetch hits). ' + + '<code>TUNNEL</code> when a binary tunnel was established for this transaction.' + }, + + 'web_log.squid_transport_errors': { + info: 'These tags are optional and describe some error conditions which occured during response delivery (if any). ' + + '<code>ABORTED</code> when the response was not completed due to the connection being aborted (usually by the client). ' + + '<code>TIMEOUT</code>, when the response was not completed due to a connection timeout.' + }, + + // ------------------------------------------------------------------------ + // Fronius Solar Power + + 'fronius.power': { + info: 'Positive <code>Grid</code> values mean that power is coming from the grid. Negative values are excess power that is going back into the grid, possibly selling it. ' + + '<code>Photovoltaics</code> is the power generated from the solar panels. ' + + '<code>Accumulator</code> is the stored power in the accumulator, if one is present.' + }, + + 'fronius.autonomy': { + commonMin: true, + commonMax: true, + valueRange: "[0, 100]", + info: 'The <code>Autonomy</code> is the percentage of how autonomous the installation is. An autonomy of 100 % means that the installation is producing more energy than it is needed. ' + + 'The <code>Self consumption</code> indicates the ratio between the current power generated and the current load. When it reaches 100 %, the <code>Autonomy</code> declines, since the solar panels can not produce enough energy and need support from the grid.' + }, + + 'fronius.energy.today': { + commonMin: true, + commonMax: true, + valueRange: "[0, null]" + }, + + // ------------------------------------------------------------------------ + // Stiebel Eltron Heat pump installation + + 'stiebeleltron.system.roomtemp': { + commonMin: true, + commonMax: true, + valueRange: "[0, null]" + }, + + // ------------------------------------------------------------------------ + // Port check + + 'portcheck.latency': { + info: 'The <code>latency</code> describes the time spent connecting to a TCP port. No data is sent or received. ' + + 'Currently, the accuracy of the latency is low and should be used as reference only.' + }, + + 'portcheck.status': { + valueRange: "[0, 1]", + info: 'The <code>status</code> chart verifies the availability of the service. ' + + 'Each status dimension will have a value of <code>1</code> if triggered. Dimension <code>success</code> is <code>1</code> only if connection could be established. ' + + 'This chart is most useful for alarms and third-party apps.' + }, + + // ------------------------------------------------------------------------ + + 'chrony.system': { + info: 'In normal operation, chronyd never steps the system clock, because any jump in the timescale can have adverse consequences for certain application programs. Instead, any error in the system clock is corrected by slightly speeding up or slowing down the system clock until the error has been removed, and then returning to the system clock’s normal speed. A consequence of this is that there will be a period when the system clock (as read by other programs using the <code>gettimeofday()</code> system call, or by the <code>date</code> command in the shell) will be different from chronyd\'s estimate of the current true time (which it reports to NTP clients when it is operating in server mode). The value reported on this line is the difference due to this effect.', + colors: NETDATA.colors[3] + }, + + 'chrony.offsets': { + info: '<code>last offset</code> is the estimated local offset on the last clock update. <code>RMS offset</code> is a long-term average of the offset value.', + height: 0.5 + }, + + 'chrony.stratum': { + info: 'The <code>stratum</code> indicates how many hops away from a computer with an attached reference clock we are. Such a computer is a stratum-1 computer.', + decimalDigits: 0, + height: 0.5 + }, + + 'chrony.root': { + info: 'Estimated delays against the root time server this system is synchronized with. <code>delay</code> is the total of the network path delays to the stratum-1 computer from which the computer is ultimately synchronised. <code>dispersion</code> is the total dispersion accumulated through all the computers back to the stratum-1 computer from which the computer is ultimately synchronised. Dispersion is due to system clock resolution, statistical measurement variations etc.' + }, + + 'chrony.frequency': { + info: 'The <code>frequency</code> is the rate by which the system\'s clock would be would be wrong if chronyd was not correcting it. It is expressed in ppm (parts per million). For example, a value of 1ppm would mean that when the system\'s clock thinks it has advanced 1 second, it has actually advanced by 1.000001 seconds relative to true time.', + colors: NETDATA.colors[0] + }, + + 'chrony.residualfreq': { + info: 'This shows the <code>residual frequency</code> for the currently selected reference source. ' + + 'It reflects any difference between what the measurements from the reference source indicate the ' + + 'frequency should be and the frequency currently being used. The reason this is not always zero is ' + + 'that a smoothing procedure is applied to the frequency. Each time a measurement from the reference ' + + 'source is obtained and a new residual frequency computed, the estimated accuracy of this residual ' + + 'is compared with the estimated accuracy (see <code>skew</code>) of the existing frequency value. ' + + 'A weighted average is computed for the new frequency, with weights depending on these accuracies. ' + + 'If the measurements from the reference source follow a consistent trend, the residual will be ' + + 'driven to zero over time.', + height: 0.5, + colors: NETDATA.colors[3] + }, + + 'chrony.skew': { + info: 'The estimated error bound on the frequency.', + height: 0.5, + colors: NETDATA.colors[5] + }, + + 'couchdb.active_tasks': { + info: 'Active tasks running on this CouchDB <b>cluster</b>. Four types of tasks currently exist: indexer (view building), replication, database compaction and view compaction.' + }, + + 'couchdb.replicator_jobs': { + info: 'Detailed breakdown of any replication jobs in progress on this node. For more information, see the <a href="http://docs.couchdb.org/en/latest/replication/replicator.html">replicator documentation</a>.' + }, + + 'couchdb.open_files': { + info: 'Count of all files held open by CouchDB. If this value seems pegged at 1024 or 4096, your server process is probably hitting the open file handle limit and <a href="http://docs.couchdb.org/en/latest/maintenance/performance.html#pam-and-ulimit">needs to be increased.</a>' + }, + + 'btrfs.disk': { + info: 'Physical disk usage of BTRFS. The disk space reported here is the raw physical disk space assigned to the BTRFS volume (i.e. <b>before any RAID levels</b>). BTRFS uses a two-stage allocator, first allocating large regions of disk space for one type of block (data, metadata, or system), and then using a regular block allocator inside those regions. <code>unallocated</code> is the physical disk space that is not allocated yet and is available to become data, metdata or system on demand. When <code>unallocated</code> is zero, all available disk space has been allocated to a specific function. Healthy volumes should ideally have at least five percent of their total space <code>unallocated</code>. You can keep your volume healthy by running the <code>btrfs balance</code> command on it regularly (check <code>man btrfs-balance</code> for more info). Note that some of the space listed as <code>unallocated</code> may not actually be usable if the volume uses devices of different sizes.', + colors: [NETDATA.colors[12]] + }, + + 'btrfs.data': { + info: 'Logical disk usage for BTRFS data. Data chunks are used to store the actual file data (file contents). The disk space reported here is the usable allocation (i.e. after any striping or replication). Healthy volumes should ideally have no more than a few GB of free space reported here persistently. Running <code>btrfs balance</code> can help here.' + }, + + 'btrfs.metadata': { + info: 'Logical disk usage for BTRFS metadata. Metadata chunks store most of the filesystem interal structures, as well as information like directory structure and file names. The disk space reported here is the usable allocation (i.e. after any striping or replication). Healthy volumes should ideally have no more than a few GB of free space reported here persistently. Running <code>btrfs balance</code> can help here.' + }, + + 'btrfs.system': { + info: 'Logical disk usage for BTRFS system. System chunks store information about the allocation of other chunks. The disk space reported here is the usable allocation (i.e. after any striping or replication). The values reported here should be relatively small compared to Data and Metadata, and will scale with the volume size and overall space usage.' + }, + + // ------------------------------------------------------------------------ + // RabbitMQ + + // info: the text above the charts + // heads: the representation of the chart at the top the subsection (second level menu) + // mainheads: the representation of the chart at the top of the section (first level menu) + // colors: the dimension colors of the chart (the default colors are appended) + // height: the ratio of the chart height relative to the default + + 'rabbitmq.queued_messages': { + info: 'Overall total of ready and unacknowledged queued messages. Messages that are delivered immediately are not counted here.' + }, + + 'rabbitmq.message_rates': { + info: 'Overall messaging rates including acknowledgements, delieveries, redeliveries, and publishes.' + }, + + 'rabbitmq.global_counts': { + info: 'Overall totals for channels, consumers, connections, queues and exchanges.' + }, + + 'rabbitmq.file_descriptors': { + info: 'Total number of used filed descriptors. See <code><a href="https://www.rabbitmq.com/production-checklist.html#resource-limits-file-handle-limit" target="_blank">Open File Limits</a></code> for further details.', + colors: NETDATA.colors[3] + }, + + 'rabbitmq.sockets': { + info: 'Total number of used socket descriptors. Each used socket also counts as a used file descriptor. See <code><a href="https://www.rabbitmq.com/production-checklist.html#resource-limits-file-handle-limit" target="_blank">Open File Limits</a></code> for further details.', + colors: NETDATA.colors[3] + }, + + 'rabbitmq.processes': { + info: 'Total number of processes running within the Erlang VM. This is not the same as the number of processes running on the host.', + colors: NETDATA.colors[3] + }, + + 'rabbitmq.erlang_run_queue': { + info: 'Number of Erlang processes the Erlang schedulers have queued to run.', + colors: NETDATA.colors[3] + }, + + 'rabbitmq.memory': { + info: 'Total amount of memory used by the RabbitMQ. This is a complex statistic that can be further analyzed in the management UI. See <code><a href="https://www.rabbitmq.com/production-checklist.html#resource-limits-ram" target="_blank">Memory</a></code> for further details.', + colors: NETDATA.colors[3] + }, + + 'rabbitmq.disk_space': { + info: 'Total amount of disk space consumed by the message store(s). See <code><a href="https://www.rabbitmq.com/production-checklist.html#resource-limits-disk-space" target=_"blank">Disk Space Limits</a></code> for further details.', + colors: NETDATA.colors[3] + }, + + // ------------------------------------------------------------------------ + // ntpd + + 'ntpd.sys_offset': { + info: 'For hosts without any time critical services an offset of < 100 ms should be acceptable even with high network latencies. For hosts with time critical services an offset of about 0.01 ms or less can be achieved by using peers with low delays and configuring optimal <b>poll exponent</b> values.', + colors: NETDATA.colors[4] + }, + + 'ntpd.sys_jitter': { + info: 'The jitter statistics are exponentially-weighted RMS averages. The system jitter is defined in the NTPv4 specification; the clock jitter statistic is computed by the clock discipline module.' + }, + + 'ntpd.sys_frequency': { + info: 'The frequency offset is shown in ppm (parts per million) relative to the frequency of the system. The frequency correction needed for the clock can vary significantly between boots and also due to external influences like temperature or radiation.', + colors: NETDATA.colors[2], + height: 0.6 + }, + + 'ntpd.sys_wander': { + info: 'The wander statistics are exponentially-weighted RMS averages.', + colors: NETDATA.colors[3], + height: 0.6 + }, + + 'ntpd.sys_rootdelay': { + info: 'The rootdelay is the round-trip delay to the primary reference clock, similar to the delay shown by the <code>ping</code> command. A lower delay should result in a lower clock offset.', + colors: NETDATA.colors[1] + }, + + 'ntpd.sys_stratum': { + info: 'The distance in "hops" to the primary reference clock', + colors: NETDATA.colors[5], + height: 0.3 + }, + + 'ntpd.sys_tc': { + info: 'Time constants and poll intervals are expressed as exponents of 2. The default poll exponent of 6 corresponds to a poll interval of 64 s. For typical Internet paths, the optimum poll interval is about 64 s. For fast LANs with modern computers, a poll exponent of 4 (16 s) is appropriate. The <a href="http://doc.ntp.org/current-stable/poll.html">poll process</a> sends NTP packets at intervals determined by the clock discipline algorithm.', + height: 0.5 + }, + + 'ntpd.sys_precision': { + colors: NETDATA.colors[6], + height: 0.2 + }, + + 'ntpd.peer_offset': { + info: 'The offset of the peer clock relative to the system clock in milliseconds. Smaller values here weight peers more heavily for selection after the initial synchronization of the local clock. For a system providing time service to other systems, these should be as low as possible.' + }, + + 'ntpd.peer_delay': { + info: 'The round-trip time (RTT) for communication with the peer, similar to the delay shown by the <code>ping</code> command. Not as critical as either the offset or jitter, but still factored into the selection algorithm (because as a general rule, lower delay means more accurate time). In most cases, it should be below 100ms.' + }, + + 'ntpd.peer_dispersion': { + info: 'This is a measure of the estimated error between the peer and the local system. Lower values here are better.' + }, + + 'ntpd.peer_jitter': { + info: 'This is essentially a remote estimate of the peer\'s <code>system_jitter</code> value. Lower values here weight highly in favor of peer selection, and this is a good indicator of overall quality of a given time server (good servers will have values not exceeding single digit milliseconds here, with high quality stratum one servers regularly having sub-millisecond jitter).' + }, + + 'ntpd.peer_xleave': { + info: 'This variable is used in interleaved mode (used only in NTP symmetric and broadcast modes). See <a href="http://doc.ntp.org/current-stable/xleave.html">NTP Interleaved Modes</a>.' + }, + + 'ntpd.peer_rootdelay': { + info: 'For a stratum 1 server, this is the access latency for the reference clock. For lower stratum servers, it is the sum of the <code>peer_delay</code> and <code>peer_rootdelay</code> for the system they are syncing off of. Similarly to <code>peer_delay</code>, lower values here are technically better, but have limited influence in peer selection.' + }, + + 'ntpd.peer_rootdisp': { + info: 'Is the same as <code>peer_rootdelay</code>, but measures accumulated <code>peer_dispersion</code> instead of accumulated <code>peer_delay</code>.' + }, + + 'ntpd.peer_hmode': { + info: 'The <code>peer_hmode</code> and <code>peer_pmode</code> variables give info about what mode the packets being sent to and received from a given peer are. Mode 1 is symmetric active (both the local system and the remote peer have each other declared as peers in <code>/etc/ntp.conf</code>), Mode 2 is symmetric passive (only one side has the other declared as a peer), Mode 3 is client, Mode 4 is server, and Mode 5 is broadcast (also used for multicast and manycast operation).', + height: 0.2 + }, + + 'ntpd.peer_pmode': { + height: 0.2 + }, + + 'ntpd.peer_hpoll': { + info: 'The <code>peer_hpoll</code> and <code>peer_ppoll</code> variables are log2 representations of the polling interval in seconds.', + height: 0.5 + }, + + 'ntpd.peer_ppoll': { + height: 0.5 + }, + + 'ntpd.peer_precision': { + height: 0.2 + }, + + 'spigotmc.tps': { + info: 'The running 1, 5, and 15 minute average number of server ticks per second. An idealized server will show 20.0 for all values, but in practice this almost never happens. Typical servers should show approximately 19.98-20.0 here. Lower values indicate progressively more server-side lag (and thus that you need better hardware for your server or a lower user limit). For every 0.05 ticks below 20, redstone clocks will lag behind by approximately 0.25%. Values below approximately 19.50 may interfere with complex free-running redstone circuits and will noticeably slow down growth.' + }, + + 'spigotmc.users': { + info: 'THe number of currently connect users on the monitored Spigot server.' + }, + + 'unbound.queries': { + info: 'Shows the number of queries being processed of each type. Note that <code>Recursive</code> queries are also accounted as cache misses.' + }, + + 'unbound.reqlist': { + info: 'Shows various stats about Unbound\'s internal request list.' + }, + + 'unbound.recursion': { + info: 'Average and median time to complete recursive name resolution.' + }, + + 'unbound.cache': { + info: 'The number of items in each of the various caches.' + }, + + 'unbound.threads.queries': { + height: 0.2 + }, + + 'unbound.threads.reqlist': { + height: 0.2 + }, + + 'unbound.threads.recursion': { + height: 0.2 + }, + + 'boinc.tasks': { + info: 'The total number of tasks and the number of active tasks. Active tasks are those which are either currently being processed, or are partialy processed but suspended.' + }, + + 'boinc.states': { + info: 'Counts of tasks in each task state. The normal sequence of states is <code>New</code>, <code>Downloading</code>, <code>Ready to Run</code>, <code>Uploading</code>, <code>Uploaded</code>. Tasks which are marked <code>Ready to Run</code> may be actively running, or may be waiting to be scheduled. <code>Compute Errors</code> are tasks which failed for some reason during execution. <code>Aborted</code> tasks were manually cancelled, and will not be processed. <code>Failed Uploads</code> are otherwise finished tasks which failed to upload to the server, and usually indicate networking issues.' + }, + + 'boinc.sched': { + info: 'Counts of active tasks in each scheduling state. <code>Scheduled</code> tasks are the ones which will run if the system is permitted to process tasks. <code>Preempted</code> tasks are on standby, and will run if a <code>Scheduled</code> task stops running for some reason. <code>Uninitialized</code> tasks should never be present, and indicate tha the scheduler has not tried to schedule them yet.' + }, + + 'boinc.process': { + info: 'Counts of active tasks in each process state. <code>Executing</code> tasks are running right now. <code>Suspended</code> tasks have an associated process, but are not currently running (either because the system isn\'t processing any tasks right now, or because they have been preempted by higher priority tasks). <code>Quit</code> tasks are exiting gracefully. <code>Aborted</code> tasks exceeded some resource limit, and are being shut down. <code>Copy Pending</code> tasks are waiting on a background file transfer to finish. <code>Uninitialized</code> tasks do not have an associated process yet.' + }, + + 'w1sensor.temp': { + info: 'Temperature derived from 1-Wire temperature sensors.' + }, + + 'logind.sessions': { + info: 'Shows the number of active sessions of each type tracked by logind.' + }, + + 'logind.users': { + info: 'Shows the number of active users of each type tracked by logind.' + }, + + 'logind.seats': { + info: 'Shows the number of active seats tracked by logind. Each seat corresponds to a combination of a display device and input device providing a physical presence for the system.' + }, + + // ------------------------------------------------------------------------ + // ProxySQL + + 'proxysql.pool_status': { + info: 'The status of the backend servers. ' + + '<code>1=ONLINE</code> backend server is fully operational, ' + + '<code>2=SHUNNED</code> backend sever is temporarily taken out of use because of either too many connection errors in a time that was too short, or replication lag exceeded the allowed threshold, ' + + '<code>3=OFFLINE_SOFT</code> when a server is put into OFFLINE_SOFT mode, new incoming connections aren\'t accepted anymore, while the existing connections are kept until they became inactive. In other words, connections are kept in use until the current transaction is completed. This allows to gracefully detach a backend, ' + + '<code>4=OFFLINE_HARD</code> when a server is put into OFFLINE_HARD mode, the existing connections are dropped, while new incoming connections aren\'t accepted either. This is equivalent to deleting the server from a hostgroup, or temporarily taking it out of the hostgroup for maintenance work, ' + + '<code>-1</code> Unknown status.' + }, + + 'proxysql.pool_net': { + info: 'The amount of data sent to/received from the backend ' + + '(This does not include metadata (packets\' headers, OK/ERR packets, fields\' description, etc).' + }, + + 'proxysql.pool_overall_net': { + info: 'The amount of data sent to/received from the all backends ' + + '(This does not include metadata (packets\' headers, OK/ERR packets, fields\' description, etc).' + }, + + 'proxysql.questions': { + info: '<code>questions</code> total number of queries sent from frontends, ' + + '<code>slow_queries</code> number of queries that ran for longer than the threshold in milliseconds defined in global variable <code>mysql-long_query_time</code>. ' + }, + + 'proxysql.connections': { + info: '<code>aborted</code> number of frontend connections aborted due to invalid credential or max_connections reached, ' + + '<code>connected</code> number of frontend connections currently connected, ' + + '<code>created</code> number of frontend connections created, ' + + '<code>non_idle</code> number of frontend connections that are not currently idle. ' + }, + + 'proxysql.pool_latency': { + info: 'The currently ping time in microseconds, as reported from Monitor.' + }, + + 'proxysql.queries': { + info: 'The number of queries routed towards this particular backend server.' + }, + + 'proxysql.pool_used_connections': { + info: 'The number of connections are currently used by ProxySQL for sending queries to the backend server.' + }, + + 'proxysql.pool_free_connections': { + info: 'The number of connections are currently free. They are kept open in order to minimize the time cost of sending a query to the backend server.' + }, + + 'proxysql.pool_ok_connections': { + info: 'The number of connections were established successfully.' + }, + + 'proxysql.pool_error_connections': { + info: 'The number of connections weren\'t established successfully.' + }, + + 'proxysql.commands_count': { + info: 'The total number of commands of that type executed' + }, + + 'proxysql.commands_duration': { + info: 'The total time spent executing commands of that type, in ms' + }, + + // ------------------------------------------------------------------------ + // Power Supplies + + 'powersupply.capacity': { + info: undefined + }, + + 'powersupply.charge': { + info: undefined + }, + + 'powersupply.energy': { + info: undefined + }, + + 'powersupply.voltage': { + info: undefined + } + + // ------------------------------------------------------------------------ +}; diff --git a/web/gui/dashboard_info_custom_example.js b/web/gui/dashboard_info_custom_example.js new file mode 100644 index 0000000..6a2d537 --- /dev/null +++ b/web/gui/dashboard_info_custom_example.js @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +/* + * Custom netdata information file + * ------------------------------- + * + * Use this file to add custom information on netdata dashboards: + * + * 1. Copy it to a new filename (so that it will not be overwritten with netdata updates) + * 2. Edit it to fit your needs + * 3. Set the following option to /etc/netdata/netdata.conf : + * + * [web] + * custom dashboard_info.js = your_filename.js + * + * Using this file you can: + * + * 1. Overwrite or add messages to menus, submenus and charts. + * Use dashboard_info.js to find out what you can define. + * + * 2. Inject javascript code into the default netdata dashboard. + * + */ + +// Codacy declarations +/* global customDashboard */ + +// ---------------------------------------------------------------------------- +// MENU +// +// - title the menu title as to be rendered at the charts menu +// - icon html fragment of the icon to display +// - info html fragment for the description above all the menu charts + +customDashboard.menu = { + +}; + + +// ---------------------------------------------------------------------------- +// SUBMENU +// +// - title the submenu title as to be rendered at the charts menu +// - info html fragment for the description above all the submenu charts + +customDashboard.submenu = { + +}; + + +// ---------------------------------------------------------------------------- +// CONTEXT (the template each chart is based on) +// +// - info html fragment for the description above the chart +// - height a ratio to the default as a decimal number: 1.0 = 100% +// - colors a single color or an array of colors to use for the dimensions +// - valuerange the y-range of the chart as an array [min, max] +// - heads an array of gauge charts to render above the submenu section +// - mainheads an array of gauge charts to render at the menu section + +customDashboard.context = { + +}; diff --git a/web/gui/demo.html b/web/gui/demo.html new file mode 100644 index 0000000..68f374b --- /dev/null +++ b/web/gui/demo.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <title>NetData Dashboard</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + <meta name="author" content="costa@tsaousis.gr"> + + <meta property="og:locale" content="en_US" /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png"/> + <meta property="og:url" content="http://my-netdata.io/"/> + <meta property="og:type" content="website"/> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> + <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> +</head> +<script type="text/javascript" src="dashboard.js?v20170724-1"></script> +<body> + +<div style="width: 100%; text-align: center;"> + <div data-netdata="netdata.server_cpu" + data-dimensions="user" + data-chart-library="gauge" + data-width="150px" + data-after="-60" + data-points="60" + data-title="Yes! Realtime!" + data-units="I am alive!" + data-colors="#FF5555" + ></div> + <br/> + <div data-netdata="netdata.server_cpu" + data-dimensions="user" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-width="200px" + data-height="30px" + data-after="-60" + data-points="60" + data-colors="#FF5555" + ></div> +</div> +</body> +</html> diff --git a/web/gui/demo2.html b/web/gui/demo2.html new file mode 100644 index 0000000..183a955 --- /dev/null +++ b/web/gui/demo2.html @@ -0,0 +1,143 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <title>NetData Dashboard</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + <meta name="author" content="costa@tsaousis.gr"> + + <meta property="og:locale" content="en_US" /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png"/> + <meta property="og:url" content="http://my-netdata.io/"/> + <meta property="og:type" content="website"/> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> + <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> +</head> +<script>var netdataTheme = 'slate';</script> +<script type="text/javascript" src="http://my-netdata.io/dashboard.js?v20170724-1"></script> +<body> + +<div class="container" style="width: 90%; padding-top: 10px; text-align: center; color: #AAA"> + <div style="font-size: 7vw;">why netdata?</div> + <br/> + <div style="font-size: 2vw; color: white;">These charts visualize the same data...</div> + + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist"> + <li role="presentation" class="active"><a href="#gauge" aria-controls="gauge" role="tab" data-toggle="tab">Gauge.js</a></li> + <li role="presentation"><a href="#easypiechart" aria-controls="easypiechart" role="tab" data-toggle="tab">Easy Pie Chart</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="gauge"> + + <div style="display: inline-block; width: 35.8%"> + <div style="font-size: 1.2vw; color: #666; padding-top: 10px;"><i class="fa fa-comment"></i> I can trace an issue like this</div> + <br/> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="gauge" + data-gauge-max-value="32767" + data-width="100%" + data-after="-600" + data-points="600" + data-title="1/second (netdata default)" + data-units="important metric" + data-colors="#5A5" + ></div> + </div> + <div style="display: inline-block; width: 50%"> + <div style="font-size: 1.2vw; color: #666;"><i class="fa fa-comment"></i> Can you trace an issue like these?<br/> <br/></div> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="gauge" + data-gauge-max-value="32767" + data-width="45%" + data-after="-600" + data-points="60" + data-title="Updates Every 10 Sec" + data-units="important metric" + data-colors="#C55" + ></div> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="gauge" + data-gauge-max-value="32767" + data-width="45%" + data-after="-600" + data-points="2" + data-title="Updates Every 5 Mins" + data-units="important metric" + data-colors="#C55" + ></div> + </div> + </div> + <div role="tabpanel" class="tab-pane" id="easypiechart"> + + <div style="display: inline-block; width: 25%"> + <div style="font-size: 1.2vw; color: #666; padding-top: 10px;"><i class="fa fa-comment"></i> I can trace an issue like this</div> + <br/> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="easypiechart" + data-easypiechart-max-value="32767" + data-width="100%" + data-after="-600" + data-points="600" + data-title="1/second (netdata default)" + data-units="important metric" + data-colors="#5A5" + ></div> + </div> + <div style="display: inline-block; width: 40%"> + <div style="font-size: 1.2vw; color: #666;"><i class="fa fa-comment"></i> Can you trace an issue like these?<br/> <br/></div> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="easypiechart" + data-easypiechart-max-value="32767" + data-width="45%" + data-after="-600" + data-points="60" + data-title="Updates Every 10 Sec" + data-units="important metric" + data-colors="#C55" + ></div> + <div data-netdata="example.random2" + data-dimensions="random" + data-chart-library="easypiechart" + data-easypiechart-max-value="32767" + data-width="45%" + data-after="-600" + data-points="2" + data-title="Updates Every 5 Mins" + data-units="important metric" + data-colors="#C55" + ></div> + </div> + </div> + </div> + <div style="font-size: 1.5vw;">Hover on the chart below, to see the selected value on the charts above!</div> + <div data-netdata="example.random2" + data-dimensions="random" + data-dygraph-theme="sparkline" + data-width="100%" + data-height="20vh" + data-after="-600" + data-points="600" + data-title="1/second (netdata default)" + data-units="something" + data-colors="#888" + ></div> +</div> +</body> +</html> diff --git a/web/gui/demosites.html b/web/gui/demosites.html new file mode 100644 index 0000000..33a771d --- /dev/null +++ b/web/gui/demosites.html @@ -0,0 +1,1501 @@ +<!doctype html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang=en-us xmlns="http://www.w3.org/1999/html"> +<head> + <meta charset=utf-8> + <title>NetData: Get control of your Linux Servers. Simple. Effective. Awesome.</title> + <meta name=author content="Costa Tsaousis"> + <meta name=description content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms."> + + <meta name=viewport content="width=device-width,initial-scale=1"> + <link rel=apple-touch-icon href=apple-touch-icon.png> + <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACNklEQVRYhcXXv2tUQRAH8M+FEIJISBHCIWIhIQSUILERi4AiiqCggiIiomAjlhaC4j+ghYWISgqNohZaCBZBC8Ei8QdEUCutFBsxCBqDYkgci/cunkfuJffjJQPD8mZm5/vd2WV2HzlJ0Bs8CvrywsgCHwy+BpGOg0sJfjj4nYKX9FdwKG9gwZlgtgK8pLOpPxfw1mCoCnClDgWtzQTvCEYWCV7SkWAlFBoEb8dlDKBF8t2bMWUSH/AHr3CiEfz5CPUusPJLkRCdk5ZqyeqUrQv4R7E5TwK7M3zTeIKduRAIitiWEfIY69GdCwGcRFuG/xqONRkzkaA7+J5x+MaDtWmHvJ4HgeEM8Nn0bridfv9HoOFyBAdwJCPkqqTzHWwUaz7wgeBHxupfBKuCj2W25mxBsCGYyAB/FxTT27HcPlyep64tCLbjKbqqhLzBlgKfF8pVE4FgRXABI+ioEnYfOyzcFWsCbg+OV+xlpU4ER4O+4HVwL51b3xYEXcGu4Ao+YQhr5gmdxHmsQyfG0b/YxbWmLfRWmnxa0s06VbTMCpnBS9zFzQKTwR5cXCzwHIE02Sl8wSZsRI/kgLVJqjSd+t9LVjiG1diPszhdK3A5gR48k5zYMTwscC59sfT799CYKvA8EttbSeXgTr3gJQKl91kR+yTlvyG5uUbLYh9gb+ovltkb6qYtNSRo3kOygsBSzGlKsubf43USWLYK5CLLXoFWyU/CtzLbVDpW2n+m40yN9ukqdvAX9ac/EIgOapcAAAAASUVORK5CYII="> + + <meta property="og:url" content="https://my-netdata.io" /> + <meta property="og:type" content="website" /> + <meta property="og:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta property="og:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png" /> + <meta property="og:image:type" content="image/png" /> + <meta property="fb:app_id" content="1200089276712916" /> + + <meta name="twitter:card" content="summary" /> + <meta name="twitter:site" content="@linuxnetdata" /> + <meta name="twitter:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" /> + + <meta name="google-site-verification" content="3Xmk2kyCvai8p9HEnYHoQ9RBW20-b1NvPAgu07Fkkds" /> + <meta name="msvalidate.01" content="896DCA31C9A664CE359FCF1A645DD476" /> + + <style>/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ +html { + line-height: 1.15; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + color: #fff; + font: 17px/1.4 'Open Sans', sans-serif; + text-align: center +} + +body { + margin: 0; + background-color: #2f3135; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADoAAAA9BAMAAAAOkGejAAAAGFBMVEUKCgoUFBQAAAAPDw8ZGRkeHh4jIyMFBQUUJmucAAAACHRSTlMzMzMzMzMzM85JBgUAAAV1SURBVDjLBQC3tkMA9OqrbtWtCKwErLoVhDUP5PffAUvqhtJFWytU/UqOWbf0nG8ZSVyyfSPwrjqzxYailPJtJu/uihN7np+51RrBgYosPTzBElTZCg8JieV4W/HJciqhFwhQLBmkX5JnNzzMlOGvQChGCKbanFWBgVeRCr9L6BZCgZxB/0wN7zTO2QuP80SIL3F5Ydbnhz12iE/nSOMrqwK/OMfbAYHkioJlnlj9CKUbeomN61U5LQ6nWRmg+tfrDusm2LHGDnRDdHUp5CLTvoHrwgtZlIr/+FyoPz2tz/HiQzc8x1TWqAZp99yto4qGuAs20qucNqPyUAyqHuAp2Hhv0OR1LC+g2voMngjB2uvyVvf0aFhD1Mi/f5Q6MER7SzJWu2AW3my9l8mB4W3WfCqwf+ikfc7pudFVvOMy0ikuSoF47zw6UYPxdqWRRSRo91RZtWYa/sQeri7tMPKcCao0vs9QTQC+8CuoReAkHuKRZCi2qtv9zJLAHfSoRltH/+sj9rlgdBTsfUbTEb7oTbTJ8acxbjMQnaftBkRVVerOeKhKr3jkRzTzqS6RpJNvF0MhOBQm/BRXor/MU/YjObdYIu1/iaQ+IviYnlsG6r3cbQoB7cj4SPgMSkLzgIM24+LSjb2sYxWDtIhCdzBfS5Kh768XgH5jkSLjrvRX/nQnv+SXQMvagpPVScAZwWhVbvPdPqcr3X/u8z558ddIdjmVMH9CIVvrW+8rPVq6M54Pf+tebGkIXwPevaCgdQ59wWbULrPB4dPT8suLWr13YKUuDNTpGBspJ9fPGSNOEjp2TYXTIgF8QgEtzX0gIbXRP8JGMbxh1uHA/CwE4a/KHUc8KzV868fO4o+8GNcNvdPaKfzprkunXIthFS9MqpEG1p7ozWTJTcnAlvUnjixEaGn5ll1yuZbtIgS/r2ISBSDE2nsksYx7YFwH2ytB0rXzqh52qJowchJSI3RJmxHeJGZFDq37LWVmzvkgA7zjT2iOsHsdb9viBQLPx3gUmys1cQG6HOEsopo6glj0VXdyli/FJsnSbg5FQLpDO1xiy0ozQy0InDVNZTuXbhENG9gu28ZoHg/de53YTAVqCwl966V7VX/g+AW3ysMyMjXNhOuaLFmBJ2Z1x9LfG55m/34snAnOgXbMqZIbaop8Zjk5P3fAw9h8vkwHKZAC7yqW6+85ZdpAFD8iAjbVRj8BI3PMYJ2oiKNrZHKSnfNJ2UZwtcT9IryvNrGxdqtCx4vc74z39odPA/h5f/MJu46HKUOcbURZd/E2QH6Kgv8Aa2PSevG2gMfoYHWdN38kadbiFHonAjv50PjgyFZwannFGebUjVmxFnokoTbwWBNVd7qx9KG1joZ69npEk0jRr7/aBYQ5ipNcGRvqjeT+kFjTgv7n33L0zlBIH6CoeaPm9eQN6uKmSwE/LAtDPgMNAOQ5X1Vr8Zd0BQlLTV88U6LzD+6iwQp9NSHD5uCcqml/N0NgRmDN9vNS6A/QJBm2jvBbFTLvly/mtLX1rg5kwgPvA4rA+LIdN3bkVvhrqk8OUYZpuYxaXW/gPVlDxtru6+3Z0KY5DMac3pQzo8y7hO2qxdd6lnvUSdXfFRduigV0YuZv9peBHwHix+d4M7fL/Y44jX6S5ZdOzBoEC2fEohdSE7PTjRBUT3T+jclLxWbKdEOoiuB81dV0xo2pFPOXZmpEMueTDrAjAr8k6y15pMsoCHOyT5qlyWn85HLLuyyAWMlmmjYSNKnv9nRsTib5DSbWLPkJjoVihW/eRQqy/dja151zycTHTBmuroDeXRvVzJ3VFWB65e+L6xu+D5fa+D0BESL4VjlKSKrvs9W69lhj2345pBjIr3+RSJFuS0A/sQAAAABJRU5ErkJggg==) +} + +a { + background-color: transparent; + -webkit-text-decoration-skip: objects; + color: #069; + text-decoration: none +} + +a:active, a:hover { + outline-width: 0 +} + +strong { + font-weight: bolder +} + +h1 { + font-size: 2.9em; + line-height: 1.2em; + margin: 0 .5em .75em +} + +img { + border-style: none; + vertical-align: middle +} + +[type=button]::-moz-focus-inner, [type=reset]::-moz-focus-inner, [type=submit]::-moz-focus-inner, button::-moz-focus-inner { + border-style: none; + padding: 0 +} + +[type=button]:-moz-focusring, [type=reset]:-moz-focusring, [type=submit]:-moz-focusring, button:-moz-focusring { + outline: 1px dotted ButtonText +} + +a:active, a:focus, a:hover { + text-decoration: underline; +} + +::-moz-selection { + background-color: #b3d4fc; + text-shadow: none; +} + +::selection { + background-color: #b3d4fc; + text-shadow: none; +} + +h2 { + font-size: 2em; + margin: 1.5em 0; +} + +h3 { + color: #555; + font-size: 1.5em; + margin: 0 0 .5em; +} + +p { + margin: 0 0 2em; +} + +.quote { + font-size: 1.15em; + margin: 0 0 .5em; + text-align: center; +} + +.title { + /* opacity: 0; */ + /* transition: opacity 500ms; */ +} + +.titlefadein { + opacity: 1; + transition: opacity 500ms; +} + +.grid { + margin: 0 -15px; + letter-spacing: -.31em; + word-spacing: -.43em; + text-rendering: optimizespeed +} + +.grid-title { + text-align: left; +} + +.grid-cell { + display: inline-block; + letter-spacing: normal; + text-align: left; + text-rendering: auto; + vertical-align: top; + width: 50%; + word-spacing: normal +} + +.grid-cell > * { + padding: 0 15px +} + +.inline-block-list { + list-style-type: none; + margin: 0; + padding: 0 +} + +.inline-block-list li { + display: inline-block; + margin: 0 0 0 1.5em; + padding: 0; + vertical-align: top +} + +.inline-block-list li:first-child { + margin-left: 0 +} + +.flex-embed { + background-color: #000; + box-shadow: 0 0 10px #000; + height: 0; + overflow: hidden; + padding-bottom: 56.25%; + position: relative +} + +.flex-embed a, .flex-embed img { + bottom: 0; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100% +} + +.flex-embed .play-btn { + background: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj48cGF0aCBkPSJNMjU2LDkyLjQ4MWM0NC40MzMsMCw4Ni4xOCwxNy4wNjgsMTE3LjU1Myw0OC4wNjRDNDA0Ljc5NCwxNzEuNDExLDQyMiwyMTIuNDEzLDQyMiwyNTUuOTk5cy0xNy4yMDYsODQuNTg4LTQ4LjQ0OCwxMTUuNDU1Yy0zMS4zNzIsMzAuOTk0LTczLjEyLDQ4LjA2NC0xMTcuNTUyLDQ4LjA2NHMtODYuMTc5LTE3LjA3LTExNy41NTItNDguMDY0QzEwNy4yMDYsMzQwLjU4Nyw5MCwyOTkuNTg1LDkwLDI1NS45OTlzMTcuMjA2LTg0LjU4OCw0OC40NDgtMTE1LjQ1M0MxNjkuODIxLDEwOS41NSwyMTEuNTY4LDkyLjQ4MSwyNTYsOTIuNDgxIE0yNTYsNTIuNDgxIGMtMTEzLjc3MSwwLTIwNiw5MS4xMTctMjA2LDIwMy41MThjMCwxMTIuMzk4LDkyLjIyOSwyMDMuNTIsMjA2LDIwMy41MmMxMTMuNzcyLDAsMjA2LTkxLjEyMSwyMDYtMjAzLjUyQzQ2MiwxNDMuNTk5LDM2OS43NzIsNTIuNDgxLDI1Niw1Mi40ODFMMjU2LDUyLjQ4MXogTTIwNi41NDQsMzU3LjE2MVYxNTkuODMzbDE2MC45MTksOTguNjY2TDIwNi41NDQsMzU3LjE2MXoiPjwvcGF0aD48L3N2Zz4K); + height: 150px; + left: 50%; + margin-left: -75px; + margin-top: -75px; + position: absolute; + top: 50%; + -webkit-transition: 1s; + transition: 1s; + width: 150px +} + +.flex-embed:hover .play-btn { + opacity: .5 +} + +.clearfix:after, .clearfix:before { + content: ' '; + display: table +} + +.clearfix:after { + clear: both +} + +.clearfix { + *zoom: 1 +} + +.container { + margin: 0 auto; + max-width: 760px; + padding: 0 10px +} + +.aside { + background-color: #eee; + border: solid #e3e3e3; + border-width: 1px 0; + font-size: 1.125em; + padding: 1em 0 +} + +.btn, .cta-option { + display: inline-block; + position: relative +} + +.cta-option { + margin: 2.5em .5em 0; + vertical-align: top +} + +.btn { + color: #fff; + font-size: 1.5em; + padding: .6em 1em; + text-decoration: none; + text-shadow: 0 -1px 0 rgba(0, 0, 0, .5); + vertical-align: middle; + border-radius: 4px; + border: 1px solid #333 +} + +.btn:active, .btn:focus, .btn:hover { + text-decoration: none +} + +.btn-download { + background-color: #d9750b; + background-image: -webkit-linear-gradient(#f90 10%, #e76a00 100%); + background-image: linear-gradient(#f90 10%, #e76a00 100%); + box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 1px 3px rgba(0, 0, 0, .2); + border: 1px solid #995309 +} + +.btn-download:active, .btn-download:focus, .btn-download:hover { + background-color: #e0811b; + background-image: -webkit-linear-gradient(#f0a100 10%, #f70 100%); + background-image: linear-gradient(#f0a100 10%, #f70 100%) +} + +.btn-download:active { + background-color: #cf6a00; + box-shadow: 0 2px 3px 0 rgba(0, 0, 0, .2) inset +} + +.btn-alt { + background-color: #444; + border-color: #222; + box-shadow: none; + font-size: 1.25em; + margin-top: .25em +} + +.btn-alt:active, .btn-alt:focus, .btn-alt:hover { + background-color: #555 +} + +.star { + color: #e08524 +} + +.Icon { + display: inline-block; + height: 16px; + margin: -3px 1px 0 0; + vertical-align: middle; + width: 16px +} + +.Icon--github { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMjEgMTIxIj48ZyBmaWxsPSIjMTkxNzE3Ij48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTYwLjUgMS42Yy0zMy4zIDAtNjAuNCAyNy02MC40IDYwLjQgMCAyNi43IDE3LjMgNDkuMyA0MS4zIDU3LjMgMyAuNiA0LjEtMS4zIDQuMS0yLjkgMC0xLjQtLjEtNi4yLS4xLTExLjItMTYuNyAzLjYtMjAuMy03LjItMjAuMy03LjItMi43LTctNi43LTguOC02LjctOC44LTUuNS0zLjcuNC0zLjcuNC0zLjcgNi4xLjQgOS4zIDYuMiA5LjMgNi4yIDUuNCA5LjIgMTQuMSA2LjYgMTcuNiA1IC41LTMuOSAyLjEtNi42IDMuOC04LjEtMTMuNC0xLjQtMjcuNS02LjYtMjcuNS0yOS44IDAtNi42IDIuNC0xMiA2LjItMTYuMi0uNi0xLjUtMi43LTcuNy42LTE2IDAgMCA1LjEtMS42IDE2LjYgNi4yIDQuOC0xLjMgMTAtMiAxNS4xLTJzMTAuMy43IDE1LjEgMmMxMS41LTcuOCAxNi42LTYuMiAxNi42LTYuMiAzLjMgOC4zIDEuMiAxNC41LjYgMTYgMy45IDQuMiA2LjIgOS42IDYuMiAxNi4yIDAgMjMuMi0xNC4xIDI4LjMtMjcuNSAyOS44IDIuMiAxLjkgNC4xIDUuNSA0LjEgMTEuMiAwIDguMS0uMSAxNC42LS4xIDE2LjYgMCAxLjYgMS4xIDMuNSA0LjEgMi45IDI0LTggNDEuMy0zMC42IDQxLjMtNTcuMyAwLTMzLjQtMjctNjAuNC02MC40LTYwLjR6Ii8+PHBhdGggZD0iTTIzIDg4LjNjLS4xLjMtLjYuNC0xIC4ycy0uNy0uNi0uNS0uOWMuMS0uMy42LS40IDEtLjJzLjYuNi41Ljl6bS0uOC0uNU0yNS40IDkxYy0uMy4zLS45LjEtMS4yLS4zLS40LS40LS41LTEtLjItMS4zLjMtLjMuOC0uMSAxLjIuMy41LjUuNSAxLjEuMiAxLjN6bS0uNS0uNk0yNy44IDk0LjVjLS40LjMtMSAwLTEuMy0uNS0uNC0uNS0uNC0xLjIgMC0xLjQuNC0uMyAxIDAgMS4zLjUuNC41LjQgMS4xIDAgMS40em0wIDBNMzEuMSA5Ny45Yy0uMy40LTEgLjMtMS42LS4yLS41LS41LS43LTEuMi0uMy0xLjUuMy0uNCAxLS4zIDEuNi4yLjUuNC42IDEuMS4zIDEuNXptMCAwTTM1LjYgOTkuOGMtLjEuNS0uOC43LTEuNS41LS43LS4yLTEuMS0uOC0xLTEuMi4xLS41LjgtLjcgMS41LS41LjcuMiAxLjEuNyAxIDEuMnptMCAwTTQwLjUgMTAwLjJjMCAuNS0uNi45LTEuMy45LS43IDAtMS4zLS40LTEuMy0uOXMuNi0uOSAxLjMtLjljLjcgMCAxLjMuNCAxLjMuOXptMCAwTTQ1LjEgOTkuNGMuMS41LS40IDEtMS4xIDEuMS0uNy4xLTEuMy0uMi0xLjQtLjctLjEtLjUuNC0xIDEuMS0xLjEuNy0uMSAxLjMuMiAxLjQuN3ptMCAwIi8+PC9nPjwvc3ZnPgo=) +} + +.Icon--html5 { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjUwIDEwMSA0MTIgNDEyIj48cGF0aCBmaWxsPSIjRTQ0RDI2IiBkPSJNMTA3LjY0NCA0NzAuODc3bC0zMy4wMTEtMzcwLjI1N2gzNjIuNzM0bC0zMy4wNDYgMzcwLjE5OS0xNDguNTQzIDQxLjE4MXoiLz48cGF0aCBmaWxsPSIjRjE2NTI5IiBkPSJNMjU2IDQ4MC41MjNsMTIwLjAzLTMzLjI3NyAyOC4yNC0zMTYuMzUyaC0xNDguMjd6Ii8+PHBhdGggZmlsbD0iI0VCRUJFQiIgZD0iTTI1NiAyNjguMjE3aC02MC4wOWwtNC4xNS00Ni41MDFoNjQuMjR2LTQ1LjQxMWgtMTEzLjg2OGwxLjA4NyAxMi4xODMgMTEuMTYxIDEyNS4xMzloMTAxLjYyem0wIDExNy45MzZsLS4xOTkuMDUzLTUwLjU3NC0xMy42NTYtMy4yMzMtMzYuMjE3aC00NS41ODVsNi4zNjIgNzEuMzAxIDkzLjAyIDI1LjgyMy4yMDktLjA1OHoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMjU1Ljg0MyAyNjguMjE3djQ1LjQxaDU1LjkxOGwtNS4yNzEgNTguODk0LTUwLjY0NyAxMy42N3Y0Ny4yNDRsOTMuMDk0LTI1LjgwMS42ODMtNy42NzIgMTAuNjcxLTExOS41NTEgMS4xMDgtMTIuMTk0aC0xMi4yMzd6bTAtOTEuOTEydjQ1LjQxMWgxMDkuNjg4bC45MTEtMTAuMjA3IDIuMDY5LTIzLjAyMSAxLjA4Ni0xMi4xODN6Ii8+PC9zdmc+Cg==) +} + +.Icon--stackoverflow { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjMgMi44IDU4LjIgNTgiPjxwYXRoIGQ9Ik05LjMwNSAzNi44NDhsNC40MDEuMDQzLS4xNTMgMTkuNTk4aDI5LjI5MXYtMTkuNTI4aDQuNjM4djI0LjI4N2gtMzguMjAxbC4wMjQtMjQuNDAxem03LjE3NyAxMS41ODZoMjIuOTQ1djQuODgyaC0yMi45NDV6IiBmaWxsPSIjOTE5MTkxIi8+PHBhdGggZmlsbD0iI2E3OGI2OCIgZD0iTTE3LjAyIDM5LjY0OGwyMi45NiAyLjIxNi0uNDgxIDQuOTgxLTIyLjk2LTIuMjE2eiIvPjxwYXRoIGZpbGw9IiNjMTk2NTMiIGQ9Ik0xOS4xMjEgMjkuNzEzbDIyLjIgNi4yNjYtMS4zNTkgNC44MTYtMjIuMi02LjI2NnoiLz48cGF0aCBmaWxsPSIjZDQ4YzI4IiBkPSJNMjQuNTAxIDE4LjQ4NGwxOS43NDUgMTEuOTI2LTIuNTg3IDQuMjgzLTE5Ljc0NS0xMS45MjZ6Ii8+PHBhdGggZmlsbD0iI2ZlODkwOCIgZD0iTTM1LjczMyA3Ljg0OWwxMy40MzUgMTguNzUxLTQuMDY4IDIuOTE0LTEzLjQzNS0xOC43NTF6Ii8+PHBhdGggZmlsbD0iI2ZmN2ExNSIgZD0iTTUxLjM0IDIuNzUxbDMuODAyIDIyLjc1Mi00LjkzNi44MjUtMy44MDItMjIuNzUyeiIvPjwvc3ZnPgo=) +} + +.site-header { + padding-top: 50px +} + +.site-logo { + color: #fff; + float: left; + font-size: 25px; + font-weight: 700; + line-height: 32px; + text-decoration: none; + text-shadow: 2px 2px 0 #000; + text-transform: uppercase +} + +.site-nav { + float: right; + list-style-type: none; + margin: 7px 0 0; + padding: 0 +} + +.site-nav a { + color: #ffa000; + display: block; + text-decoration: none; + text-transform: uppercase +} + +.site-nav a:active, .site-nav a:focus, .site-nav a:hover { + color: #fff +} + +.site-promo { + padding: 4em 0 6em; + color: white; +} + +.site-promo .description { + color: #ddd; + font-size: 1.2em; + margin: 1em 2em 0 +} + +.last-update { + color: #999; + display: block; + font-size: .75em; + margin-top: 10px +} + +.site-section { + background-color: #f9f9f9; + color: #333; + overflow: hidden; + padding: 2em 0 2em +} + +.site-section-gray { + background-color: #f5f5f5; + color: #333; + overflow: hidden; + padding: 2em 0 2em +} + +.site-section-dark { + background-color: transparent; + color: #fff; + text-align: center; + padding: 2em 0 3em +} + +.site-section-dark .content { + max-width: 720px; + margin: auto; + padding: 10px +} + +.site-section-dark h2 { + margin: 1em 0 +} +.site-section-dark h3 { + color: white; +} + +.in-the-wild { + font-size: 1.25em; + margin: 0 auto; + max-width: 720px +} + +.site-footer { + font-size: .875em; + padding: 2em +} + +.site-footer a { + color: #ffa000 +} + +@media only screen and (max-width: 800px) { + .site-logo, .site-nav { + float: none + } + + .site-nav li { + margin: 0 .5em + } + + .site-header { + padding-top: 40px + } + + .site-promo { + padding: 3em 0; + color: white; + } + + .site-section { + padding: 0 1em 4em + } +} + +@media only screen and (max-width: 600px) { + html { + font-size: 14px + } + + .last-update, .site-footer { + font-size: 1em + } +} + +@media only screen and (max-width: 460px) { + .grid-cell { + width: 100% + } +} + +@media only screen and (max-width: 420px) { + h1 { + font-size: 2.5em + } + + html { + font-size: 13px + } +} + +@media print { + * { + background-color: transparent !important; + box-shadow: none !important; + color: #000 !important; + text-shadow: none !important + } + + a, a:visited { + text-decoration: underline + } + + img { + page-break-inside: avoid; + max-width: 100% !important + } + + h1 { + padding: 1em 0 0 + } + + .site-promo { + margin: 1em; + padding: 0; + color: white; + } + + .site-section { + padding: 0; + margin: 2em 1em + } + + .site-section-dark { + display: none + } + + h2, h3, p { + orphans: 3; + widows: 3 + } + + h2, h3 { + page-break-after: avoid + } +} +</style> + +<script> + // --- OPTIONS FOR THE DASHBOARD -- + + // this section has to appear before loading dashboard.js + + // Select a theme. + // uncomment on of the two themes: + + // var netdataTheme = 'default'; // this is white + var netdataTheme = 'slate'; // this is dark + + var netdataNoBootstrap = true; + + // Set the default netdata server. + // on charts without a 'data-host', this one will be used. + // the default is the server that dashboard.js is downloaded from. + + // var netdataServer = 'http://my.server:19999/'; +</script> + +<!-- + --- LOAD dashboard.js --- + + to host this HTML file on your web server, + you have to load dashboard.js from the netdata server. + + So, pick one the two below + If you pick the first, set the server name/IP. + + The second assumes you host this file on /usr/share/netdata/web + and that you have chown it to be owned by netdata:netdata +--> +<!-- <script type="text/javascript" src="http://my.server:19999/dashboard.js"></script> --> +<script type="text/javascript" src="dashboard.js?v20170724-1"></script> + +<script> + // --- OPTIONS FOR THE CHARTS -- + + // destroy charts not shown (lowers memory on the browsers) + // set this to 'true' to destroy, 'false' to hide the charts + NETDATA.options.current.destroy_on_hide = false; + + // set this to false, to always show all dimensions + NETDATA.options.current.eliminate_zero_dimensions = true; + + // set this to false, to lower the pressure on the browser + NETDATA.options.current.concurrent_refreshes = true; + + // if you need to support slow mobile phones, set this to false + NETDATA.options.current.parallel_refresher = true; + + // set this to false, to always update the charts, even if focus is lost + NETDATA.options.current.stop_updates_when_focus_is_lost = true; + + // since we have many servers and limited sockets, + // abort ajax calls when we scroll + NETDATA.options.current.abort_ajax_on_scroll = true; + + // do not to give errors on netdata demo servers for 60 seconds + NETDATA.options.current.retries_on_data_failures = 60; +</script> + +<style> + .mygauge-combo { + display: inline-block; + } + + .mygauge-combo20 { + display: inline-block; + min-width: 150px; + width: 49%; + padding-top: 40px; + text-align: center; + } + + .mygauge-combo30 { + display: inline-block; + min-width: 150px; + width: 32%; + padding-top: 40px; + text-align: center; + } + + .mygauge { + position: relative; + display: block; + width: 171px; + /* height: 150px; */ + } + + .mygauge-button { + display: block; + } + + .mygauge-legend-button { + font-size: 13px; + } + + .mygause-donation { + font-size: 9px; + color: #999; + } + + .mysparkline { + position: relative; + display: inline-block; + width: 100%; + height: 50px; + text-align: left; + } + + .mysparkline-overchart-label { + position: absolute; + display: block; + top: -15px; + left: 10px; + bottom: 0; + right: 0; + font-size: 14px; + z-index: 1; + pointer-events: none; + } + + .mysparkline-overchart-label2 { + position: absolute; + display: block; + top: -15px; + left: 10px; + bottom: 0; + right: 0; + font-size: 8px; + color: #676b70; + z-index: 1; + pointer-events: none; + } + + .mysparkline-overchart-value { + position: absolute; + display: block; + top: 0px; + left: 10px; + bottom: 0; + right: 0; + font-size: 40px; + z-index: 2; + text-shadow: #333 0px 0px 2px; + pointer-events: none; + } + + .mysparkline-overchart-value-center { + position: absolute; + display: block; + top: 5px; + left: 0px; + bottom: 0; + right: 0; + font-size: 35px; + font-weight: bold; + text-align: center; + z-index: 2; + text-shadow: #333 0px 0px 2px; + pointer-events: none; + } + + .fb-share-button span { + top: 0px; + } + .fb-like span { + top: 0px; + } + .fb-follow span { + top: 0px; + } + +</style> +</head> +<body> +<div class=container> + <div class="site-header clearfix" role=banner> + <div class=site-logo>my-netdata.io</div> + <ul class="site-nav inline-block-list"> + <li><a href=https://github.com/netdata/netdata data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label="Source code" target="_blank">Source code</a> + <li><a href=https://docs.netdata.cloud data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Docs target="_blank">Docs</a> + </ul> + </div> + <div class=site-promo><h1><span class="title">Monitor your systems and applications, the right way!</span></h1> + <p class=description> + <strong>Unparalleled</strong> insights, in <strong>real-time</strong>, + of <strong>everything</strong> happening on your systems and applications, + with stunning, <strong>interactive</strong> web dashboards + and powerful <strong>performance</strong> and <strong>health</strong> alarms. + <div class=cta-option> + <a class="btn btn-download" href="https://docs.netdata.cloud/packaging/installer/" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Install><strong>Install netdata now</strong></a> + <a class=last-update href="https://github.com/netdata/netdata/releases" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Releases>See netdata releases</a></div> + <div class=cta-option> + <a class="btn btn-alt" href="#demosites" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Demo>netdata live demo</a> + </div> + </div> +</div> +<div class=site-section> + <div class=container><h2>Enter the world of Netdata!</h2> + <div class="grid-title"> + <h3><span class=star>★</span> 1s granularity</h3> + </div> + <div class=grid> + <div class=grid-cell> + <p> + <b>Per second</b> data collection and visualization, for all metrics! + </p> + <p> + Netdata <b>zooms into the problems</b> by providing higher resolution information, compared to any other monitoring solution. + </p> + </div> + <div class=grid-cell> + <p class="quote"><i> + The world goes real-time. + <br/> <br/> + High resolution metrics are required to effectively monitor and troubleshoot systems and applications, especially on virtual environments. + </i></p> + </div> + </div> + </div> + <div> + <a href="https://docs.netdata.cloud/docs/why-netdata/1s-granularity/">Learn more about high resolution metrics</a> + </div> +</div> + +<div class="site-section site-section-gray"> + <div class=container> + <div class="grid-title"> + <h3><span class=star>★</span> Unlimited metrics</h3> + </div> + <div class=grid> + <div class=grid-cell> + <p> + Use all the metrics, from all available sources! + </p> + <p> + Netdata collects all the metrics native console tools do. It has been <b>designed to kill the console</b> for troubleshooting infrastructure slowdowns and outages. + </p> + </div> + <div class=grid-cell> + <p class="quote"><i> + All metrics are important and all should be available when you need them. + <br/> <br/> + Filtering out most metrics is like reading a book by skipping most of its pages. + </i></p> + </div> + </div> + </div> + <div> + <a href="https://docs.netdata.cloud/docs/why-netdata/unlimited-metrics/">Learn more about unlimited metrics</a> + </div> +</div> +<div class="site-section"> + <div class=container> + <div class="grid-title"> + <h3><span class=star>★</span> Meaningful presentation</h3> + </div> + <div class=grid> + <div class=grid-cell> + <p> + Explore all metrics in a meaningful, easy to understand way! + </p> + <p> + Netdata engineers and experts on our community organize metrics in a meaningful way, so that you can learn and understand them right on the job, while troubleshooting issues of your infrastructure. + </p> + </div> + <div class=grid-cell> + <p class="quote"><i> + Metrics are a lot more than name-value pairs over time. + <br/> <br/> + It is just not practical to require from all users to have a deep understanding of all metrics for monitoring their systems and applications. + </i></p> + </div> + </div> + </div> + <div> + <a href="https://docs.netdata.cloud/docs/why-netdata/meaningful-presentation/">Learn more about meaningful presentation</a> + </div> +</div> + +<div class="site-section site-section-gray"> + <div class=container> + <div class="grid-title"> + <h3><span class=star>★</span> Immediate results</h3> + </div> + <div class=grid> + <div class=grid-cell> + <p> + Install and use immediately! Get fully functional visualization and alarms, in just a couple of seconds after installation! + </p> + <p> + Netdata <b>decouples your skills from your monitoring infrastructure</b>. + No matter how skillful or novice you are, Netdata will apply all the community knowledge and expertise to your monitoring infrastructure. + </p> + </div> + <div class=grid-cell> + <p class="quote"><i> + Most of our infrastructure is based on standardized systems and applications. + <br/> <br/> + It is a tremendous waste of time and effort, in a global scale, to require from all users to configure their infrastructure dashboards and alarms metric by metric. + </i></p> + </div> + </div> + </div> + <div> + <a href="https://docs.netdata.cloud/docs/why-netdata/immediate-results/">Learn more about immediate results</a> + </div> +</div> + +<div class="site-section site-section-dark"> + <div class=container><h2>How it works</h2> + <div style="padding-bottom: 1em"> + <p> + Netdata is a monitoring agent you install on all your systems: + <br/> + <b>physical servers</b>, <b>virtual servers</b>, <b>containers</b>, <b>IoT</b>. + </p> + <p> + Netdata is lightweight, designed to permanently run on all systems without disrupting their core function. + By default, it needs just 1% CPU of a single core, a few MB or RAM and no disk I/O at all. + </p> + <p> + Each Netdata is (by default) autonomous, taking care of all the following. + <br/>But all your Netdata are integrated into one large distributed application. + </p> + </div> + <div class=grid> + <div class=grid-cell><h3><span class=star>★</span> Collect</h3> + <p> + Netdata automatically detects data collection sources on the host it runs. + It comes with hundreds of plugins for collecting system and application metrics, + including databases, web servers, and commonly used application servers. + <br/> <br/> + Netdata is also a high performance, distributed <b>statsd server</b>, allowing custom + application metrics to be collected and visualized. + </p> + </div> + <div class=grid-cell><h3><span class=star>★</span> Check (alarms)</h3> + <p> + Each Netdata spawns a thread that examines the metrics as they get collected, + evaluates pre-configured alarm expressions and triggers alarm notifications. + <br/> <br/> + Netdata comes with hundreds of alarms to detect common system and application issues, + that are automatically attached to the collected metrics, + supporting dozens of alarm notification integrations. + </p> + </div> + <div class=grid-cell><h3><span class=star>★</span> Stream</h3> + <p> + Each Netdata can stream its metrics, in real-time, to any other Netdata. + Streaming allows Netdata to be used in ephemeral nodes and containers in auto-scaled environments, + but it also allows building Netdata hierarchies for aggregating the metrics of multiple Netdata nodes. + </p> + </div> + <div class=grid-cell><h3><span class=star>★</span> Store</h3> + <p> + Each Netdata has its own internal metrics database. This database is optimized + for minimal memory footprint, and due to its lockless design allows one writer + and multiple readers per metric, concurrently, contributing significantly to + the performance of Netdata. + </p> + </div> + <div class=grid-cell><h3><span class=star>★</span> Archive</h3> + <p> + Netdata can archive its metrics to time-series databases (prometheus, graphite, opentsdb, json document dbs, etc) + so that Netdata can be integrated to existing monitoring tool-chains. + </p> + </div> + <div class=grid-cell><h3><span class=star>★</span> Visualize</h3> + <p> + The best part of Netdata is its visualization. Low latency, speedy and snazzy. + <br/> <br/> + Netdata dashboards are optimized for visual anomaly detection, a powerful tool to troubleshoot + performance issues. + </p> + </div> + </div> + </div> +</div> + +<div class="site-section"> + +</div> + + +<div id="demosites" class="site-section site-section-dark"><h2>netdata live demo sites</h2> + <div class="content"> + <div class="container" style="text-align: center;"> + + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//london.my-netdata.io" + data-title="EU - London" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#558855" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//london.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoLondon><strong>Enter London!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//atlanta.my-netdata.io" + data-title="US - Atlanta" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#AA5555" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//atlanta.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoAtlanta><strong>Enter Atlanta!</strong></a> + <div class="mygause-donation"> + Donated by CDN77.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//sanfrancisco.my-netdata.io" + data-title="US - California" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#5555AA" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//sanfrancisco.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoSanfrancisco><strong>Enter California!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//toronto.my-netdata.io" + data-title="Canada" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#885588" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//toronto.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoToronto><strong>Enter Canada!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <br/> <br/> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//frankfurt.my-netdata.io" + data-title="EU - Germany" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#AAAA55" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//frankfurt.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoFrankfurt><strong>Enter Germany!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//newyork.my-netdata.io" + data-title="US - New York" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#BB5533" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//newyork.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoNewYork><strong>Enter New York!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//singapore.my-netdata.io" + data-title="Singapore" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#5588BB" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//singapore.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoSingapore><strong>Enter Singapore!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//bangalore.my-netdata.io" + data-title="India" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#BB55BB" + ></div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//bangalore.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoBangalore><strong>Enter India!</strong></a> + <div class="mygause-donation"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div style="padding-top: 20px;"> + <div class="mygauge-combo"> + <div class="mygauge"> + <div style="padding-bottom: 20px; font-size: 10px; color: #676b70;"> + <b>Isreal</b> + </div> + <div class="mysparkline"> + <div class="mysparkline-overchart-label2"> + requests/s + </div> + <div class="mysparkline-overchart-value" id="octopuscs.requests.netdata" > + </div> + <div data-netdata="netdata.requests" + data-dimensions="requests" + data-host="//octopuscs.my-netdata.io" + data-common-max="top-gauges" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#4BFF91" + data-show-value-of-requests-at="octopuscs.requests.netdata" + ></div> + </div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//octopuscs.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoOctopuscs><strong>Enter Isreal!</strong></a> + <div class="mygause-donation"> + Donated by octopuscs.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div style="padding-bottom: 20px; font-size: 10px; color: #676b70;"> + <b>EU - France</b> + </div> + <div class="mysparkline"> + <div class="mysparkline-overchart-label2"> + requests/s + </div> + <div class="mysparkline-overchart-value" id="ventureer.requests.netdata" > + </div> + <div data-netdata="netdata.requests" + data-dimensions="requests" + data-host="//ventureer.my-netdata.io" + data-common-max="top-gauges" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#FF4B91" + data-show-value-of-requests-at="ventureer.requests.netdata" + ></div> + </div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//ventureer.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoVentureer><strong>Enter Roubaix!</strong></a> + <div class="mygause-donation"> + Donated by ventureer.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div style="padding-bottom: 20px; font-size: 10px; color: #676b70;"> + <b>EU - Spain</b> + </div> + <div class="mysparkline"> + <div class="mysparkline-overchart-label2"> + requests/s + </div> + <div class="mysparkline-overchart-value" id="stackscale.requests.netdata" > + </div> + <div data-netdata="netdata.requests" + data-dimensions="requests" + data-host="//stackscale.my-netdata.io" + data-common-max="top-gauges" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#4B91FF" + data-show-value-of-requests-at="stackscale.requests.netdata" + ></div> + </div> + </div> + <div class="mygauge-button"> + <a class="btn btn-alt mygauge-legend-button" href=//stackscale.my-netdata.io/default.html data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=DemoStackScale><strong>Enter Madrid!</strong></a> + <div class="mygause-donation"> + Donated by stackscale.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + </div> + </div> + </div> + </div> + + <div class="container" style="padding-top: 40px; text-align: center;"> + Charts are coming from all servers, <b>in parallel</b>. + <br/> + The servers are <b>not aware</b> of this multi-server dashboard. + </div> + + <div class="container" style="padding-top: 40px; padding-bottom: 40px; text-align: center;"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b> connected clients + </div> + <div class="mysparkline-overchart-value" id="nginx_local.connections.netdata" > + </div> + <div data-netdata="nginx_local.connections" + data-dimensions="active" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-common-max="web-connections" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-active-at="nginx_local.connections.netdata" + ></div> + </div> + </div> + + <div class="container" style="padding-top: 0px; text-align: center;"> + Each server is <b>not aware</b> of the other servers. + <br/> + But on this dashboard <b>they are one</b>! (hover on the chart above) + </div> + + + <!-- + <div style="padding-top: 40px; color: #999;"> + <small>We would love to show demos of IoT devices running netdata.<br/> + If you can host at your DC an RPi or a Linux IoT, <a href="mailto:costa@tsaousis.gr?subject=I can host IoT for netdata&body=Hi Costa,%0D%0A%0D%0AI would love to host an IoT device to demo netdata on it.%0D%0A%0D%0A-- please tell me who you are and what infrastructure you have --%0D%0A-- Take into account I would need SSH access to it --%0D%0A-- You have to have a DC - a home is not good enough - sorry. --%0D%0A%0D%0AThanks!">contact me</a>.</small> + </div> + --> + </div> +</div> + +<div class=site-section><h2>Who uses netdata?</h2> + <div class="content"> + <div class="container" style="text-align: center;"> + <p> + Netdata is used by hundreds of thousands of users all over the world. + <br/> <br/> + Check our <a href="https://github.com/netdata/netdata/watchers">GitHub watchers</a> list. + <br/> + You will find people working for <b>Amazon</b>, <b>Atos</b>, <b>Baidu</b>, <b>Cisco Systems</b>, <b>Citrix</b>, + <b>Deutsche Telekom</b>, <b>DigitalOcean</b>, <b>Elastic</b>, <b>EPAM Systems</b>, <b>Ericsson</b>, <b>Google</b>, + <b>Groupon</b>, <b>Hortonworks</b>, <b>HP</b>, <b>Huawei</b>, <b>IBM</b>, <b>Microsoft</b>, <b>NewRelic</b>, + <b>Nvidia</b>, <b>Red Hat</b>, <b>SAP</b>, <b>Selectel</b>, <b>TicketMaster</b>, <b>Vimeo</b>, and many more! + </p> + <small> + The following figures come from users using the <a href="https://github.com/netdata/netdata/tree/master/registry" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=GlobalRegistry>netdata public global registry</a>.<br/>Counting since May 16th 2016. Actual figures may be a lot higher.<br/></small> + <div class="container" style="padding-top: 40px; text-align: center; width: 30%; min-width: 220px; display: inline-block;"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + netdata <b>unique users</b> + </div> + <div class="mysparkline-overchart-value-center" id="netdata.registry_entries.persons.netdata" > + </div> + <div data-netdata="netdata.registry_entries" + data-dimensions="persons" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-persons-at="netdata.registry_entries.persons.netdata" + ></div> + </div> + </div> + <div class="container" style="padding-top: 40px; text-align: center; width: 30%; min-width: 220px; display: inline-block;"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + netdata <b>monitored servers</b> + </div> + <div class="mysparkline-overchart-value-center" id="netdata.registry_entries.machines.netdata" > + </div> + <div data-netdata="netdata.registry_entries" + data-dimensions="machines" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855 #558855 #558855" + data-show-value-of-machines-at="netdata.registry_entries.machines.netdata" + ></div> + </div> + </div> + <div class="container" style="padding-top: 40px; text-align: center; width: 30%; min-width: 220px; display: inline-block;"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + netdata <b>sessions served</b> + </div> + <div class="mysparkline-overchart-value-center" id="netdata.registry_sessions.sessions.netdata" > + </div> + <div data-netdata="netdata.registry_sessions" + data-dimensions="sessions" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855 #558855 #558855" + data-show-value-of-sessions-at="netdata.registry_sessions.sessions.netdata" + ></div> + </div> + </div> + <p> + + <!-- + <embed src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&label=user%20base&units=null&value_color=blue&precision=0&refresh=30&v42" type="image/svg+xml" height="20" /> + <embed src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&label=servers%20monitored&units=null&value_color=orange&precision=0&refresh=30&v42" type="image/svg+xml" height="20" /> + <embed src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&label=sessions%20served&units=null&value_color=yellowgreen&precision=0&refresh=30&v42" type="image/svg+xml" height="20" /> + <br/><i>(figures come from <a href="https://github.com/netdata/netdata/tree/master/registry" target="_blank">the public netdata registry</a> data, showing only installations that use this registry, counting since May 16th 2016)</i> + <br/> + --> + </p> + <p> + <small> + netdata can generate auto-refreshing <strong><a href="https://github.com/netdata/netdata/tree/master/web/api/badges#netdata-badges" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Badges>badges</a></strong>, like these: + </small> + <br/> + <embed style="padding-top: 10px; padding-bottom: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&after=-86400&options=unaligned&group=incremental-sum&label=new%20users%20today&units=null&value_color=blue&precision=0&refresh=60&v42" type="image/svg+xml" height="20" /> + <embed style="padding-top: 10px; padding-bottom: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&group=incremental-sum&after=-86400&options=unaligned&label=servers%20added%20today&units=null&value_color=orange&precision=0&refresh=60&v42" type="image/svg+xml" height="20" /> + <embed style="padding-top: 10px; padding-bottom: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&after=-86400&group=incremental-sum&options=unaligned&label=sessions%20served%20today&units=null&value_color=yellowgreen&precision=0&refresh=60&v42" type="image/svg+xml" height="20" /> + <br/> + <small>These badges auto-refresh every minute.</small> + </p> + </div> + <div class="container" style="text-align: center;"> + <strong>netdata</strong> is featured at the <a href="https://octoverse.github.com/2016/" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Octoverse>GitHub's state of the Octoverse 2016</a> + <div style="padding-top: 10px;"> + <a href="https://octoverse.github.com/2016/" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=OctoverseImage> + <img src="https://cloud.githubusercontent.com/assets/2662304/21743260/23ebe62c-d507-11e6-80c0-76b95f53e464.png" width="90%" style="border-radius: 4px; border: 1px solid #fff;"/> + </a> + </div> + </div> + <div class=cta-option> + <a class="btn btn-download" href="https://docs.netdata.cloud/packaging/installer/" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=InstallAfterDemo><strong>Install netdata now</strong></a> + </div> + </div> +</div> +<div class=aside> + <div class=container> + <!-- Place this tag where you want the button to render. --> + <a class="github-button" href="https://github.com/netdata/netdata/subscription" data-style="mega" data-show-count="true" aria-label="Watch netdata/netdata on GitHub"><img src="https://img.shields.io/github/watchers/netdata/netdata.svg?style=flat&label=Github%20Watchers"></a> + <!-- Place this tag where you want the button to render. --> + <a class="github-button" href="https://github.com/netdata/netdata" data-style="mega" data-show-count="true" aria-label="Star netdata/netdata on GitHub"><img src="https://img.shields.io/github/stars/netdata/netdata.svg?style=flat&label=Github%20Stars"></a> + <!-- Place this tag where you want the button to render. --> + <a class="github-button" href="https://github.com/netdata/netdata/fork" data-style="mega" data-show-count="true" aria-label="Fork netdata/netdata on GitHub"><img src="https://img.shields.io/github/forks/netdata/netdata.svg?style=flat&label=Github%20Repo%20Forks"></a> + </div> +</div> + +<!-- the footer --> +<div class=site-footer role=contentinfo> + <p> + <div style="display: inline-block;"> + <div style="vertical-align:top;display:inline-block; height: 34px;">twitter:</div> + <div style="vertical-align:top;display:inline-block; height: 34px;"><a class=twitter-share-button href=https://twitter.com/share data-count=none data-lang=en data-via=linuxnetdata data-size=small data-text="Get control of your Linux servers. Simple. Effective. Awesome." data-url=https://my-netdata.io/ >Tweet</a></div> + <div style="vertical-align:top;display:inline-block; height: 34px;"><a class=twitter-follow-button href=https://twitter.com/linuxnetdata data-show-count=false data-lang=en data-size=small>Follow @linuxnetdata</a></div> + </div> + <div style="display: inline-block;"> + <div style="vertical-align:top;display:inline-block; height: 34px; padding-left: 10px;">facebook:</div> + <div class="fb-like" data-href="https://my-netdata.io/" data-layout="button" data-action="like" data-show-faces="false" data-share="false" style="vertical-align:top;display:inline-block; height: 34px;"></div> + <div class="fb-share-button" data-href="https://my-netdata.io/" data-layout="button" data-size="small" data-mobile-iframe="true"><a class="fb-xfbml-parse-ignore" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmy-netdata.io%2F&src=sdkpreparse" style="vertical-align:top;display:inline-block; height: 34px;">Share</a></div> + <div class="fb-follow" data-href="https://www.facebook.com/linuxnetdata/" data-layout="standard" data-size="small" data-show-faces="false" data-colorscheme="dark" width="225" style="vertical-align:top;display:inline-block; height: 34px;"></div> + </div> + </p> + <p> + <strong>netdata</strong><br/> + © Copyright 2018-2019, <a href="https://github.com/netdata" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=NetdataInc>Netdata</a><br/> + © Copyright 2016-2018, <a href="https://github.com/ktsaou" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=CostaTsaousis>Costa Tsaousis</a><br/> + Released under <a href="https://github.com/netdata/netdata/blob/master/LICENSE.md" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=License>GPL v3+</a><br/> + </p> + </p> + <p style="padding-top: 20px;"> + netdata has received significant contributions from:<br/> <br/> + <a href="https://github.com/philwhineray" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Phil>Phil Whineray</a> (release management),<br/> + <a href="https://github.com/alonbl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Alon>Alon Bar-Lev</a> (autoconf and automake),<br/> + <a href="https://github.com/titpetric" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=titpetric>Tit Petric</a> (docker image maintainer),<br/> + <a href="https://github.com/paulfantom" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Pawel>Paweł Krupa</a> (python.d.plugin and modules),<br/> + <a href="https://github.com/simonnagl" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=simonnagl>simonnagl</a> (disk plugin and more),<br/> + <a href="https://github.com/fredericopissarra" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=Frederico>Frederico Lamberti Pissarra</a> (performance improvements)<br/> + <a href="https://github.com/vlvkobal" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=VladimirKobal>Vladimir Kobal</a> (FreeBSD port)<br/> + <a href="https://github.com/l2isbad" target="_blank" data-ga-category="Outbound links" data-ga-action="Nav click" data-ga-label=l2isbad>Ilya Mashchenko</a> (python plugin modules)<br/> + <br/> + and dozens more enthusiasts, engineers and professionals.<br/> <br/> + </p> + </p> + Thank you! You are awesome! + <p> +</div> +</body> + +<script> + if(window.location.hostname != 'my-netdata.io' || window.location.protocol != 'https:') { + var canonical = document.createElement('link'); + canonical.rel = 'canonical'; + canonical.href = 'https://my-netdata.io/'; + document.head.appendChild(canonical); + } +</script> + +<script>!function (t, e) { + "use strict"; + function a(t, n) { + return t.hasAttribute(n) === !0 ? t : t.parentNode !== r.body ? a(t.parentNode, n) : e + } + + function n(n) { + var o, i, r, c, g, u = a(n.target, "data-ga-action"), l = !1; + u !== e && (o = u.getAttribute("data-ga-action") || e, i = u.getAttribute("data-ga-category") || e, r = u.getAttribute("data-ga-label") || e, c = u.getAttribute("href"), g = parseInt(u.getAttribute("data-ga-value"), 10) || e, ga !== e && i !== e && o !== e && (n.preventDefault(), "Download" !== i && n.ctrlKey !== !0 && n.metaKey !== !0 && 2 !== n.which || (l = !0, t.open(c)), function (a) { + var n; + ga("send", "event", i, o, r, g, { + hitCallback: function () { + l === !1 && (n !== e && clearTimeout(n), t.location = a) + } + }), n = setTimeout(function () { + l === !1 && (t.location.href = a) + }, 1e3) + }(c))) + } + + function o() { + !function (t, e, a, n, o, i) { + t.GoogleAnalyticsObject = n, t[n] || (t[n] = function () { + (t[n].q = t[n].q || []).push(arguments) + }), t[n].l = +new Date, o = e.createElement(a), i = e.getElementsByTagName(a)[0], o.src = "//www.google-analytics.com/analytics.js", i.parentNode.insertBefore(o, i) + }(t, r, "script", "ga"), ga("create", "UA-64295674-3", "auto"), ga("send", "pageview", "/site"+window.location.pathname), t.document.addEventListener("click", n) + } + + function i() { + !function (t, e, a) { + var n, o = t.getElementsByTagName(e)[0]; + t.getElementById(a) || (n = t.createElement(e), n.id = a, n.src = "//platform.twitter.com/widgets.js", o.parentNode.insertBefore(n, o)) + }(r, "script", "twitter-wjs") + } + + var r = t.document; + o(), t.onload = i +}(window)</script> + +<!-- facebook sdk --> +<div id="fb-root"></div> +<script> + window.fbAsyncInit = function() { + FB.init({ + appId : '1200089276712916', + xfbml : true, + version : 'v2.8' + }); + }; + + (function(d, s, id){ + var js, fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) {return;} + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/en_US/sdk.js"; + fjs.parentNode.insertBefore(js, fjs); + }(document, 'script', 'facebook-jssdk')); +</script> + +<script> + var allTitles = [ + 'Get control<br/>of your Linux servers' + , 'Get control<br/>of your FreeBSD servers' + , 'Monitor<br/>your containers' + , 'Monitor<br/>your virtual machines' + , 'Monitor<br/>your web servers' + , 'Monitor<br/>your databases' + , 'Monitor<br/>your applications' + , 'Monitor<br/>your SNMP devices' + , 'Monitor<br/>your IoT devices' + , 'Monitor<br/>your MacOS systems' + ]; + var lastTitle = -1; + + function updateTitle(){ + lastTitle++; + if(lastTitle >= allTitles.length) + lastTitle = 0; + + var os = document.getElementsByClassName('title'); + var len = os.length; + while (len--) { + var el = os[len]; + el.innerHTML = allTitles[lastTitle]; + el.classList.add('titlefadein'); + } + + setTimeout(function() { + var os = document.getElementsByClassName('title'); + var len = os.length; + while (len--) + os[len].classList.remove('titlefadein'); + + }, 5750); + setTimeout(updateTitle, 6000); + } + //updateTitle(); +</script> + +<!-- Start of HubSpot Embed Code --> +<script type="text/javascript" id="hs-script-loader" async defer src="//js.hs-scripts.com/4567453.js"></script> +<!-- End of HubSpot Embed Code --> diff --git a/web/gui/demosites2.html b/web/gui/demosites2.html new file mode 100644 index 0000000..41ad9d6 --- /dev/null +++ b/web/gui/demosites2.html @@ -0,0 +1,1112 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <title>NetData - Real-time performance monitoring, done right!</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + + <meta property="og:locale" content="en_US" /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png"/> + <meta property="og:url" content="http://my-netdata.io/"/> + <meta property="og:type" content="website"/> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> + <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> +</head> + +<script> + // --- OPTIONS FOR THE DASHBOARD -- + + // this section has to appear before loading dashboard.js + + // Select a theme. + // uncomment on of the two themes: + + // var netdataTheme = 'default'; // this is white + var netdataTheme = 'slate'; // this is dark + + + // Set the default netdata server. + // on charts without a 'data-host', this one will be used. + // the default is the server that dashboard.js is downloaded from. + + // var netdataServer = 'http://my.server:19999/'; + </script> + + <!-- + --- LOAD dashboard.js --- + + to host this HTML file on your web server, + you have to load dashboard.js from the netdata server. + + So, pick one the two below + If you pick the first, set the server name/IP. + + The second assumes you host this file on /usr/share/netdata/web + and that you have chown it to be owned by netdata:netdata + --> + <!-- <script type="text/javascript" src="http://my.server:19999/dashboard.js"></script> --> + <script type="text/javascript" src="dashboard.js?v20170724-1"></script> + + <script> + // --- OPTIONS FOR THE CHARTS -- + + // destroy charts not shown (lowers memory on the browsers) + // set this to 'true' to destroy, 'false' to hide the charts + NETDATA.options.current.destroy_on_hide = false; + + // set this to false, to always show all dimensions + NETDATA.options.current.eliminate_zero_dimensions = true; + + // set this to false, to lower the pressure on the browser + NETDATA.options.current.concurrent_refreshes = true; + + // if you need to support slow mobile phones, set this to false + NETDATA.options.current.parallel_refresher = true; + + // set this to false, to always update the charts, even if focus is lost + NETDATA.options.current.stop_updates_when_focus_is_lost = true; + + // since we have many servers and limited sockets, + // abort ajax calls when we scroll + NETDATA.options.current.abort_ajax_on_scroll = true; +</script> +<style> + body { + font-size: 1vw; + } + + .mysparkline { + position: relative; + display: inline-block; + min-height: 50px; + width: 100%; + height: 7vmax; + text-align: left; + } + + .mysparkline-overchart-label { + position: absolute; + display: block; + top: 0; + left: 10px; + bottom: 0; + right: 0; + font-size: 1vmax; + z-index: 1; + } + + .mysparkline-overchart-value { + position: absolute; + display: block; + top: 1.1vmax; + left: 10px; + bottom: 0; + right: 0; + font-size: 5vmax; + z-index: 2; + text-shadow: #333 0px 0px 2px; + } + + .myfullchart { + position: relative; + display: inline-block; + width: 100%; + height: 12vmax; + min-height: 150px; + text-align: left; + } + + .mygauge-combo { + display: inline-block; + } + + .mygauge { + position: relative; + display: block; + width: 18vw; + height: 11vw; + } + + .mygauge-button { + display: block; + } + + .mytitle { + padding-top: 6vw; + padding-bottom: 1vw; + text-align: center; + font-size: 2.4vw; + } + + .mysubtitle { + padding-top: 2vw; + padding-bottom: 1vw; + text-align: center; + font-size: 1.8vw; + } + + .mycontent { + text-align: center; + font-size: 1.5vw; + } + + @media only screen and (min-width : 992px) { + .container { + width: 80%; + } + } + @media only screen and (max-width : 992px) { + .container { + width: 100%; + } + } +</style> + +<body style="text-align: center; background-color: #272b30;"> + +<div class="container"> + + <div style="text-align: center; font-size: 13vw; height: 14vw;"> + <b>netdata</b> + </div> + <div style="text-align: center; font-size: 2vw; height: 2.5vw;"> + real-time performance monitoring + </div> + <div style="width:80%; text-align: right; font-size: 2.7vw;"> + <strong>scaled out</strong>! + </div> + <div class="mytitle"> + pick a <b>netdata</b> demo server + </div> + <div class="mycontent"> + these demo servers show what you will get by installing <b>netdata</b> + </div> + + <div style="width: 100%; text-align: center; padding-top: 2vw;"> + <div style="width: 100%; text-align: center;"> + + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//london.my-netdata.io" + data-title="EU - London" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#558855" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//london.my-netdata.io/default.html'" style="font-size: 1.0vw;">Enter London!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//atlanta.my-netdata.io" + data-title="US - Atlanta" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#AA5555" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//atlanta.my-netdata.io/default.html'" style="font-size: 1.0vw;">Enter Atlanta!</button> + <div style="font-size: 0.8vw;"> + Donated by CDN77.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//sanfrancisco.netdata.rocks" + data-title="US - California" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#5555AA" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//sanfrancisco.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter California!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//toronto.netdata.rocks" + data-title="Canada" + data-chart-library="gauge" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="100%" + data-after="-300" + data-points="300" + data-colors="#885588" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//toronto.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Canada!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <br/> <br/> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//frankfurt.netdata.rocks" + data-title="EU - Germany" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#AAAA55" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//frankfurt.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Germany!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//newyork.netdata.rocks" + data-title="US - New York" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#BB5533" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//newyork.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter New York!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//singapore.netdata.rocks" + data-title="Singapore" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#5588BB" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//singapore.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter Singapore!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + <div class="mygauge-combo"> + <div class="mygauge"> + <div data-netdata="netdata.requests" + data-host="//bangalore.netdata.rocks" + data-title="India" + data-chart-library="easypiechart" + data-decimal-digits="0" + data-common-max="top-gauges" + data-width="75%" + data-after="-300" + data-points="300" + data-colors="#BB55BB" + ></div> + </div> + <div class="mygauge-button"> + <br/> <br/> + <button type="button" class="btn btn-default" data-toggle="button" aria-pressed="false" autocomplete="off" onclick="window.location='//bangalore.netdata.rocks/default.html'" style="font-size: 1.0vw;">Enter India!</button> + <div style="font-size: 0.8vw;"> + Donated by DigitalOcean.com + </div> + </div> + </div> + </div> + </div> + + <div class="mytitle"> + this page is a custom <b>netdata</b> dashboard + </div> + <div class="mycontent"> + charts are coming from 8 servers, in parallel + <br/> + the servers are not aware of this multi-server dashboard, + <br/> + each server is not aware of the other servers, + <br/> + but on this dashboard <b>they are one</b>! + </div> + <div style="padding-top: 1vw; width: 100%; text-align: center; font-size: 1.5vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> + hover on a chart below, or drag it to show the past - <b>the others will follow</b>! + <br/> + double click on a chart to reset them all + </div> + + <div class="mytitle"> + our <code>nginx</code> performance + </div> + <div class="mycontent"> + (we proxy netdata through nginx, on the demo sites) + </div> + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist" style="padding-top: 1vw;"> + <li role="presentation" class="active"><a href="#nginx_requests" aria-controls="nginx_requests" role="tab" data-toggle="tab">Requests</a></li> + <li role="presentation"><a href="#nginx_connections" aria-controls="nginx_connections" role="tab" data-toggle="tab">Connections</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="nginx_requests"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b> web requests/s + </div> + <div class="mysparkline-overchart-value" id="nginx_local.requests.netdata" > + </div> + <div data-netdata="nginx_local.requests" + data-dimensions="requests" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-common-max="web-requests" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-requests-at="nginx_local.requests.netdata" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - Atlanta</b> web requests/s + </div> + <div class="mysparkline-overchart-value" id="nginx_local.requests.netdata2" > + </div> + <div data-netdata="nginx_local.requests" + data-dimensions="requests" + data-host="//atlanta.my-netdata.io" + data-decimal-digits="0" + data-common-max="web-requests" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#AA5555" + data-show-value-of-requests-at="nginx_local.requests.netdata2" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - California</b> web requests/s + </div> + <div class="mysparkline-overchart-value" id="nginx_local.requests.netdata3" > + </div> + <div data-netdata="nginx_local.requests" + data-dimensions="requests" + data-host="//sanfrancisco.netdata.rocks" + data-decimal-digits="0" + data-common-max="web-requests" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#5555AA" + data-show-value-of-requests-at="nginx_local.requests.netdata3" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>Canada</b> web requests/s + </div> + <div class="mysparkline-overchart-value" id="nginx_local.requests.netdata4" > + </div> + <div data-netdata="nginx_local.requests" + data-dimensions="requests" + data-host="//toronto.netdata.rocks" + data-decimal-digits="0" + data-common-max="web-requests" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885588" + data-show-value-of-requests-at="nginx_local.requests.netdata4" + ></div> + </div> + </div> + + <div role="tabpanel" class="tab-pane" id="nginx_connections"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b> active connections + </div> + <div class="mysparkline-overchart-value" id="nginx_local.connections.netdata1" > + </div> + <div data-netdata="nginx_local.connections" + data-dimensions="active" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-common-max="web-connections" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-active-at="nginx_local.connections.netdata1" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - Atlanta</b> active connections + </div> + <div class="mysparkline-overchart-value" id="nginx_local.connections.netdata2" > + </div> + <div data-netdata="nginx_local.connections" + data-dimensions="active" + data-host="//atlanta.my-netdata.io" + data-decimal-digits="0" + data-common-max="web-connections" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#AA5555" + data-show-value-of-active-at="nginx_local.connections.netdata2" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - California</b> active connections + </div> + <div class="mysparkline-overchart-value" id="nginx_local.connections.netdata3" > + </div> + <div data-netdata="nginx_local.connections" + data-dimensions="active" + data-host="//sanfrancisco.netdata.rocks" + data-decimal-digits="0" + data-common-max="web-connections" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#5555AA" + data-show-value-of-active-at="nginx_local.connections.netdata3" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>Canada</b> active connections + </div> + <div class="mysparkline-overchart-value" id="nginx_local.connections.netdata4" > + </div> + <div data-netdata="nginx_local.connections" + data-dimensions="active" + data-host="//toronto.netdata.rocks" + data-decimal-digits="0" + data-common-max="web-connections" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885588" + data-show-value-of-active-at="nginx_local.connections.netdata4" + ></div> + </div> + </div> + </div> + + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> these charts are draggable and touchable, double click them to reset them + </div> + + + <div class="mytitle"> + bandwidth consumption on the demo sites + </div> + <div class="mycontent"> + Linux QoS is configured by <a href="https://github.com/netdata/netdata/tree/master/collectors/tc.plugin#tcplugin">FireQOS</a> + </div> + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist" style="padding-top: 1vw;"> + <li role="presentation" class="active"><a href="#outbout" aria-controls="outbout" role="tab" data-toggle="tab">Outbound</a></li> + <li role="presentation"><a href="#inbound" aria-controls="inbound" role="tab" data-toggle="tab">Inbound</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="outbout"> + <div class="myfullchart"> + <div data-netdata="tc.world_out" + data-host="//london.my-netdata.io" + data-common-max="tc-world-out" + data-chart-library="dygraph" + data-title="EU - London, traffic we send per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_out" + data-host="//atlanta.my-netdata.io" + data-chart-library="dygraph" + data-common-max="tc-world-out" + data-title="US - Atlanta, traffic we send per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_out" + data-host="//sanfrancisco.netdata.rocks" + data-chart-library="dygraph" + data-common-max="tc-world-out" + data-title="US - California, traffic we send per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_out" + data-host="//toronto.netdata.rocks" + data-chart-library="dygraph" + data-common-max="tc-world-out" + data-title="Canada, traffic we send per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + </div> + </div> + + <div role="tabpanel" class="tab-pane" id="inbound"> + <div class="myfullchart"> + <div data-netdata="tc.world_in" + data-host="//london.my-netdata.io" + data-common-max="tc-world-in" + data-chart-library="dygraph" + data-title="EU - London, traffic we receive per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_in" + data-host="//atlanta.my-netdata.io" + data-common-max="tc-world-in" + data-chart-library="dygraph" + data-title="US - Atlanta, traffic we receive per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_in" + data-host="//sanfrancisco.netdata.rocks" + data-common-max="tc-world-in" + data-chart-library="dygraph" + data-title="US - California, traffic we receive per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="tc.world_in" + data-host="//toronto.netdata.rocks" + data-common-max="tc-world-in" + data-chart-library="dygraph" + data-title="Canada, traffic we receive per service" + data-width="100%" + data-height="100%" + data-after="-300" + ></div> + </div> + </div> + </div> + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> <i>these legends are interactive and the charts are resizable here ^^^</i> + </div> + + <div class="mytitle"> + DDoS protection performance on the demo sites + </div> + <div class="mycontent"> + iptables SYNPROXY configured by <a href="https://github.com/netdata/netdata/blob/master/collectors/proc.plugin/README.md#linux-anti-ddos">FireHOL</a> + </div> + + <div style="padding-top: 4vw; width: 100%; text-align: center; font-size: 1.5vw;"> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b>, TCP SYN packets/s received + </div> + <div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata1" > + </div> + <div data-netdata="netfilter.synproxy_syn_received" + data-dimensions="received" + data-host="//london.my-netdata.io" + data-decimal-digits="0" + data-common-max="synproxy-in" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata1" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - Atlanta</b>, TCP SYN packets/s received + </div> + <div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata2" > + </div> + <div data-netdata="netfilter.synproxy_syn_received" + data-dimensions="received" + data-host="//atlanta.my-netdata.io" + data-decimal-digits="0" + data-common-max="synproxy-in" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885555" + data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata2" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - California</b>, TCP SYN packets/s received + </div> + <div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata3" > + </div> + <div data-netdata="netfilter.synproxy_syn_received" + data-dimensions="received" + data-host="//sanfrancisco.netdata.rocks" + data-decimal-digits="0" + data-common-max="synproxy-in" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#555588" + data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata3" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>Canada</b>, TCP SYN packets/s received + </div> + <div class="mysparkline-overchart-value" id="netfilter.synproxy_syn_received.netdata4" > + </div> + <div data-netdata="netfilter.synproxy_syn_received" + data-dimensions="received" + data-host="//toronto.netdata.rocks" + data-decimal-digits="0" + data-common-max="synproxy-in" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885588" + data-show-value-of-received-at="netfilter.synproxy_syn_received.netdata4" + ></div> + </div> + </div> + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> <i>did you notice the decimal numbers? + <br/>netdata interpolates collected values at second boundaries, with nanosecond detail!</i> + </div> + + + <div class="mytitle"> + CPU Utilization of the demo sites + </div> + + <div style="padding-top: 1vw;"> + <div class="myfullchart"> + <div data-netdata="system.cpu" + data-host="//london.my-netdata.io" + data-chart-library="dygraph" + data-title="EU - London, CPU Usage" + data-width="100%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="system.cpu" + data-host="//atlanta.my-netdata.io" + data-chart-library="dygraph" + data-title="US - Atlanta, CPU Usage" + data-width="100%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="system.cpu" + data-host="//sanfrancisco.netdata.rocks" + data-chart-library="dygraph" + data-title="US - California, CPU Usage" + data-width="100%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + </div> + + <div class="myfullchart"> + <div data-netdata="system.cpu" + data-host="//toronto.netdata.rocks" + data-chart-library="dygraph" + data-title="Canada, CPU Usage" + data-width="100%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + </div> + </div> + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> <i>what is using so much CPU? + <br/>The site <a href="//iplists.firehol.org/">iplists.firehol.org</a> is maintained by FireHOL - the CPU is used for comparing security IP Lists.</i> + </div> + + <div class="mytitle"> + Netdata performance + </div> + <div class="mycontent"> + netdata monitors <b>users</b>, <b>user groups</b>, <b>applications (process trees)</b> + <br/> + <b>containers</b> (<code>lxc</code>, <code>docker</code>, etc.) and SNMP devices. + </div> + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist" style="padding-top: 1vw;"> + <li role="presentation" class="active"><a href="#netdata_cpu" aria-controls="netdata_cpu" role="tab" data-toggle="tab">CPU</a></li> + <li role="presentation"><a href="#netdata_avgtime" aria-controls="netdata_avgtime" role="tab" data-toggle="tab">Average Response Time</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="netdata_cpu"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b>, CPU % of a single core + </div> + <div class="mysparkline-overchart-value" id="users.cpu.netdata1" > + </div> + <div data-netdata="apps.cpu" + data-dimensions="netdata" + data-common-max="users-cpu" + data-decimal-digits="1" + data-host="//london.my-netdata.io" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855" + data-show-value-of-netdata-at="users.cpu.netdata1" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - Atlanta</b>, CPU % of a single core + </div> + <div class="mysparkline-overchart-value" id="users.cpu.netdata2" > + </div> + <div data-netdata="apps.cpu" + data-dimensions="netdata" + data-common-max="users-cpu" + data-decimal-digits="1" + data-host="//atlanta.my-netdata.io" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885555" + data-show-value-of-netdata-at="users.cpu.netdata2" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - California</b>, CPU % of a single core + </div> + <div class="mysparkline-overchart-value" id="users.cpu.netdata3" > + </div> + <div data-netdata="apps.cpu" + data-dimensions="netdata" + data-common-max="users-cpu" + data-decimal-digits="1" + data-host="//sanfrancisco.netdata.rocks" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#555588" + data-show-value-of-netdata-at="users.cpu.netdata3" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>Toronto</b>, CPU % of a single core + </div> + <div class="mysparkline-overchart-value" id="users.cpu.netdata4" > + </div> + <div data-netdata="apps.cpu" + data-dimensions="netdata" + data-common-max="users-cpu" + data-decimal-digits="1" + data-host="//toronto.netdata.rocks" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885588" + data-show-value-of-netdata-at="users.cpu.netdata4" + ></div> + </div> + + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> <i>this utilization is about the whole netdata process tree and the percentage is of <b>a single core</b>! + <br/>including <b>BASH</b> plugins (it monitors <code>mysql</code> on the demo sites), <b>node.js</b> plugins (it monitors <code>bind9</code> on the demo sites), etc. + <br/>and including the chart refreshes for the dashboards of all viewers.</i> + </div> + </div> + + <div role="tabpanel" class="tab-pane" id="netdata_avgtime"> + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>EU - London</b>, API average response time in milliseconds + </div> + <div class="mysparkline-overchart-value" id="netdata.response_time1" > + </div> + <div data-netdata="netdata.response_time" + data-host="//london.my-netdata.io" + data-common-max="netdata-response-time" + data-decimal-digits="1" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#558855 #356835" + data-show-value-of-average-at="netdata.response_time1" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - Atlanta</b>, API average response time in milliseconds + </div> + <div class="mysparkline-overchart-value" id="netdata.response_time2" > + </div> + <div data-netdata="netdata.response_time" + data-host="//atlanta.my-netdata.io" + data-common-max="netdata-response-time" + data-decimal-digits="1" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885555 #683535" + data-show-value-of-average-at="netdata.response_time2" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>US - California</b>, API average response time in milliseconds + </div> + <div class="mysparkline-overchart-value" id="netdata.response_time3" > + </div> + <div data-netdata="netdata.response_time" + data-host="//sanfrancisco.netdata.rocks" + data-common-max="netdata-response-time" + data-decimal-digits="1" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#555588 #353568" + data-show-value-of-average-at="netdata.response_time3" + ></div> + </div> + + <div class="mysparkline"> + <div class="mysparkline-overchart-label"> + <b>Canada</b>, API average response time in milliseconds + </div> + <div class="mysparkline-overchart-value" id="netdata.response_time4" > + </div> + <div data-netdata="netdata.response_time" + data-host="//toronto.netdata.rocks" + data-decimal-digits="1" + data-common-max="netdata-response-time" + data-chart-library="dygraph" + data-dygraph-theme="sparkline" + data-dygraph-type="area" + data-width="100%" + data-height="100%" + data-after="-300" + data-colors="#885588 #683568" + data-show-value-of-average-at="netdata.response_time4" + ></div> + </div> + + <div style="width: 100%; text-align: right; font-size: 1vw;"> + <i class="fa fa-comment" aria-hidden="true"></i> <i>netdata is really <b>fast</b> (the values are milliseconds!) + <br/> + These values include everything, from the reception of the first byte to the dispatch of the last, including gzip compression. + <br/> + Values above 2-3ms are usually chart refreshes of charts with several dimensions, charts with very long durations (zoomed out), or file transfers. + </i> + </div> + </div> + </div> + + <div style="padding-top: 6vw; width: 100%; text-align: center; font-size: 2vw;"> + want to know more? + <br/> + jump to <a href="https://github.com/netdata/netdata/">the netdata page at github</a> + <br/> + it needs just 3 mins to be installed on your servers! + <br/> + + </div> +</div> +</body> +<script> + // google analytics when this is used for the home page of the demo sites + // you don't need this if you customize this dashboard for your needs + setTimeout(function() { + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) + })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); + + ga('create', 'UA-64295674-3', 'auto'); + ga('send', 'pageview'); + }, 2000); +</script> +</html> diff --git a/web/gui/favicon.ico b/web/gui/favicon.ico Binary files differnew file mode 100644 index 0000000..857c582 --- /dev/null +++ b/web/gui/favicon.ico diff --git a/web/gui/fonts/glyphicons-halflings-regular.eot b/web/gui/fonts/glyphicons-halflings-regular.eot Binary files differnew file mode 100644 index 0000000..b93a495 --- /dev/null +++ b/web/gui/fonts/glyphicons-halflings-regular.eot diff --git a/web/gui/fonts/glyphicons-halflings-regular.svg b/web/gui/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..2a4aaba --- /dev/null +++ b/web/gui/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,289 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<!-- SPDX-License-Identifier: CC-BY-4.0 --> +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="glyphicons_halflingsregular" horiz-adv-x="1200" > +<font-face units-per-em="1200" ascent="960" descent="-240" /> +<missing-glyph horiz-adv-x="500" /> +<glyph horiz-adv-x="0" /> +<glyph horiz-adv-x="400" /> +<glyph unicode=" " /> +<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" /> +<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode=" " /> +<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="433" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="162" /> +<glyph unicode=" " horiz-adv-x="260" /> +<glyph unicode=" " horiz-adv-x="72" /> +<glyph unicode=" " horiz-adv-x="260" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" /> +<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" /> +<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" /> +<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" /> +<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " /> +<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" /> +<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" /> +<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" /> +<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" /> +<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" /> +<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" /> +<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" /> +<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" /> +<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" /> +<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" /> +<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" /> +<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" /> +<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" /> +<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" /> +<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" /> +<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" /> +<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" /> +<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" /> +<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" /> +<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" /> +<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" /> +<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" /> +<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" /> +<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" /> +<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" /> +<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" /> +<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" /> +<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" /> +<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" /> +<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" /> +<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" /> +<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" /> +<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" /> +<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" /> +<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" /> +<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" /> +<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" /> +<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" /> +<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" /> +<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" /> +<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" /> +<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" /> +<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" /> +<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" /> +<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" /> +<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" /> +<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" /> +<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" /> +<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" /> +<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" /> +<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" /> +<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" /> +<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" /> +<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" /> +<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" /> +<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" /> +<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" /> +<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" /> +<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" /> +<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" /> +<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" /> +<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" /> +<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " /> +<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" /> +<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" /> +<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" /> +<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" /> +<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" /> +<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" /> +<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" /> +<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" /> +<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" /> +<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" /> +<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" /> +<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" /> +<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" /> +<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" /> +<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" /> +<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" /> +<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" /> +<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" /> +<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" /> +<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" /> +<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" /> +<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" /> +<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" /> +<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" /> +<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" /> +<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" /> +<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" /> +<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" /> +<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" /> +<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" /> +<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" /> +<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" /> +<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" /> +<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" /> +<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" /> +<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" /> +<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" /> +<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " /> +<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" /> +<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" /> +<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" /> +<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" /> +<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" /> +<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" /> +<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" /> +<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" /> +<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" /> +<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" /> +<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" /> +<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" /> +<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" /> +<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" /> +<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" /> +<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" /> +<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" /> +<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" /> +<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" /> +<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" /> +<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" /> +<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" /> +<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" /> +<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" /> +<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" /> +<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" /> +</font> +</defs></svg> diff --git a/web/gui/fonts/glyphicons-halflings-regular.ttf b/web/gui/fonts/glyphicons-halflings-regular.ttf Binary files differnew file mode 100644 index 0000000..1413fc6 --- /dev/null +++ b/web/gui/fonts/glyphicons-halflings-regular.ttf diff --git a/web/gui/fonts/glyphicons-halflings-regular.woff b/web/gui/fonts/glyphicons-halflings-regular.woff Binary files differnew file mode 100644 index 0000000..9e61285 --- /dev/null +++ b/web/gui/fonts/glyphicons-halflings-regular.woff diff --git a/web/gui/fonts/glyphicons-halflings-regular.woff2 b/web/gui/fonts/glyphicons-halflings-regular.woff2 Binary files differnew file mode 100644 index 0000000..64539b5 --- /dev/null +++ b/web/gui/fonts/glyphicons-halflings-regular.woff2 diff --git a/web/gui/goto-host-from-alarm.html b/web/gui/goto-host-from-alarm.html new file mode 100644 index 0000000..eb1d483 --- /dev/null +++ b/web/gui/goto-host-from-alarm.html @@ -0,0 +1,249 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': + new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], + j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= + 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); + })(window,document,'script','dataLayer','GTM-N6CBMJD'); + dataLayer.push({"anonymous_statistics" : "false"}); + </script> + <title>Goto a host you know...</title> + <meta name="application-name" content="netdata"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> +</head> +<script> + var netdataRegistry = true; + var netdataRegistryAfterMs = 0; + var netdataTheme = 'slate'; + var netdataShowHelp = true; +</script> +<script type="text/javascript" src="dashboard.js?v20170724-7"></script> + +<script> +function escapeUserInputHTML(s) { + return s.toString() + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/#/g, '#') + .replace(/'/g, ''') + .replace(/\(/g,'(') + .replace(/\)/g,')') + .replace(/\//g,'/'); +} + +// if string.startsWith is not defined, define it +if(typeof String.prototype.startsWith !== 'function') { + String.prototype.startsWith = function(s) { + if(s.length > this.length) return false; + return this.slice(s.length) === s; + }; +} + +function verifyURL(s) { + if(typeof(s) === 'string' && (s.startsWith('http://') || s.startsWith('https://'))) + return s + .replace(/'/g, '%22') + .replace(/"/g, '%27') + .replace(/\)/g, '%28') + .replace(/\(/g, '%29'); + + console.log('invalid URL detected:'); + console.log(s); + return 'javascript:alert("invalid url");'; +} + +var urlOptions = { + host: null, + chart: null, + family: null, + alarm: null, + alarm_unique_id: 0, + alarm_id: 0, + alarm_event_id: 0, + hasProperty: function(property) { + return typeof this[property] !== 'undefined'; + } +}; + +function netdataQueryParse() { + var query = document.location.search.split('?'); + var variables = query[1].split('&'); + var len = variables.length; + while(len--) { + var p = variables[len].split('='); + if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined') + urlOptions[p[0]] = decodeURIComponent(p[1]); + } + + if(typeof urlOptions.family !== 'string') + urlOptions.family = ''; + + if(typeof urlOptions.chart !== 'string') + urlOptions.chart = ''; +} + +function netdataURL(url) { + return url + '#top' + + ';nowelcome=1' + // + ';show_alarms=1' + + ';chart=' + encodeURIComponent(urlOptions.chart) + + ';family=' + encodeURIComponent(urlOptions.family) + + ';alarm=' + encodeURIComponent(urlOptions.alarm) + + ';alarm_unique_id=' + urlOptions.alarm_unique_id.toString() + + ';alarm_id=' + urlOptions.alarm_id.toString() + + ';alarm_event_id=' + urlOptions.alarm_event_id.toString() + ; +} + +var gotoServerValidateRemaining = 0; +var gotoServerMiddleClick = false; +var gotoServerStop = false; +var thisIsHttps = false; +var urlsInHttp = 0; +function gotoServerValidateUrl(id, guid, url) { + var penaldy = 0; + var error = 'failed'; + + if(thisIsHttps === false && url.toString().startsWith('https://')) + // we penalize https only if the current url is http + // to allow the user walk through all its servers. + penaldy = 500; + + else if(thisIsHttps === true && url.toString().startsWith('http://')) { + error = 'can\'t check'; + urlsInHttp++; + } + + var finalURL = netdataURL(url); + + setTimeout(function() { + document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + verifyURL(finalURL) + '" target="_blank">' + escapeUserInputHTML(url) + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>'; + + NETDATA.registry.hello(url, function(data) { + if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) { + // console.log('OK ' + id + ' URL: ' + url); + document.getElementById(guid + '-' + id + '-status').innerHTML = "OK"; + + if(!gotoServerStop) { + gotoServerStop = true; + + if(gotoServerMiddleClick) { + window.open(finalURL); + gotoServerMiddleClick = false; + document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + verifyURL(finalURL) + '">' + escapeUserInputHTML(url) + '</a></b><br/>(check your pop-up blocker if it fails)'; + } + else { + document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + escapeUserInputHTML(url) + '</small>'; + document.location = verifyURL(finalURL); + } + } + } + else { + if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid) + error = 'wrong machine'; + + document.getElementById(guid + '-' + id + '-status').innerHTML = error; + gotoServerValidateRemaining--; + if(gotoServerValidateRemaining <= 0) { + gotoServerMiddleClick = false; + document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>'; + + if(thisIsHttps === true && urlsInHttp > 0) { + document.getElementById('gotoServerResponse').innerHTML += '<br/>redirecting myself to HTTP to allow checking'; + document.location = verifyURL(document.location.toString().replace('https://', 'http://')); + } + } + } + }); + }, (id * 50) + penaldy); +} + +var netdataRegistryCallback = function(machines_array) { + if(typeof urlOptions.host !== 'string') { + document.getElementById('bodylog').innerHTML = "Sorry... bad request."; + return; + } + + document.getElementById('message').innerHTML = 'These are the URLs this machine is known:'; + + if(document.location.toString().startsWith('https://')) + thisIsHttps = true; + + if(machines_array) { + var guids = {}; + var checked = {}; + var len = machines_array.length; + var count = 0; + + while(len--) { + if(machines_array[len].name === urlOptions.host) { + var ulen = machines_array[len].alternate_urls.length; + var guid = machines_array[len].guid; + guids[guid] = true; + + gotoServerValidateRemaining = ulen; + while(ulen--) { + var url = machines_array[len].alternate_urls[ulen]; + checked[url] = true; + gotoServerValidateUrl(count++, guid, url); + } + + setTimeout(function() { + if(gotoServerStop === false) { + document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>'; + var guid; + for(guid in guids) { + NETDATA.registry.search(guid, function(data) { + // console.log(data); + len = data.urls.length; + while(len--) { + var url = data.urls[len][1]; + // console.log(url); + if(typeof checked[url] === 'undefined') { + gotoServerValidateRemaining++; + checked[url] = true; + gotoServerValidateUrl(count++, guid, url); + } + } + }); + } + } + }, 2000); + + return false; + } + } + } + + document.getElementById('bodylog').innerHTML = "Sorry... your account is not linked to a netdata server named: <b>" + escapeUserInputHTML(urlOptions.host) + '</b>'; +}; + +netdataQueryParse(); +</script> +<body> +<div class="container"> + <div id="bodylog" style="padding-top: 8vmax; font-size: 2.0vmax;"> + <span id="message">Please wait...</span> + + <div style="padding-top: 20px;"> + <table id="gotoServerList" class="table"> + </table> + </div> + <p style="padding-top: 10px;"><small> + This page can only find netdata URLs you have already visited and are linked to your account on this netdata registry. + </small></p> + <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> + </div> + +</div> +</body> +</html> diff --git a/web/gui/images/alert-128-orange.png b/web/gui/images/alert-128-orange.png Binary files differnew file mode 100644 index 0000000..c6182bf --- /dev/null +++ b/web/gui/images/alert-128-orange.png diff --git a/web/gui/images/alert-128-red.png b/web/gui/images/alert-128-red.png Binary files differnew file mode 100644 index 0000000..90b9c73 --- /dev/null +++ b/web/gui/images/alert-128-red.png diff --git a/web/gui/images/alert-multi-size-orange.ico b/web/gui/images/alert-multi-size-orange.ico Binary files differnew file mode 100644 index 0000000..edca438 --- /dev/null +++ b/web/gui/images/alert-multi-size-orange.ico diff --git a/web/gui/images/alert-multi-size-red.ico b/web/gui/images/alert-multi-size-red.ico Binary files differnew file mode 100644 index 0000000..8f7cbd0 --- /dev/null +++ b/web/gui/images/alert-multi-size-red.ico diff --git a/web/gui/images/android-icon-144x144.png b/web/gui/images/android-icon-144x144.png Binary files differnew file mode 100644 index 0000000..c3013cc --- /dev/null +++ b/web/gui/images/android-icon-144x144.png diff --git a/web/gui/images/android-icon-192x192.png b/web/gui/images/android-icon-192x192.png Binary files differnew file mode 100644 index 0000000..77d18d9 --- /dev/null +++ b/web/gui/images/android-icon-192x192.png diff --git a/web/gui/images/android-icon-36x36.png b/web/gui/images/android-icon-36x36.png Binary files differnew file mode 100644 index 0000000..74576f6 --- /dev/null +++ b/web/gui/images/android-icon-36x36.png diff --git a/web/gui/images/android-icon-48x48.png b/web/gui/images/android-icon-48x48.png Binary files differnew file mode 100644 index 0000000..5666fa1 --- /dev/null +++ b/web/gui/images/android-icon-48x48.png diff --git a/web/gui/images/android-icon-72x72.png b/web/gui/images/android-icon-72x72.png Binary files differnew file mode 100644 index 0000000..7f7043f --- /dev/null +++ b/web/gui/images/android-icon-72x72.png diff --git a/web/gui/images/android-icon-96x96.png b/web/gui/images/android-icon-96x96.png Binary files differnew file mode 100644 index 0000000..1bbf594 --- /dev/null +++ b/web/gui/images/android-icon-96x96.png diff --git a/web/gui/images/animated.gif b/web/gui/images/animated.gif Binary files differnew file mode 100644 index 0000000..0e94a20 --- /dev/null +++ b/web/gui/images/animated.gif diff --git a/web/gui/images/apple-icon-114x114.png b/web/gui/images/apple-icon-114x114.png Binary files differnew file mode 100644 index 0000000..7d093e8 --- /dev/null +++ b/web/gui/images/apple-icon-114x114.png diff --git a/web/gui/images/apple-icon-120x120.png b/web/gui/images/apple-icon-120x120.png Binary files differnew file mode 100644 index 0000000..d4c38e7 --- /dev/null +++ b/web/gui/images/apple-icon-120x120.png diff --git a/web/gui/images/apple-icon-144x144.png b/web/gui/images/apple-icon-144x144.png Binary files differnew file mode 100644 index 0000000..c3013cc --- /dev/null +++ b/web/gui/images/apple-icon-144x144.png diff --git a/web/gui/images/apple-icon-152x152.png b/web/gui/images/apple-icon-152x152.png Binary files differnew file mode 100644 index 0000000..c92f381 --- /dev/null +++ b/web/gui/images/apple-icon-152x152.png diff --git a/web/gui/images/apple-icon-180x180.png b/web/gui/images/apple-icon-180x180.png Binary files differnew file mode 100644 index 0000000..1a58fdb --- /dev/null +++ b/web/gui/images/apple-icon-180x180.png diff --git a/web/gui/images/apple-icon-57x57.png b/web/gui/images/apple-icon-57x57.png Binary files differnew file mode 100644 index 0000000..36c273c --- /dev/null +++ b/web/gui/images/apple-icon-57x57.png diff --git a/web/gui/images/apple-icon-60x60.png b/web/gui/images/apple-icon-60x60.png Binary files differnew file mode 100644 index 0000000..c3c48c8 --- /dev/null +++ b/web/gui/images/apple-icon-60x60.png diff --git a/web/gui/images/apple-icon-72x72.png b/web/gui/images/apple-icon-72x72.png Binary files differnew file mode 100644 index 0000000..7f7043f --- /dev/null +++ b/web/gui/images/apple-icon-72x72.png diff --git a/web/gui/images/apple-icon-76x76.png b/web/gui/images/apple-icon-76x76.png Binary files differnew file mode 100644 index 0000000..b5e73cd --- /dev/null +++ b/web/gui/images/apple-icon-76x76.png diff --git a/web/gui/images/apple-icon-precomposed.png b/web/gui/images/apple-icon-precomposed.png Binary files differnew file mode 100644 index 0000000..f69945b --- /dev/null +++ b/web/gui/images/apple-icon-precomposed.png diff --git a/web/gui/images/apple-icon.png b/web/gui/images/apple-icon.png Binary files differnew file mode 100644 index 0000000..f69945b --- /dev/null +++ b/web/gui/images/apple-icon.png diff --git a/web/gui/images/banner-icon-144x144.png b/web/gui/images/banner-icon-144x144.png Binary files differnew file mode 100644 index 0000000..c3013cc --- /dev/null +++ b/web/gui/images/banner-icon-144x144.png diff --git a/web/gui/images/check-mark-2-128-green.png b/web/gui/images/check-mark-2-128-green.png Binary files differnew file mode 100644 index 0000000..e04ddca --- /dev/null +++ b/web/gui/images/check-mark-2-128-green.png diff --git a/web/gui/images/check-mark-2-multi-size-green.ico b/web/gui/images/check-mark-2-multi-size-green.ico Binary files differnew file mode 100644 index 0000000..2fc4141 --- /dev/null +++ b/web/gui/images/check-mark-2-multi-size-green.ico diff --git a/web/gui/images/favicon-16x16.png b/web/gui/images/favicon-16x16.png Binary files differnew file mode 100644 index 0000000..43eb188 --- /dev/null +++ b/web/gui/images/favicon-16x16.png diff --git a/web/gui/images/favicon-32x32.png b/web/gui/images/favicon-32x32.png Binary files differnew file mode 100644 index 0000000..e657e92 --- /dev/null +++ b/web/gui/images/favicon-32x32.png diff --git a/web/gui/images/favicon-96x96.png b/web/gui/images/favicon-96x96.png Binary files differnew file mode 100644 index 0000000..1bbf594 --- /dev/null +++ b/web/gui/images/favicon-96x96.png diff --git a/web/gui/images/favicon.ico b/web/gui/images/favicon.ico Binary files differnew file mode 100644 index 0000000..7ed9572 --- /dev/null +++ b/web/gui/images/favicon.ico diff --git a/web/gui/images/ms-icon-144x144.png b/web/gui/images/ms-icon-144x144.png Binary files differnew file mode 100644 index 0000000..c3013cc --- /dev/null +++ b/web/gui/images/ms-icon-144x144.png diff --git a/web/gui/images/ms-icon-150x150.png b/web/gui/images/ms-icon-150x150.png Binary files differnew file mode 100644 index 0000000..f0cf412 --- /dev/null +++ b/web/gui/images/ms-icon-150x150.png diff --git a/web/gui/images/ms-icon-310x310.png b/web/gui/images/ms-icon-310x310.png Binary files differnew file mode 100644 index 0000000..4f5f7e6 --- /dev/null +++ b/web/gui/images/ms-icon-310x310.png diff --git a/web/gui/images/ms-icon-70x70.png b/web/gui/images/ms-icon-70x70.png Binary files differnew file mode 100644 index 0000000..70012c6 --- /dev/null +++ b/web/gui/images/ms-icon-70x70.png diff --git a/web/gui/images/netdata-logomark.svg b/web/gui/images/netdata-logomark.svg new file mode 100644 index 0000000..87fb2bd --- /dev/null +++ b/web/gui/images/netdata-logomark.svg @@ -0,0 +1,3 @@ +<svg width="1723" height="1723" viewBox="0 0 1723 1723" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M0.628784 849.678C0.628784 473.909 235.042 153.621 563.766 30.7914C701.438 19.0613 843.892 50.2449 970.557 129.297C1052.47 180.42 1119.71 246.528 1170.96 321.982C1161.21 207.568 1122.97 96.4678 1058.94 0.187012C1220.56 38.587 1364.64 123.126 1476.91 239.343C1518.34 297.634 1548.55 365.545 1563.67 440.489C1578.54 514.244 1577.35 587.545 1562.5 656.661C1601.04 613.105 1632.22 563.24 1654.63 509.251C1698.41 613.852 1722.63 728.899 1722.63 849.678C1722.63 1331.55 1337.15 1722.19 861.629 1722.19C386.112 1722.19 0.628784 1331.55 0.628784 849.678ZM1178.87 1369.04C1286.71 1369.04 1374.13 1280.45 1374.13 1171.17C1374.13 1061.88 1286.71 973.293 1178.87 973.293C1071.03 973.293 983.603 1061.88 983.603 1171.17C983.603 1280.45 1071.03 1369.04 1178.87 1369.04Z" fill="#00C853"/> +</svg> diff --git a/web/gui/images/netdata.svg b/web/gui/images/netdata.svg new file mode 100644 index 0000000..f8ddbda --- /dev/null +++ b/web/gui/images/netdata.svg @@ -0,0 +1,18 @@ +<?xml version="1.0" standalone="no"?> +<!-- SPDX-License-Identifier: CC0-1.0 --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<svg version="1.0" xmlns="http://www.w3.org/2000/svg" + width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000" + preserveAspectRatio="xMidYMid meet"> + <metadata> + Created by potrace 1.15, written by Peter Selinger 2001-2017 + </metadata> + <g transform="translate(0.000000,16.000000) scale(0.003125,-0.003125)" fill="#000000" stroke="none"> + <path d="M3643 5008 c-235 -199 -1100 -956 -1108 -968 -4 -6 103 -10 293 -10 165 0 314 -3 331 -6 41 -8 40 -23 -4 -194 -95 -361 -208 -619 -396 -899 -425 -633 -1052 -1047 -1776 -1172 -159 -27 -444 -36 -647 -19 -185 15 -206 11 -206 -30 0 -24 7 -33 39 -50 80 -40 389 -115 646 -155 139 -22 612 -32 781 -16 910 85 1765 550 2281 1239 227 303 365 582 479 971 26 88 74 299 74 327 0 2 127 4 283 4 l282 0 -45 43 c-25 23 -167 148 -315 277 -149 129 -355 309 -460 400 -298 261 -404 350 -414 350 -5 0 -58 -42 -118 -92z"/> + <path d="M4542 3770 c-74 -276 -162 -509 -266 -705 -73 -137 -190 -325 -270 -430 l-66 -88 0 -1269 0 -1268 320 0 320 0 -1 1773 c-1 974 -4 1840 -8 1922 l-6 150 -23 -85z"/> + <path d="M3555 2148 c-96 -82 -310 -238 -442 -323 l-123 -78 0 -868 0 -869 320 0 320 0 0 1095 c0 602 -3 1095 -7 1095 -5 0 -35 -23 -68 -52z"/> + <path d="M2599 1566 c-85 -36 -270 -95 -419 -136 l-135 -37 -3 -692 -2 -691 310 0 310 0 0 790 c0 435 -1 790 -2 790 -2 -1 -28 -11 -59 -24z"/> + <path d="M127 1403 c-4 -54 -7 -389 -7 -745 l0 -648 320 0 320 0 0 669 0 669 -117 21 c-127 24 -342 78 -437 111 -33 11 -62 20 -66 20 -4 0 -10 -44 -13 -97z"/> + <path d="M1635 1330 c-27 -5 -122 -9 -211 -9 -88 -1 -202 -4 -252 -7 l-92 -7 0 -648 0 -649 315 0 315 0 0 619 c0 577 -4 713 -19 710 -3 -1 -28 -5 -56 -9z"/> + </g> +</svg> diff --git a/web/gui/images/post.png b/web/gui/images/post.png Binary files differnew file mode 100644 index 0000000..6bad547 --- /dev/null +++ b/web/gui/images/post.png diff --git a/web/gui/images/seo-performance-128.png b/web/gui/images/seo-performance-128.png Binary files differnew file mode 100644 index 0000000..2a212a4 --- /dev/null +++ b/web/gui/images/seo-performance-128.png diff --git a/web/gui/index.html b/web/gui/index.html new file mode 100644 index 0000000..faee5ba --- /dev/null +++ b/web/gui/index.html @@ -0,0 +1,1371 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': + new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], + j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= + 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); + })(window,document,'script','dataLayer','GTM-N6CBMJD'); + dataLayer.push({"anonymous_statistics" : "false"}); + </script> + <title>netdata dashboard</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + <meta name="author" content="costa@tsaousis.gr"> + + <link rel="stylesheet" type="text/css" href="main.css?v=4"> + + <link rel="icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAA7EAAAOxAGVKw4bAAACyklEQVRYhcWXz0sUYRjHP8+wLItImEhnEfEgEVJk+56CbCECQWezOkTQTTp6kejgKUSoEAoK/wAhaaeDBkLoIahZIWIJo0U8hHQJJBYJERGfDrOju7PjuO5u6/c0PM/7zvfzvvP+eEaoVu6wBZIA3cW82wtvY7cD1xEWSTpb1bxWjm2RtbtQxoF7iLSA7gO/UL4A74G3mBIzNz0Peg1hFmUK46zXBuDaCYQJlDFE4ke/QreAZyhPMc42rt2PyEoxt4cyDUxgnO3qAVy7C8gg0hdFHwBZA0ZIOt9w7e+I9B6mdBVhmGTlbFQCuPYFhA8g56o3P3D6CwyiDCIyFshtgqRIZnKlUStg3lW7OYC0AvPATkiuA9U3uOlEOEDWTgCZ2s3LIMbCU9ID3A8HUCZO9s2jGCRxdFIflDUF/EX3I3q1N0iq+8BZf+v6MzDeFHMAEQvoJpuOAwiu3Qr89g6ZJkm5CnoHeBwDbjTV3CPoRRhF+WQBA801B+AJiAUMWMDFptuLtBef+iygs+kAh+q0gDOnCNBmETyOmywLKJyifyEG/ATqPP+LUt0FZoAlIA6MgNyKqDo2YkAO6G+QeQrjfCyJzuHaoyCvjuiVs4q0jdBMwNyTcV6j+jm0h7BkAYuohpZLJ1TUQJYrIqo7KAtW8VaabQBA1GVWmROZwzgFfwtOoRpealevdGg0a8eAoUB0D9VJ8M8A46yDTNdlL9wmaz8MMX9RrIQOpfoS4+S9br7cdAvoCiLn6wLxFtwyQhxlKMQ8j3CJpFeml+9QN90N6iLSURfEkXD8AQwms+aHyo9hk1kHSaG6+Z/MU6XmlQAeRA7EoLraQPM83si/BlPhF5E3E1dQfY5S++5Q/9dMLwdH7uv4n1PX7gEeAXejy+0y4x2QOWASk8lHNT0e4AAk3QZ6E6+E68MrZNqK2QKwgXevLCEskHSqumX/AUXU5QBtOC5FAAAAAElFTkSuQmCC"> + + <!-- <link rel="apple-touch-icon" sizes="57x57" href="images/apple-icon-57x57.png"> + <link rel="apple-touch-icon" sizes="60x60" href="images/apple-icon-60x60.png"> + <link rel="apple-touch-icon" sizes="72x72" href="images/apple-icon-72x72.png"> + <link rel="apple-touch-icon" sizes="76x76" href="images/apple-icon-76x76.png"> + <link rel="apple-touch-icon" sizes="114x114" href="images/apple-icon-114x114.png"> + <link rel="apple-touch-icon" sizes="120x120" href="images/apple-icon-120x120.png"> + <link rel="apple-touch-icon" sizes="144x144" href="images/apple-icon-144x144.png"> + <link rel="apple-touch-icon" sizes="152x152" href="images/apple-icon-152x152.png"> + <link rel="apple-touch-icon" sizes="180x180" href="images/apple-icon-180x180.png"> + <link rel="icon" type="image/png" sizes="192x192" href="images/android-icon-192x192.png"> + <link rel="icon" type="image/png" sizes="32x32" href="images/favicon-32x32.png"> + <link rel="icon" type="image/png" sizes="96x96" href="images/favicon-96x96.png"> + <link rel="icon" type="image/png" sizes="16x16" href="images/favicon-16x16.png"> + <link rel="manifest" href="manifest.json"> + <meta name="msapplication-TileColor" content="#ffffff"> + <meta name="msapplication-TileImage" content="images/ms-icon-144x144.png"> + <meta name="theme-color" content="#ffffff"> --> + + <meta property="og:locale" content="en_US" /> + <meta property="og:url" content="https://my-netdata.io" /> + <meta property="og:type" content="website" /> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta property="og:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png" /> + <meta property="og:image:type" content="image/png" /> + <meta property="fb:app_id" content="1200089276712916" /> + + <meta name="twitter:card" content="summary" /> + <meta name="twitter:site" content="@linuxnetdata" /> + <meta name="twitter:title" content="Get control of your Linux Servers. Simple. Effective. Awesome." /> + <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" /> + + <script src="main.js?v=4"></script> +</head> + +<body data-spy="scroll" data-target="#sidebar" data-offset="100"> + <div id="loadOverlay" class="loadOverlay" style="background-color: #fff; color: #888;"> + <div style="font-size: 3vh;"> + You must enable JavaScript in order to use Netdata!<br /> + You can do this in <a href="https://enable-javascript.com/" target="_blank">your browser settings</a>. + </div> + </div> + <script type="text/javascript"> + // Cleanup JS warning. + document.documentElement.style.overflowY = "scroll"; + + // Change the loadOverlay colors ASAP to match the theme. + let theme; + const hash = document.location.hash; + if (hash.includes('theme=slate')) { + theme = 'slate'; + } else if (hash.includes('theme=white')) { + theme = 'white'; + } else { + theme = localStorage.getItem('netdataTheme') || 'slate'; + } + const overlayEl = document.getElementById('loadOverlay'); + overlayEl.innerHTML = 'netdata<br/><div style="font-size: 3vh;">Real-time performance monitoring, done right!</div>'; + overlayEl.style = theme == 'slate' ? "background-color: #272b30; color: #373b40;" : "background-color: #fff; color: #ddd;"; + </script> + <nav class="navbar navbar-default navbar-fixed-top" role="banner"> + <div class="container"> + <!-- <nav id="mynetdata_nav" class="collapse navbar-collapse navbar-left" role="navigation" style="padding-right: 20px;"> + <ul class="nav navbar-nav"> + <li data-placement="right" style="line-height: 50px; margin-right: 15px" title="Netdata Agent"> + <img src="images/netdata-logomark.svg" height="32"/> + </li> + <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> + <a href="#" id="hostname" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> + </div> + </li> + </ul> + </nav> --> + <div class="navbar-header"> + <button class="navbar-toggle" type="button" data-toggle="collapse" data-target=".navbar-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <!-- <a href="/" class="navbar-brand" id="1hostname" title="server hostname<br/>click it to reload the dashboard" data-toggle="tooltip" data-placement="bottom">netdata</a> --> + <ul class="nav navbar-nav" style="display: inline-block"> + <li data-placement="right" class="hidden-xs hidden-sm" style="line-height: 50px; margin-right: 15px" title="Netdata Agent"> + <img src="images/netdata-logomark.svg" height="32"/> + </li> + <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> + <a href="#" id="hostname" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> + </div> + </li> + </ul> + </div> + <nav class="collapse navbar-collapse navbar-right" role="navigation"> + <ul class="nav navbar-nav"> + <li id="alarmsButton" title="check the health monitoring alarms and their log" data-toggle="tooltip" data-placement="bottom"><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal"><i class="fas fa-bell"></i> <span class="hidden-sm hidden-md">Alarms </span><span id="alarms_count_badge" class="badge"></span></a></li> + <li title="change dashboard settings" data-toggle="tooltip" data-placement="bottom"><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal"><i class="fas fa-cog"></i> <span class="hidden-sm hidden-md">Settings</span></a></li> + <li title="check for netdata updates<br/>you should keep your netdata updated" data-toggle="tooltip" data-placement="bottom" class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal"><i class="fas fa-cloud-download-alt"></i> <span class="hidden-sm hidden-md">Update </span><span id="update_badge" class="badge"></span></a></li> + <li title="the netdata wiki home at github<br/>remember to <b>give netdata a <i class="fas fa-star"></i></b> !" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://github.com/netdata/netdata" class="btn" target="_blank"><i class="fab fa-github"></i></a></li> + <li title="follow netdata on twitter" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://twitter.com/linuxnetdata" class="btn" target="_blank"><i class="fab fa-twitter"></i></a></li> + <li title="like netdata on facebook" data-toggle="tooltip" data-placement="bottom" class="hidden-xs hidden-sm hidden-md"><a href="https://www.facebook.com/linuxnetdata/" class="btn" target="_blank"><i class="fab fa-facebook"></i></a></li> + <li title="import / load a netdata snapshot" data-toggle="tooltip" data-placement="bottom" id="loadButton"><a href="#" class="btn" data-toggle="modal" data-target="#loadSnapshotModal"><i class="fas fa-download"></i> <span class="hidden-sm hidden-md hidden-lg">Import</span></a></li> + <li title="export / save a netdata snapshot" data-toggle="tooltip" data-placement="bottom" id="saveButton"><a href="#" class="btn" data-toggle="modal" data-target="#saveSnapshotModal"><i class="fas fa-upload"></i> <span class="hidden-sm hidden-md hidden-lg">Export</span></a></li> + <li title="print this dashboard to PDF" data-toggle="tooltip" data-placement="bottom" id="printButton"><a href="#" class="btn" data-toggle="modal" data-target="#printPreflightModal"><i class="fas fa-print"></i> <span class="hidden-sm hidden-md hidden-lg">Print</span></a></li> + <li title="get help on using the charts" data-toggle="tooltip" data-placement="bottom" class="hidden-sm"><a href="#" class="btn" data-toggle="modal" data-target="#helpModal"><i class="fas fa-question-circle"></i> <span class="hidden-sm hidden-md">Help</span></a></li> + <li id="account-menu-container" class="dropdown" data-toggle="tooltip"></li> + <!-- + <li class="dropdown hidden-sm hidden-md hidden-lg" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a> + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu"> + <div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div> + </div> + </li> + --> + <!-- + <li class="dropdown hidden-sm hidden-md hidden-lg"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">My Nodes <strong class="caret"></strong></a> + <ul id="mynetdata_servers2" class="dropdown-menu scrollable-menu inpagemenu" role="menu"> + <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li> + </ul> + </li> + --> + </ul> + </nav> + </div> + </nav> + <div class="navbar-highlight"> + <div id="navbar-highlight-content" class="navbar-highlight-content"></div> + </div> + + <div id="masthead" style="display: none;"> + <div class="container"> + <div class="row"> + <div class="col-md-7"> + <h1>Netdata + <p class="lead">Real-time performance monitoring, in the greatest possible detail</p> + </h1> + </div> + <div class="col-md-5"> + <div class="well well-lg"> + <div class="row"> + <div class="col-md-6"> + <b>Drag</b> charts to pan. + <b>Shift + wheel</b> on them, to zoom in and out. + <b>Double-click</b> on them, to reset. + <b>Hover</b> on them too! + </div> + <div class="col-md-6"> + <div class="netdata-container" data-netdata="system.intr" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dygraph-type="line" data-dygraph-strokewidth="3" data-dygraph-smooth="true" data-dygraph-highlightcirclesize="6" data-after="-90" data-height="60px" data-colors="#C66"></div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div class="container"> + <div class="row"> + <div class="charts-body" role="main"> + <div id="charts_div"></div> + </div> + <div class="sidebar-body hidden-xs hidden-sm hidden-print" id="sidebar-body" role="complementary"> + <nav class="dashboard-sidebar hidden-print hidden-xs hidden-sm" id="sidebar" role="menu"></nav> + </div> + </div> + </div> + + <div id="footer" class="container" style="display: none;"> + <div class="row"> + <div class="col-md-10" role="main"> + <div class="p"> + <big><a href="https://github.com/netdata/netdata/wiki" target="_blank">Netdata</a></big> + <br /><br /> + <i class="fas fa-copyright"></i> Copyright 2018, <a href="mailto:info@netdata.cloud">Netdata, Inc</a>.<br/> + <i class="fas fa-copyright"></i> Copyright 2016-2018, <a href="mailto:costa@tsaousis.gr">Costa Tsaousis</a>.<br/> + </div> + <div class="p"> + Released under <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPL v3 or later</a>. + Netdata uses <a href="https://github.com/netdata/netdata/blob/master/REDISTRIBUTED.md" target="_blank">third party tools</a>. + <br /><br /> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="xssModal" tabindex="-1" role="dialog" aria-labelledby="xssModalLabel" data-keyboard="false" data-backdrop="static" style="z-index: 3000"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <h4 class="modal-title" id="xssModalLabel">XSS Protection</h4> + </div> + <div class="modal-body"> + <p> + This dashboard is about to render data from server: + </p> + <p style="font-size: 1.25em;"> + <code id="netdataXssModalServer"></code> + </p> + <p> + To protect your privacy, the dashboard will <b>check all data transferred</b> for cross site scripting (XSS). + <br/>This is CPU intensive, so your browser might be a bit slower. + </p> + <p> + If you <b>trust</b> the remote server, you can disable XSS protection.<br/> + In this case, any remote dashboard decoration code (javascript) will also run. + </p> + <p> + If you <b>don't trust</b> the remote server, you should keep the protection on.<br/> + The dashboard will run slower and remote dashboard decoration code will not run, but better be safe than sorry... + </p> + </div> + <div class="modal-footer"> + <a href="#" onclick="return xssModalKeepXss();" type="button" class="btn btn-success" data-dismiss="modal">Keep protecting me</a> + <a href="#" onclick="return xssModalDisableXss();" type="button" class="btn btn-danger" data-dismiss="modal">I don't need this, the server is mine</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="printPreflightModal" tabindex="-1" role="dialog" aria-labelledby="printPreflightModalLabel"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="printPreflightModalLabel">Print this netdata dashboard</h4> + </div> + <div class="modal-body"> + <p> + netdata dashboards cannot be captured, since we are lazy loading and hiding all but the visible charts. + <br/> + To capture the whole page with all the charts rendered, a new browser window will pop-up that will render all the charts at once. + The new browser window will maintain the current pan and zoom settings of the charts. So, align the charts before proceeding. + </p> + <p> + <small> + This process will put some CPU and memory pressure on your browser.<br/> + For the netdata server, we will sequencially download all the charts, to avoid congesting network and server resources.<br/> + <b>Please, do not print netdata dashboards on paper!</b> + </small> + </p> + </div> + <div class="modal-footer"> + <a href="#" onclick="printPreflight(); return false;" type="button" class="btn btn-default">Print</a> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="printModal" tabindex="-1" role="dialog" aria-labelledby="printModalLabel" data-keyboard="false" data-backdrop="static"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="printModalLabel">Preparing dashboard for printing...</h4> + </div> + <div class="modal-body"> + Please wait while we initialize and render all the charts on the dashboard. + <div class="progress progress-striped active" style="height: 2em !important;"> + <div id="printModalProgressBar" class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em;"> + <span id="printModalProgressBarText" style="padding-left: 10px; padding-top: 4px; font-size: 1.2em; text-align: left; width: 100%; position: absolute; display: block; color: black;"></span> + </div> + </div> + The print dialog will appear as soon as we finish rendering the page. + </div> + <div class="modal-footer"> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="loadSnapshotModal" tabindex="-1" role="dialog" aria-labelledby="loadSnapshotModalLabel"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="loadSnapshotModalLabel">Import a netdata snapshot</h4> + </div> + <div id="loadSnapshotDragAndDrop" class="modal-body"> + <p> + netdata can export and import dashboard snapshots. + Any netdata can import the snapshot of any other netdata. + The snapshots are not uploaded to a server. They are handled entirely by your web browser, on your computer. + </p> + <p style="text-align: center;"> + <label class="btn btn-default"> + Click here to select the netdata snapshot file to import + <input type="file" id="loadSnapshotSelectFiles" value="Import" style="display: none;" + onchange="loadSnapshotPreflight();"> + </label> + </p> + <div id="loadSnapshotStatus" class="alert alert-info" role="alert"> + Browse for a snapshot file (or drag it and drop it here), then click <b>Import</b> to render it. + </div> + <p> + <table class="table"> + <tbody> + <tr><th>Filename</th><td id="loadSnapshotFilename"></td></tr> + <tr><th>Hostname</th><td id="loadSnapshotHostname"></td></tr> + <tr><th>Origin URL</th><td id="loadSnapshotURL"></td></tr> + <tr><th>Charts Info</th><td id="loadSnapshotCharts"></td></tr> + <tr><th>Snapshot Info</th><td id="loadSnapshotInfo"></td></tr> + <tr><th>Time Range</th><td id="loadSnapshotTimeRange"></td></tr> + <tr><th>Comments</th><td id="loadSnapshotComments"></td></tr> + </tbody> + </table> + </p> + </div> + <div class="modal-footer"> + <span style="display: inline-block; padding-right: 20px;">Snapshot files contain both data and javascript code. Make sure <b>you trust the files</b> you import!</span> + <a id="loadSnapshotImport" href="#" onclick="loadSnapshot(); return false;" type="button" class="btn btn-success disabled">Import</a> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="saveSnapshotModal" tabindex="-1" role="dialog" aria-labelledby="saveSnapshotModalLabel" data-keyboard="false" data-backdrop="static"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="saveSnapshotModalLabel">Export a snapshot</h4> + </div> + <div class="modal-body"> + <div id="saveSnapshotModalProgressSection" hidden> + Please wait while we collect all the dashboard data... + <div class="progress progress-striped active" style="height: 2em !important;"> + <div id="saveSnapshotModalProgressBar" class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="min-width: 2em;"> + <span id="saveSnapshotModalProgressBarText" style="padding-left: 10px; padding-top: 4px; font-size: 1.2em; text-align: left; width: 100%; position: absolute; display: block;"></span> + </div> + </div> + </div> + + <div id="saveSnapshotResolutionRadio" style="text-align: center;"> + Select the desired resolution of the snapshot. This is the <b>seconds of data per point</b>. + <br/> + + <br/> + + <br/> + <input id="saveSnapshotResolutionSlider" data-slider-id='saveSnapshotResolutionSlider' type="text" style="width: 80%;" tabindex="0"/> + <br/> <br/> + <div class="input-group"> + <span class="input-group-addon" id="sizing-saveSnapshotFilename" style="width: 100px;">Filename</span> + <input id="saveSnapshotFilename" class="form-control" placeholder="Filename of the generated snapshot" aria-describedby="sizing-saveSnapshotFilename" tabindex="2"/> + <div class="input-group-btn"> + <div class="input-group-btn"> + <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><span id="saveSnapshotCompressionName">Compression</span> <span class="caret"></span></button> + <ul class="dropdown-menu dropdown-menu-right"> + <li class="disabled"><a href="#" class="disabled">Select Compression</a></li> + <li role="separator" class="divider"></li> + <li><a href="#" onclick="saveSnapshotSetCompression('none'); return false;">uncompressed</a></li> + <li role="separator" class="divider"></li> + <li><a href="#" onclick="saveSnapshotSetCompression('pako.deflate'); return false;">pako.deflate (gzip, binary)</a></li> + <li><a href="#" onclick="saveSnapshotSetCompression('pako.deflate.base64'); return false;">pako.deflate.base64 (gzip, ascii)</a></li> + <li role="separator" class="divider"></li> + <li><a href="#" onclick="saveSnapshotSetCompression('lzstring.uri'); return false;">lzstring.uri (LZ, ascii)</a></li> + <li><a href="#" onclick="saveSnapshotSetCompression('lzstring.utf16'); return false;">lzstring.utf16 (LZ, utf16)</a></li> + <li><a href="#" onclick="saveSnapshotSetCompression('lzstring.base64'); return false;">lzstring.base64 (LZ, ascii)</a></li> + </ul> + </div><!-- /btn-group --> + </div> + </div> + <div class="input-group" style="padding-top: 10px; width: 100%"> + <span class="input-group-addon" id="sizing-saveSnapshotComments" style="width: 100px;">Comments</span> + <input id="saveSnapshotComments" class="form-control" placeholder="Any comments about this snapshot?" aria-describedby="sizing-saveSnapshotComments" tabindex="3"/> + </div> + </div> + + + <div id="saveSnapshotStatus" class="alert alert-info" role="alert"> + Select snaphost resolution. This controls the size the snapshot file. + </div> + <p> + The generated snapshot will include all charts of this dashboard, <b>for the visible timeframe</b>, so align, pan and zoom the charts as needed. + The scroll position of the dashboard will also be saved. + The snapshot will be downloaded as a file, to your computer, that can be imported back into any netdata dashboard (no need to import it back on this server). + </p> + <p> + <small> + Snapshot files include all the information of the dashboard, including the URL of the origin server, its netdata unique ID, etc. + So, if you share the snapshot file with third parties, they will be able to access the origin server, if this server is exposed on the internet. + <br/> + Snapshots are handled entirely by the web browser. The netdata servers are not aware of them. + </small> + </p> + </div> + <div class="modal-footer"> + <a id="saveSnapshotExport" href="#" onclick="saveSnapshot(); return false;" type="button" class="btn btn-success" tabindex="4">Export</a> + <button type="button" class="btn btn-default" data-dismiss="modal" tabindex="5">Cancel</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="welcomeModal" tabindex="-1" role="dialog" aria-labelledby="welcomeModalLabel"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="welcomeModalLabel">Welcome to the world of netdata</h4> + </div> + <div class="modal-body"> + <div class="p"> + <div style="width: 100%; text-align: center; padding-top: 10px; padding-bottom: 10px; font-size: 18px;"> + if there is a metric for something, we want it visualised<br/> + and we want this visualisation to be <strong>real-time</strong>, <strong>efficient</strong> and <strong>awesome</strong> + </div> + </div> + <div class="p"> + <b><a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a></b> + is a new way to monitor your systems and applications, to get <strong>real-time insights</strong> + of what is really happening and what affects performance. + It is carefully optimised to be a real-time system, without interfering in any way, + to the core function of your systems. + </div> + <div class="p"> + <b><a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a></b> + has been designed to monitor <strong>massive amounts of metrics, per server, per second</strong>. + When installed, it might come up with 1k to 3k metrics, but we have been testing it with 100k + metrics, all collected per second, and still the cpu utilisation remained negligible. + <br/> + We have also tried to give each metric, a meaning, a context. + We have grouped and categorized all metrics into meaningful charts, providing a + better understanding of the underlying technologies and mechanisms. + </div> + <div class="p"> + <b><a href="https://github.com/netdata/netdata/wiki" target="_blank">netdata</a></b> is free, + open-source software. If you decide to use it, + <strong><a href="https://github.com/netdata/netdata/tree/master/docs/a-github-star-is-important.md" target="_blank">it is important to give netdata a star at GitHub</a></strong>. + </div> + <div class="p"> + Enjoy real-time performance monitoring! + </div> + <div class="p"> + Costa Tsaousis + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="helpModal" tabindex="-1" role="dialog" aria-labelledby="helpModalLabel"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="helpModalLabel">Dashboard Help</h4> + </div> + <div class="modal-body"> + + <h4>Dygraphs (line, area and stacked area charts)</h4> + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist"> + <li role="presentation" class="active"><a href="#help_mouse" aria-controls="help_mouse" role="tab" data-toggle="tab">Mouse Interface</a></li> + <li role="presentation"><a href="#help_touch" aria-controls="help_touch" role="tab" data-toggle="tab">Touch Interface</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="help_mouse"> + <div class="p"> + <h4>Mouse Over / Hover</h4> + Mouse over on a chart to show, at its legend, the values for the timestamp under the mouse (the chart will also highlight the point at the chart). + <br/> + All the other visible charts will also show and highlight their values for the same timestamp. + </div> + <hr/> + <div class="p"> + <h4>Drag Chart Contents</h4> + Drag the contents of a chart, by pressing the left mouse button and moving the mouse, to pan it horizontally. + <br/> + All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring). + <br/> + Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double click</b> a panned chart. + </div> + <hr/> + <div class="p"> + <h4>Double Click</h4> + Double Click a chart to reset all the charts to their default auto-refreshing state. + </div> + <hr/> + <div class="p"> + <h4>SHIFT + Drag</h4> + While pressing the <code>SHIFT</code> key, press the left mouse button on the contents of a chart and move the mouse to select an area, to zoom in. The other charts will follow too. Zooming is performed in two phases: + <ul> + <li>The already loaded chart contents are zoomed (low resolution)</li> + <li>New data are transferred from the netdata server, to refresh the chart with possibly more detail.</li> + </ul> + Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. + </div> + <hr/> + <div class="p"> + <h4>Highlight Timeframe</h4> + While pressing the <code>ALT</code> key, press the left mouse button on the contents of a chart and move the mouse to select an area. The selected are will be highlighted on all charts. + </div> + <hr/> + <div class="p"> + <h4>SHIFT + Mouse Wheel</h4> + While pressing the <code>SHIFT</code> key and the mouse pointer is over the contents of a chart, scroll the mouse wheel to zoom in or out. This kind of zooming is aligned to center below the mouse pointer. The other charts will follow too. + <br/> + Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. + </div> + <hr/> + <div class="p"> + <h4>Legend Operations</h4> + Click on the label or value of a dimension, will select / un-select this dimension. + <br/> + You can press any of the SHIFT or CONTROL keys and then click on legend labels or values, to select / un-select multiple dimensions. + </div> + </div> + <div role="tabpanel" class="tab-pane" id="help_touch"> + <div class="p"> + <h4>Single Tap</h4> + Single Tap on the contents of a chart to show, at its legend, the values for the timestamp tapped (the chart will also highlight the point at the chart). + <br/> + All the other visible charts will also show and highlight their values for the same timestamp. + </div> + <hr/> + <div class="p"> + <h4>Drag Chart Contents</h4> + Touch and Drag the contents of a chart to pan it horizontally. + <br/> + All the charts will follow soon after you let the chart alone (this little delay is by design: it speeds up your browser and lets you focus on what you are exploring). + <br/> + Once a chart is panned, auto refreshing stops for all charts. To enable it again, <b>double tap</b> a panned chart. + </div> + <hr/> + <div class="p"> + <h4>Double Tap</h4> + Double tap a chart to reset all the charts to their default auto-refreshing state. + </div> + <hr/> + <div class="p"> + <h4>Zoom <small>(does not work on firefox and IE/Edge)</small></h4> + With two fingers, zoom in or out. + <br/> + Once a chart is zoomed, auto refreshing stops for all charts. To enable it again, <b>double click</b> a zoomed chart. + </div> + <hr/> + <div class="p"> + <h4>Legend Operations</h4> + Tap on the label or value of a dimension, will select / un-select this dimension. + </div> + </div> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="alarmsModal" tabindex="-1" role="dialog" aria-labelledby="alarmsModalLabel"> + <div class="modal-dialog modal-lg" role="document" style="display: table;"> <!-- allow the modal to expand horizontally --> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="alarmsModalLabel">netdata alarms</h4> + </div> + <div class="modal-body"> + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist"> + <li role="presentation" class="active"><a href="#alarms_active" aria-controls="alarms_active" role="tab" data-toggle="tab">Active</a></li> + <li role="presentation"><a href="#alarms_all" aria-controls="alarms_all" role="tab" data-toggle="tab">All</a></li> + <li role="presentation"><a href="#alarms_log" aria-controls="alarms_log" role="tab" data-toggle="tab">Log</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="alarms_active"> + loading... + </div> + <div role="tabpanel" class="tab-pane" id="alarms_all"> + loading... + </div> + <div role="tabpanel" class="tab-pane" id="alarms_log"> + loading... + </div> + </div> + </div> + <div class="modal-footer"> + <!-- <a href="#" onclick="alarmsUpdateModal(); return false;" type="button" class="btn btn-default">Update</a> --> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="optionsModal" tabindex="-1" role="dialog" aria-labelledby="optionsModalLabel"> + <div class="modal-dialog modal-lg" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="optionsModalLabel">netdata dashboard options</h4> + </div> + <div class="modal-body"> + <center> + <small style="color: #BBBBBB;">These are browser settings. Each viewer has its own. They do not affect the operation of your netdata server. + <br/> + Settings take effect immediately and are saved permanently to browser local storage (except the refresh on focus / always option). + <br/> + To reset all options (including charts sizes) to their defaults, click <a href="#" onclick="resetDashboardOptions(); return false;">here</a>.</small> + </center> + <div style="padding: 10px;"></div> + + <!-- Nav tabs --> + <ul class="nav nav-tabs" role="tablist"> + <li role="presentation" class="active"><a href="#settings_performance" aria-controls="settings_performance" role="tab" data-toggle="tab">Performance</a></li> + <li role="presentation"><a href="#settings_sync" aria-controls="settings_sync" role="tab" data-toggle="tab">Synchronization</a></li> + <li role="presentation"><a href="#settings_visual" aria-controls="settings_visual" role="tab" data-toggle="tab">Visual</a></li> + <li role="presentation"><a href="#settings_locale" aria-controls="settings_locale" role="tab" data-toggle="tab">Locale</a></li> + </ul> + + <!-- Tab panes --> + <div class="tab-content"> + <div role="tabpanel" class="tab-pane active" id="settings_performance"> + <form id="optionsForm1" method="get" class="form-horizontal"> + <div class="form-group"> + <table> + <tr class="option-row"> + <td class="option-control"><input id="stop_updates_when_focus_is_lost" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="On Focus" data-off="Always" data-width="110px"></td> + <td class="option-info"><strong>When to refresh the charts?</strong><br/> + <small>When set to <b>On Focus</b>, the charts will stop being updated if the page / tab does not have the focus of the user. When set to <b>Always</b>, the charts will always be refreshed. Set it to <b>On Focus</b> it to lower the CPU requirements of the browser (and extend the battery of laptops and tablets) when this page does not have your focus. Set to <b>Always</b> to work on another window (i.e. change the settings of something) and have the charts auto-refresh in this window.</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"> + <input id="eliminate_zero_dimensions" type="checkbox" checked data-toggle="toggle" data-on="Non Zero" data-off="All" data-width="110px"> + </td> + <td class="option-info"><strong>Which dimensions to show?</strong><br/> + <small>When set to <b>Non Zero</b>, dimensions that have all their values (within the current view) set to zero will not be transferred from the netdata server (except if all dimensions of the chart are zero, in which case this setting does nothing - all dimensions are transferred and shown). When set to <b>All</b>, all dimensions will always be shown. Set it to <b>Non Zero</b> to lower the data transferred between netdata and your browser, lower the CPU requirements of your browser (fewer lines to draw) and increase the focus on the legends (fewer entries at the legends).</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="destroy_on_hide" type="checkbox" data-toggle="toggle" data-on="Destroy" data-off="Hide" data-width="110px"></td> + <td class="option-info"><strong>How to handle hidden charts?</strong><br/> + <small>When set to <b>Destroy</b>, charts that are not in the current viewport of the browser (are above, or below the visible area of the page), will be destroyed and re-created if and when they become visible again. When set to <b>Hide</b>, the not-visible charts will be just hidden, to simplify the DOM and speed up your browser. Set it to <b>Destroy</b>, to lower the memory requirements of your browser. Set it to <b>Hide</b> for faster restoration of charts on page scrolling.</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="async_on_scroll" type="checkbox" data-toggle="toggle" data-on="Async" data-off="Sync" data-width="110px"></td> + <td class="option-info"><strong>Page scroll handling?</strong><br/> + <small>When set to <b>Sync</b>, charts will be examined for their visibility immediately after scrolling. On slow computers this may impact the smoothness of page scrolling. To update the page when scrolling ends, set it to <b>Async</b>. Set it to <b>Sync</b> for immediate chart updates when scrolling. Set it to <b>Async</b> for smoother page scrolling on slower computers.</small> + </td> + </tr> + </table> + </div> + </form> + </div> + <div role="tabpanel" class="tab-pane" id="settings_sync"> + <form id="optionsForm2" method="get" class="form-horizontal"> + <div class="form-group"> + <table> + <tr class="option-row"> + <td class="option-control"><input id="parallel_refresher" type="checkbox" checked data-toggle="toggle" data-on="Parallel" data-off="Sequential" data-width="110px"></td> + <td class="option-info"><strong>Which chart refresh policy to use?</strong><br/> + <small>When set to <b>parallel</b>, visible charts are refreshed in parallel (all queries are sent to netdata server in parallel) and are rendered asynchronously. When set to <b>sequential</b> charts are refreshed one after another. Set it to parallel if your browser can cope with it (most modern browsers do), set it to sequential if you work on an older/slower computer.</small> + </td> + </tr> + <tr class="option-row" id="concurrent_refreshes_row"> + <td class="option-control"><input id="concurrent_refreshes" type="checkbox" checked data-toggle="toggle" data-on="Resync" data-off="Best Effort" data-width="110px"></td> + <td class="option-info"><strong>Shall we re-sync chart refreshes?</strong><br/> + <small>When set to <b>Resync</b>, the dashboard will attempt to re-synchronize all the charts so that they are refreshed concurrently. When set to <b>Best Effort</b>, each chart may be refreshed with a little time difference to the others. Normally, the dashboard starts refreshing them in parallel, but depending on the speed of your computer and the network latencies, charts start having a slight time difference. Setting this to <b>Resync</b> will attempt to re-synchronize the charts on every update. Setting it to <b>Best Effort</b> may lower the pressure on your browser and the network.</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="sync_selection" type="checkbox" checked data-toggle="toggle" data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td> + <td class="option-info"><strong>Sync hover selection on all charts?</strong><br/> + <small>When enabled, a selection on one chart will automatically select the same time on all other visible charts and the legends of all visible charts will be updated to show the selected values. When disabled, only the chart getting the user's attention will be selected. Enable it to get better insights of the data. Disable it if you are on a very slow computer that cannot actually do it.</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="sync_pan_and_zoom" type="checkbox" checked data-toggle="toggle" data-on="Sync" data-off="Don't Sync" data-onstyle="success" data-offstyle="danger" data-width="110px"></td> + <td class="option-info"><strong>Sync pan and zoom on all charts?</strong><br/> + <small>When enabled, pan and zoom operations on a chart will be replicated to all charts (even the ones that are not currently visible - of course only when they will become visible). When disabled, pan and zoom operations will not be propagated to other charts.</small> + </td> + </tr> + </table> + </div> + </form> + </div> + <div role="tabpanel" class="tab-pane" id="settings_visual"> + <form id="optionsForm3" method="get" class="form-horizontal"> + <div class="form-group"> + <table> + <tr class="option-row"> + <td class="option-control"><input id="netdata_theme_control" type="checkbox" checked data-toggle="toggle" data-offstyle="danger" data-onstyle="success" data-on="Dark" data-off="White" data-width="110px"></td> + <td class="option-info"><strong>Which theme to use?</strong><br/> + <small>Netdata comes with two themes: <b>Dark</b> (the default) and <b>White</b>. + <br/> + <b>Switching this will reload the dashboard</b>. + </small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="show_help" type="checkbox" checked data-toggle="toggle" data-on="Help Me" data-off="No Help" data-width="110px"></td> + <td class="option-info"><strong>Do you need help?</strong><br/> + <small>Netdata can show some help in some areas to help you use the dashboard. If all these balloons bother you, disable them using this switch. + <br/> + <b>Switching this will reload the dashboard</b>. + </small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="pan_and_zoom_data_padding" type="checkbox" checked data-toggle="toggle" data-on="Pad" data-off="Don't Pad" data-width="110px"></td> + <td class="option-info"><strong>Enable data padding when panning and zooming?</strong><br/> + <small>When set to <b>Pad</b> the charts will be padded with more data, both before and after the visible area, thus giving the impression the whole database is loaded. This padding will happen only after the first pan or zoom operation on the chart (initially all charts have only the visible data). When set to <b>Don't Pad</b> only the visible data will be transfered from the netdata server, even after the first pan and zoom operation.</small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="smooth_plot" type="checkbox" checked data-toggle="toggle" data-on="Smooth" data-off="Rough" data-width="110px"></td> + <td class="option-info"><strong>Enable Bézier lines on charts?</strong><br/> + <small>When set to <b>Smooth</b> the charts libraries that support it, will plot smooth curves instead of simple straight lines to connect the points. + <br/> + Keep in mind <a href="http://dygraphs.com" target="_blank">dygraphs</a>, the main charting library in netdata dashboards, can only smooth line charts. It cannot smooth area or stacked charts. When set to <b>Rough</b>, this setting can lower the CPU resources consumed by your browser.</small> + </td> + </tr> + </table> + </div> + </form> + </div> + <div role="tabpanel" class="tab-pane" id="settings_locale"> + <form id="optionsForm4" method="get" class="form-horizontal"> + <div class="form-group"> + <table> + <tr class="option-row"> + <td colspan="2" align="center"> + <small> + <b>These settings are applied gradually, as charts are updated. To force them, refresh the dashboard now</b>. + </small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="units_conversion" type="checkbox" checked data-toggle="toggle" data-on="Scale Units" data-off="Fixed Units" data-onstyle="success" data-width="110px"></td> + <td class="option-info"><strong>Enable auto-scaling of select units?</strong><br/> + <small>When set to <b>Scale Units</b> the values shown will dynamically be scaled (e.g. 1000 kilobits will be shown as 1 megabit). + Netdata can auto-scale these original units: <code>kilobits/s</code>, <code>kilobytes/s</code>, <code>KB/s</code>, + <code>KB</code>, <code>MB</code>, and <code>GB</code>. + When set to <b>Fixed Units</b> all the values will be rendered using the original units maintained by the netdata server. + </small> + </td> + </tr> + <tr id="settingsLocaleTempRow" class="option-row"> + <td class="option-control"><input id="units_temp" type="checkbox" checked data-toggle="toggle" data-on="Celsius" data-off="Fahrenheit" data-width="110px"></td> + <td class="option-info"><strong>Which units to use for temperatures?</strong><br/> + <small>Set the temperature units of the dashboard. + </small> + </td> + </tr> + <tr id="settingsLocaleTimeRow" class="option-row"> + <td class="option-control"><input id="seconds_as_time" type="checkbox" checked data-toggle="toggle" data-on="Time" data-off="Seconds" data-onstyle="success" data-width="110px"></td> + <td class="option-info"><strong>Convert seconds to time?</strong><br/> + <small>When set to <b>Time</b>, charts that present <code>seconds</code> will show <code>DDd:HH:MM:SS</code>. + When set to <b>Seconds</b>, the raw number of seconds will be presented. + </small> + </td> + </tr> + <tr class="option-row"> + <td class="option-control"><input id="local_timezone" type="checkbox" checked data-toggle="toggle" data-on="Your Time" data-off="Server Time" data-onstyle="success" data-offstyle="danger" data-width="110px"></td> + <td class="option-info"><strong>Show browser local time or server time?</strong><br/> + <small>When set to <b>Your Time</b>, the charts will use your browser local time. When set to <b>Server Time</b> the charts will use the server time. + <br/> + Set it to <b>Your Time</b> to have a common time-reference, no matter where the server is and which time zone it uses (all your dashboards will report your local time). + Set it to <b>Server Time</b> when you need to compare netdata charts with server log files. + <br/> + Your browser time zone is: <b><span id="browser_timezone">-</span></b>.<br/> + The server reported timezone is: <b><span id="server_timezone">-</span></b> (you can set this in netdata.conf <code>[global].timezone</code>).<br/> + The current time zone on the dashboard is: <b><span id="current_timezone">-</span></b>. + <br/> + <div class="dropup"> + <button class="btn btn-default dropdown-toggle" type="button" id="dropdownTimeZone" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true"> + Select Server Time Zone + <span class="caret"></span> + </button> + <ul class="dropdown-menu scrollable-menu-50" aria-labelledby="dropdownTimeZone"> + <li><a href=# onclick="return selected_server_timezone('UTC');">Universal Time Coordinated (UTC)</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Abidjan');">Africa/Abidjan</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Accra');">Africa/Accra</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Algiers');">Africa/Algiers</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Bissau');">Africa/Bissau</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Cairo');">Africa/Cairo</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Casablanca');">Africa/Casablanca</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Ceuta');">Africa/Ceuta</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/El_Aaiun');">Africa/El_Aaiun</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Johannesburg');">Africa/Johannesburg</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Khartoum');">Africa/Khartoum</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Lagos');">Africa/Lagos</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Maputo');">Africa/Maputo</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Monrovia');">Africa/Monrovia</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Nairobi');">Africa/Nairobi</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Ndjamena');">Africa/Ndjamena</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Tripoli');">Africa/Tripoli</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Tunis');">Africa/Tunis</a></li> + <li><a href=# onclick="return selected_server_timezone('Africa/Windhoek');">Africa/Windhoek</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Adak');">America/Adak</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Anchorage');">America/Anchorage</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Araguaina');">America/Araguaina</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Buenos_Aires');">America/Argentina/Buenos_Aires</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Catamarca');">America/Argentina/Catamarca</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Cordoba');">America/Argentina/Cordoba</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Jujuy');">America/Argentina/Jujuy</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/La_Rioja');">America/Argentina/La_Rioja</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Mendoza');">America/Argentina/Mendoza</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Rio_Gallegos');">America/Argentina/Rio_Gallegos</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Salta');">America/Argentina/Salta</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/San_Juan');">America/Argentina/San_Juan</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/San_Luis');">America/Argentina/San_Luis</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Tucuman');">America/Argentina/Tucuman</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Argentina/Ushuaia');">America/Argentina/Ushuaia</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Asuncion');">America/Asuncion</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Atikokan');">America/Atikokan</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Bahia');">America/Bahia</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Bahia_Banderas');">America/Bahia_Banderas</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Barbados');">America/Barbados</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Belem');">America/Belem</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Belize');">America/Belize</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Blanc-Sablon');">America/Blanc-Sablon</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Boa_Vista');">America/Boa_Vista</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Bogota');">America/Bogota</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Boise');">America/Boise</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Cambridge_Bay');">America/Cambridge_Bay</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Campo_Grande');">America/Campo_Grande</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Cancun');">America/Cancun</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Caracas');">America/Caracas</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Cayenne');">America/Cayenne</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Chicago');">America/Chicago</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Chihuahua');">America/Chihuahua</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Costa_Rica');">America/Costa_Rica</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Creston');">America/Creston</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Cuiaba');">America/Cuiaba</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Curacao');">America/Curacao</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Danmarkshavn');">America/Danmarkshavn</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Dawson');">America/Dawson</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Dawson_Creek');">America/Dawson_Creek</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Denver');">America/Denver</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Detroit');">America/Detroit</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Edmonton');">America/Edmonton</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Eirunepe');">America/Eirunepe</a></li> + <li><a href=# onclick="return selected_server_timezone('America/El_Salvador');">America/El_Salvador</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Fortaleza');">America/Fortaleza</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Fort_Nelson');">America/Fort_Nelson</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Glace_Bay');">America/Glace_Bay</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Godthab');">America/Godthab</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Goose_Bay');">America/Goose_Bay</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Grand_Turk');">America/Grand_Turk</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Guatemala');">America/Guatemala</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Guayaquil');">America/Guayaquil</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Guyana');">America/Guyana</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Halifax');">America/Halifax</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Havana');">America/Havana</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Hermosillo');">America/Hermosillo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Indianapolis');">America/Indiana/Indianapolis</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Knox');">America/Indiana/Knox</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Marengo');">America/Indiana/Marengo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Petersburg');">America/Indiana/Petersburg</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Tell_City');">America/Indiana/Tell_City</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Vevay');">America/Indiana/Vevay</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Vincennes');">America/Indiana/Vincennes</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Indiana/Winamac');">America/Indiana/Winamac</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Inuvik');">America/Inuvik</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Iqaluit');">America/Iqaluit</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Jamaica');">America/Jamaica</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Juneau');">America/Juneau</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Kentucky/Louisville');">America/Kentucky/Louisville</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Kentucky/Monticello');">America/Kentucky/Monticello</a></li> + <li><a href=# onclick="return selected_server_timezone('America/La_Paz');">America/La_Paz</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Lima');">America/Lima</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Los_Angeles');">America/Los_Angeles</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Maceio');">America/Maceio</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Managua');">America/Managua</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Manaus');">America/Manaus</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Martinique');">America/Martinique</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Matamoros');">America/Matamoros</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Mazatlan');">America/Mazatlan</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Menominee');">America/Menominee</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Merida');">America/Merida</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Metlakatla');">America/Metlakatla</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Mexico_City');">America/Mexico_City</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Miquelon');">America/Miquelon</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Moncton');">America/Moncton</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Monterrey');">America/Monterrey</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Montevideo');">America/Montevideo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Nassau');">America/Nassau</a></li> + <li><a href=# onclick="return selected_server_timezone('America/New_York');">America/New_York</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Nipigon');">America/Nipigon</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Nome');">America/Nome</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Noronha');">America/Noronha</a></li> + <li><a href=# onclick="return selected_server_timezone('America/North_Dakota/Beulah');">America/North_Dakota/Beulah</a></li> + <li><a href=# onclick="return selected_server_timezone('America/North_Dakota/Center');">America/North_Dakota/Center</a></li> + <li><a href=# onclick="return selected_server_timezone('America/North_Dakota/New_Salem');">America/North_Dakota/New_Salem</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Ojinaga');">America/Ojinaga</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Panama');">America/Panama</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Pangnirtung');">America/Pangnirtung</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Paramaribo');">America/Paramaribo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Phoenix');">America/Phoenix</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Port-au-Prince');">America/Port-au-Prince</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Port_of_Spain');">America/Port_of_Spain</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Porto_Velho');">America/Porto_Velho</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Puerto_Rico');">America/Puerto_Rico</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Punta_Arenas');">America/Punta_Arenas</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Rainy_River');">America/Rainy_River</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Rankin_Inlet');">America/Rankin_Inlet</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Recife');">America/Recife</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Regina');">America/Regina</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Resolute');">America/Resolute</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Rio_Branco');">America/Rio_Branco</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Santarem');">America/Santarem</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Santiago');">America/Santiago</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Santo_Domingo');">America/Santo_Domingo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Sao_Paulo');">America/Sao_Paulo</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Scoresbysund');">America/Scoresbysund</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Sitka');">America/Sitka</a></li> + <li><a href=# onclick="return selected_server_timezone('America/St_Johns');">America/St_Johns</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Swift_Current');">America/Swift_Current</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Tegucigalpa');">America/Tegucigalpa</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Thule');">America/Thule</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Thunder_Bay');">America/Thunder_Bay</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Tijuana');">America/Tijuana</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Toronto');">America/Toronto</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Vancouver');">America/Vancouver</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Whitehorse');">America/Whitehorse</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Winnipeg');">America/Winnipeg</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Yakutat');">America/Yakutat</a></li> + <li><a href=# onclick="return selected_server_timezone('America/Yellowknife');">America/Yellowknife</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Casey');">Antarctica/Casey</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Davis');">Antarctica/Davis</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/DumontDUrville');">Antarctica/DumontDUrville</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Macquarie');">Antarctica/Macquarie</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Mawson');">Antarctica/Mawson</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Palmer');">Antarctica/Palmer</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Rothera');">Antarctica/Rothera</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Syowa');">Antarctica/Syowa</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Troll');">Antarctica/Troll</a></li> + <li><a href=# onclick="return selected_server_timezone('Antarctica/Vostok');">Antarctica/Vostok</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Almaty');">Asia/Almaty</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Amman');">Asia/Amman</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Anadyr');">Asia/Anadyr</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Aqtau');">Asia/Aqtau</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Aqtobe');">Asia/Aqtobe</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Ashgabat');">Asia/Ashgabat</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Atyrau');">Asia/Atyrau</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Baghdad');">Asia/Baghdad</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Baku');">Asia/Baku</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Bangkok');">Asia/Bangkok</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Barnaul');">Asia/Barnaul</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Beirut');">Asia/Beirut</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Bishkek');">Asia/Bishkek</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Brunei');">Asia/Brunei</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Chita');">Asia/Chita</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Choibalsan');">Asia/Choibalsan</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Colombo');">Asia/Colombo</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Damascus');">Asia/Damascus</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Dhaka');">Asia/Dhaka</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Dili');">Asia/Dili</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Dubai');">Asia/Dubai</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Dushanbe');">Asia/Dushanbe</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Famagusta');">Asia/Famagusta</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Gaza');">Asia/Gaza</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Hebron');">Asia/Hebron</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Ho_Chi_Minh');">Asia/Ho_Chi_Minh</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Hong_Kong');">Asia/Hong_Kong</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Hovd');">Asia/Hovd</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Irkutsk');">Asia/Irkutsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Jakarta');">Asia/Jakarta</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Jayapura');">Asia/Jayapura</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Jerusalem');">Asia/Jerusalem</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kabul');">Asia/Kabul</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kamchatka');">Asia/Kamchatka</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Karachi');">Asia/Karachi</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kathmandu');">Asia/Kathmandu</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Khandyga');">Asia/Khandyga</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kolkata');">Asia/Kolkata</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Krasnoyarsk');">Asia/Krasnoyarsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kuala_Lumpur');">Asia/Kuala_Lumpur</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Kuching');">Asia/Kuching</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Macau');">Asia/Macau</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Magadan');">Asia/Magadan</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Makassar');">Asia/Makassar</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Manila');">Asia/Manila</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Nicosia');">Asia/Nicosia</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Novokuznetsk');">Asia/Novokuznetsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Novosibirsk');">Asia/Novosibirsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Omsk');">Asia/Omsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Oral');">Asia/Oral</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Pontianak');">Asia/Pontianak</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Pyongyang');">Asia/Pyongyang</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Qatar');">Asia/Qatar</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Qyzylorda');">Asia/Qyzylorda</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Riyadh');">Asia/Riyadh</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Sakhalin');">Asia/Sakhalin</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Samarkand');">Asia/Samarkand</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Seoul');">Asia/Seoul</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Shanghai');">Asia/Shanghai</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Singapore');">Asia/Singapore</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Srednekolymsk');">Asia/Srednekolymsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Taipei');">Asia/Taipei</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Tashkent');">Asia/Tashkent</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Tbilisi');">Asia/Tbilisi</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Tehran');">Asia/Tehran</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Thimphu');">Asia/Thimphu</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Tokyo');">Asia/Tokyo</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Tomsk');">Asia/Tomsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Ulaanbaatar');">Asia/Ulaanbaatar</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Urumqi');">Asia/Urumqi</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Ust-Nera');">Asia/Ust-Nera</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Vladivostok');">Asia/Vladivostok</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Yakutsk');">Asia/Yakutsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Yangon');">Asia/Yangon</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Yekaterinburg');">Asia/Yekaterinburg</a></li> + <li><a href=# onclick="return selected_server_timezone('Asia/Yerevan');">Asia/Yerevan</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Azores');">Atlantic/Azores</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Bermuda');">Atlantic/Bermuda</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Canary');">Atlantic/Canary</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Cape_Verde');">Atlantic/Cape_Verde</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Faroe');">Atlantic/Faroe</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Madeira');">Atlantic/Madeira</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Reykjavik');">Atlantic/Reykjavik</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/South_Georgia');">Atlantic/South_Georgia</a></li> + <li><a href=# onclick="return selected_server_timezone('Atlantic/Stanley');">Atlantic/Stanley</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Adelaide');">Australia/Adelaide</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Brisbane');">Australia/Brisbane</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Broken_Hill');">Australia/Broken_Hill</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Currie');">Australia/Currie</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Darwin');">Australia/Darwin</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Eucla');">Australia/Eucla</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Hobart');">Australia/Hobart</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Lindeman');">Australia/Lindeman</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Lord_Howe');">Australia/Lord_Howe</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Melbourne');">Australia/Melbourne</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Perth');">Australia/Perth</a></li> + <li><a href=# onclick="return selected_server_timezone('Australia/Sydney');">Australia/Sydney</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Amsterdam');">Europe/Amsterdam</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Andorra');">Europe/Andorra</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Astrakhan');">Europe/Astrakhan</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Athens');">Europe/Athens</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Belgrade');">Europe/Belgrade</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Berlin');">Europe/Berlin</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Brussels');">Europe/Brussels</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Bucharest');">Europe/Bucharest</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Budapest');">Europe/Budapest</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Chisinau');">Europe/Chisinau</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Copenhagen');">Europe/Copenhagen</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Dublin');">Europe/Dublin</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Gibraltar');">Europe/Gibraltar</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Helsinki');">Europe/Helsinki</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Istanbul');">Europe/Istanbul</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Kaliningrad');">Europe/Kaliningrad</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Kiev');">Europe/Kiev</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Kirov');">Europe/Kirov</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Lisbon');">Europe/Lisbon</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/London');">Europe/London</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Luxembourg');">Europe/Luxembourg</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Madrid');">Europe/Madrid</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Malta');">Europe/Malta</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Minsk');">Europe/Minsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Monaco');">Europe/Monaco</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Moscow');">Europe/Moscow</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Oslo');">Europe/Oslo</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Paris');">Europe/Paris</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Prague');">Europe/Prague</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Riga');">Europe/Riga</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Rome');">Europe/Rome</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Samara');">Europe/Samara</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Saratov');">Europe/Saratov</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Simferopol');">Europe/Simferopol</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Sofia');">Europe/Sofia</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Stockholm');">Europe/Stockholm</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Tallinn');">Europe/Tallinn</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Tirane');">Europe/Tirane</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Ulyanovsk');">Europe/Ulyanovsk</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Uzhgorod');">Europe/Uzhgorod</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Vienna');">Europe/Vienna</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Vilnius');">Europe/Vilnius</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Volgograd');">Europe/Volgograd</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Warsaw');">Europe/Warsaw</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Zaporozhye');">Europe/Zaporozhye</a></li> + <li><a href=# onclick="return selected_server_timezone('Europe/Zurich');">Europe/Zurich</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Chagos');">Indian/Chagos</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Christmas');">Indian/Christmas</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Cocos');">Indian/Cocos</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Kerguelen');">Indian/Kerguelen</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Mahe');">Indian/Mahe</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Maldives');">Indian/Maldives</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Mauritius');">Indian/Mauritius</a></li> + <li><a href=# onclick="return selected_server_timezone('Indian/Reunion');">Indian/Reunion</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Apia');">Pacific/Apia</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Auckland');">Pacific/Auckland</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Bougainville');">Pacific/Bougainville</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Chatham');">Pacific/Chatham</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Chuuk');">Pacific/Chuuk</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Easter');">Pacific/Easter</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Efate');">Pacific/Efate</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Enderbury');">Pacific/Enderbury</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Fakaofo');">Pacific/Fakaofo</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Fiji');">Pacific/Fiji</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Funafuti');">Pacific/Funafuti</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Galapagos');">Pacific/Galapagos</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Gambier');">Pacific/Gambier</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Guadalcanal');">Pacific/Guadalcanal</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Guam');">Pacific/Guam</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Honolulu');">Pacific/Honolulu</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Kiritimati');">Pacific/Kiritimati</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Kosrae');">Pacific/Kosrae</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Kwajalein');">Pacific/Kwajalein</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Majuro');">Pacific/Majuro</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Marquesas');">Pacific/Marquesas</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Nauru');">Pacific/Nauru</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Niue');">Pacific/Niue</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Norfolk');">Pacific/Norfolk</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Noumea');">Pacific/Noumea</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Pago_Pago');">Pacific/Pago_Pago</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Palau');">Pacific/Palau</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Pitcairn');">Pacific/Pitcairn</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Pohnpei');">Pacific/Pohnpei</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Port_Moresby');">Pacific/Port_Moresby</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Rarotonga');">Pacific/Rarotonga</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Tahiti');">Pacific/Tahiti</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Tarawa');">Pacific/Tarawa</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Tongatapu');">Pacific/Tongatapu</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Wake');">Pacific/Wake</a></li> + <li><a href=# onclick="return selected_server_timezone('Pacific/Wallis');">Pacific/Wallis</a></li> + </ul> + </div> + <b><span id="timezone_error_message"></span></b> + + </small> + </td> + </tr> + </table> + </div> + </form> + </div> + </div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + + <div class="modal fade" id="updateModal" tabindex="-1" role="dialog" aria-labelledby="updateModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="updateModalLabel">Update Check</h4> + </div> + <div class="modal-body"> + Your netdata version: <b><code><span id="netdataVersion">Unknown</span></code></b><br/> + <br/> + <div style="padding: 10px;"></div> + <div id="versionCheckLog">Not checked yet. Please press the Check Now button.</div> + <div> + <hr/> + </div> + <div> + For progress reports and key netdata updates: <strong><a href="https://twitter.com/linuxnetdata" target="_blank">follow netdata on <i class="fab fa-twitter"></i> twitter</a></strong>. + <br/> + You can also <a href="https://www.facebook.com/linuxnetdata/" target="_blank">follow netdata on <i class="fab fa-facebook"></i> facebook</a>, + or <a href="https://github.com/netdata/netdata" target="_blank">watch netdata on <i class="fab fa-github"></i> github</a>. + </div> + </div> + <div class="modal-footer"> + <a href="#" onclick="notifyForUpdate(true); return false;" type="button" class="btn btn-default">Check Now</a> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="signInModal" tabindex="-1" role="dialog" aria-labelledby="signInModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="signInModalLabel">Sign In</h4> + </div> + <div class="modal-body"> + <p> + Signing-in to netdata.cloud will synchronize the list of + your netdata monitored nodes known at registry + <strong><span id="sim-registry"></span></strong>. This + may include server hostnames, urls and identification + GUIDs. + </p> + <p> + After you upgrade all your netdata servers, your private + registry will not be needed any more. + </p> + <p> + Are you sure you want to proceed? + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <a href="#" onclick="explicitlySignIn(); return false;" type="button" class="btn btn-success">Sign In</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="syncRegistryModal" tabindex="-1" role="dialog" aria-labelledby="syncRegistryModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="syncRegistryModalLabel">Synchronize netdata.cloud with registry?</h4> + </div> + <div class="modal-body"> + <p> + You are about to synchronize your netdata.cloud account with data from the registry at <strong><span id="sync-registry-modal-registry"></span></strong>. + This may include server hostnames, urls and identification GUIDs. + </p> + <p> + Are you sure you want to proceed? + </p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> + <a href="#" onclick="explicitlySyncAgents(); return false;" type="button" class="btn btn-success">Synchronize</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="deleteRegistryModal" tabindex="-1" role="dialog" aria-labelledby="deleteRegistryModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="deleteRegistryModalLabel">Delete <span id="deleteRegistryServerName"></span>?</h4> + </div> + <div class="modal-body"> + You are about to delete, from your personal list of netdata servers, the following server: + <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;"> + <b><span id="deleteRegistryServerName2"></span></b> + <br/> + <b><span id="deleteRegistryServerURL"></span></b> + </p> + Are you sure you want to do this? + <br/> + <div style="padding: 10px;"></div> + <small>Keep in mind, this server will be added back if and when you visit it again.</small> + <br/> + <div id="deleteRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-success" data-dismiss="modal">keep it</button> + <a href="#" onclick="notifyForDeleteRegistry(); return false;" type="button" class="btn btn-danger">delete it</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="switchRegistryModal" tabindex="-1" role="dialog" aria-labelledby="switchRegistryModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="switchRegistryModalLabel">Switch Netdata Registry Identity</h4> + </div> + <div class="modal-body"> + You can copy and paste the following ID to all your browsers (e.g. work and home). + <br/> + All the browsers with the same ID will identify <b>you</b>, so please don't share this with others. + <div style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;"> + <form action="#"> + <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;"> + </form> + </div> + Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser. + <div style="padding-top: 10px;"><small> + Keep in mind that: + <ul> + <li>when you switch ID, your previous ID will be lost forever - this is irreversible.</li> + <li>both IDs (your old and the new) must list this netdata at their personal lists.</li> + <li>both IDs have to be known by the registry: <b><span id="switchRegistryURL"></span></b>.</li> + <li>to get a new ID, just clear your browser cookies.</li> + </ul> + </small></div> + <div id="switchRegistryResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-success" data-dismiss="modal">cancel</button> + <a href="#" onclick="notifyForSwitchRegistry(); return false;" type="button" class="btn btn-danger">impersonate</a> + </div> + </div> + </div> + </div> + + <div class="modal fade" id="gotoServerModal" tabindex="-1" role="dialog" aria-labelledby="gotoServerModalLabel"> + <div class="modal-dialog" role="document"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> + <h4 class="modal-title" id="gotoServerModalLabel"><span id="gotoServerName"></span></h4> + </div> + <div class="modal-body"> + Checking known URLs for this server... + <div style="padding-top: 20px;"> + <table id="gotoServerList"> + </table> + </div> + <p style="padding-top: 10px;"><small> + Checks may fail if you are viewing an HTTPS page and the server to be checked is HTTP only. + </small></p> + <div id="gotoServerResponse" style="display: block; width: 100%; text-align: center; padding-top: 20px;"></div> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> + </div> + </div> + </div> + </div> + <iframe id="ssoifrm" width="0" height="0"></iframe> + <div id="hiddenDownloadLinks" style="display: none;" hidden></div> + <script type="text/javascript" src="dashboard.js?v20190130-1"></script> +</body> +</html> diff --git a/web/gui/infographic.html b/web/gui/infographic.html new file mode 100644 index 0000000..b311278 --- /dev/null +++ b/web/gui/infographic.html @@ -0,0 +1,171 @@ +<!doctype html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang=en-us> +<head> + <meta charset=utf-8> + <title>NetData: Get control of your Linux Servers. Simple. Effective. Awesome.</title> + <meta name=author content="Costa Tsaousis"> + <meta name=description content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms."> + + <meta name=viewport content="width=device-width,initial-scale=1"> + <link rel=apple-touch-icon href=apple-touch-icon.png> + <link rel="icon" type="image/png" sizes="32x32" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACNklEQVRYhcXXv2tUQRAH8M+FEIJISBHCIWIhIQSUILERi4AiiqCggiIiomAjlhaC4j+ghYWISgqNohZaCBZBC8Ei8QdEUCutFBsxCBqDYkgci/cunkfuJffjJQPD8mZm5/vd2WV2HzlJ0Bs8CvrywsgCHwy+BpGOg0sJfjj4nYKX9FdwKG9gwZlgtgK8pLOpPxfw1mCoCnClDgWtzQTvCEYWCV7SkWAlFBoEb8dlDKBF8t2bMWUSH/AHr3CiEfz5CPUusPJLkRCdk5ZqyeqUrQv4R7E5TwK7M3zTeIKduRAIitiWEfIY69GdCwGcRFuG/xqONRkzkaA7+J5x+MaDtWmHvJ4HgeEM8Nn0bridfv9HoOFyBAdwJCPkqqTzHWwUaz7wgeBHxupfBKuCj2W25mxBsCGYyAB/FxTT27HcPlyep64tCLbjKbqqhLzBlgKfF8pVE4FgRXABI+ioEnYfOyzcFWsCbg+OV+xlpU4ER4O+4HVwL51b3xYEXcGu4Ao+YQhr5gmdxHmsQyfG0b/YxbWmLfRWmnxa0s06VbTMCpnBS9zFzQKTwR5cXCzwHIE02Sl8wSZsRI/kgLVJqjSd+t9LVjiG1diPszhdK3A5gR48k5zYMTwscC59sfT799CYKvA8EttbSeXgTr3gJQKl91kR+yTlvyG5uUbLYh9gb+ovltkb6qYtNSRo3kOygsBSzGlKsubf43USWLYK5CLLXoFWyU/CtzLbVDpW2n+m40yN9ukqdvAX9ac/EIgOapcAAAAASUVORK5CYII="> + + <meta property="og:url" content="https://my-netdata.io/infographic.html" /> + <meta property="og:type" content="website" /> + <meta property="og:title" content="netdata infographic" /> + <meta property="og:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/25580009/bf7016a4-2e85-11e7-9a7a-b36c57db7b91.png" /> + <meta property="og:image:type" content="image/png" /> + <meta property="fb:app_id" content="1200089276712916" /> + + <meta name="twitter:card" content="summary" /> + <meta name="twitter:site" content="@linuxnetdata" /> + <meta name="twitter:title" content="netdata infographic" /> + <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." /> + <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/25580009/bf7016a4-2e85-11e7-9a7a-b36c57db7b91.png" /> + + <meta name="google-site-verification" content="3Xmk2kyCvai8p9HEnYHoQ9RBW20-b1NvPAgu07Fkkds" /> + <meta name="msvalidate.01" content="896DCA31C9A664CE359FCF1A645DD476" /> + + <style>/*! normalize.css v4.1.1 | MIT License | github.com/necolas/normalize.css */ + html { + line-height: 1.15; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + font: 17px/1.4 'Open Sans', sans-serif; + text-align: center + } + </style> +</head> +<body> +<div style="width: 100%;text-align:center;"> + <div> + <p style="font-size: 16pt"> + <b>Interactive infographic of netdata features and functions</b> + </p> + <p> + Hover and click on the infographic, to open the related wiki page. + <br/> + <small> + The links and the docs are still a work in progress. + The interactive infographic is a feature of <b>draw.io</b>. + </small> + </p> + </div> + <div class=site-footer role=contentinfo> + <p> + <div style="display: inline-block;"> + <div style="vertical-align:top;display:inline-block; height: 34px;margin-top:3px;"><a class=twitter-share-button href=https://twitter.com/share data-count=none data-lang=en data-via=linuxnetdata data-size=small data-text="Get control of your Linux servers. Simple. Effective. Awesome." data-url=https://my-netdata.io/infographic.html >Tweet</a></div> + <div style="vertical-align:top;display:inline-block; height: 34px;margin-top:3px;"><a class=twitter-follow-button href=https://twitter.com/linuxnetdata data-show-count=false data-lang=en data-size=small>Follow @linuxnetdata</a></div> + </div> + <div style="display: inline-block;"> + <div class="fb-like" data-href="https://my-netdata.io/" data-layout="button" data-action="like" data-show-faces="false" data-share="false" style="vertical-align:top;display:inline-block; height: 34px;"></div> + <div class="fb-share-button" data-href="https://my-netdata.io/" data-layout="button" data-size="small" data-mobile-iframe="true"><a class="fb-xfbml-parse-ignore" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmy-netdata.io%2Finfographic.html&src=sdkpreparse" style="vertical-align:top;display:inline-block; height: 34px;">Share</a></div> + </div> + </div> + <div> + <p style="font-size: 14pt"> + <b>New to netdata?</b> <a href="//my-netdata.io" target="_blank">Have a look at a netdata demo</a>. You will love it! + </p> + <p> + <embed style="padding-top: 10px; padding-botton: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=persons&label=user%20base&units=null&value_color=blue&precision=0&v42" type="image/svg+xml" height="20" /> + <embed style="padding-top: 10px; padding-botton: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_entries&dimensions=machines&label=servers%20monitored&units=null&value_color=orange&precision=0&v42" type="image/svg+xml" height="20" /> + <embed style="padding-top: 10px; padding-botton: 25px;" src="//registry.my-netdata.io/api/v1/badge.svg?chart=netdata.registry_sessions&label=sessions%20served&units=null&value_color=yellowgreen&precision=0&v42" type="image/svg+xml" height="20" /> + </p> + <hr/> + </div> + <div style="width:90%;display:inline-block;max-width:1300px;text-align:left;"> + <div id="drawing" class="mxgraph" style="max-width:100%;border:1px solid transparent;"></div> + </div> +</div> +</body> + +<script> + var opts = { + "highlight":"#0000ff", + "target":"blank", + "lightbox":false, + "nav":false, + "resize":true, + "toolbar":"", + "auto-fit":true, + "check-visible-state":false, + "edit":"https://raw.githubusercontent.com/ktsaou/netdata/master/diagrams/netdata-overview.xml", + "url":"https://raw.githubusercontent.com/ktsaou/netdata/master/diagrams/netdata-overview.xml" + }; + document.getElementById("drawing").dataset.mxgraph = JSON.stringify(opts); +</script> + +<script> + if(window.location.hostname != 'my-netdata.io' || window.location.protocol != 'https:') { + var canonical = document.createElement('link'); + canonical.rel = 'canonical'; + canonical.href = 'https://my-netdata.io/infographic.html'; + document.head.appendChild(canonical); + } +</script> + +<script>!function (t, e) { + "use strict"; + function a(t, n) { + return t.hasAttribute(n) === !0 ? t : t.parentNode !== r.body ? a(t.parentNode, n) : e + } + + function n(n) { + var o, i, r, c, g, u = a(n.target, "data-ga-action"), l = !1; + u !== e && (o = u.getAttribute("data-ga-action") || e, i = u.getAttribute("data-ga-category") || e, r = u.getAttribute("data-ga-label") || e, c = u.getAttribute("href"), g = parseInt(u.getAttribute("data-ga-value"), 10) || e, ga !== e && i !== e && o !== e && (n.preventDefault(), "Download" !== i && n.ctrlKey !== !0 && n.metaKey !== !0 && 2 !== n.which || (l = !0, t.open(c)), function (a) { + var n; + ga("send", "event", i, o, r, g, { + hitCallback: function () { + l === !1 && (n !== e && clearTimeout(n), t.location = a) + } + }), n = setTimeout(function () { + l === !1 && (t.location.href = a) + }, 1e3) + }(c))) + } + + function o() { + !function (t, e, a, n, o, i) { + t.GoogleAnalyticsObject = n, t[n] || (t[n] = function () { + (t[n].q = t[n].q || []).push(arguments) + }), t[n].l = +new Date, o = e.createElement(a), i = e.getElementsByTagName(a)[0], o.src = "//www.google-analytics.com/analytics.js", i.parentNode.insertBefore(o, i) + }(t, r, "script", "ga"), ga("create", "UA-64295674-3", "auto"), ga("send", "pageview"), t.document.addEventListener("click", n) + } + + function i() { + !function (t, e, a) { + var n, o = t.getElementsByTagName(e)[0]; + t.getElementById(a) || (n = t.createElement(e), n.id = a, n.src = "//platform.twitter.com/widgets.js", o.parentNode.insertBefore(n, o)) + }(r, "script", "twitter-wjs") + } + + var r = t.document; + o(), t.onload = i +}(window)</script> + +<!-- facebook sdk --> +<div id="fb-root"></div> +<script> + window.fbAsyncInit = function() { + FB.init({ + appId : '1200089276712916', + xfbml : true, + version : 'v2.8' + }); + }; + + (function(d, s, id){ + var js, fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) {return;} + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/en_US/sdk.js"; + fjs.parentNode.insertBefore(js, fjs); + }(document, 'script', 'facebook-jssdk')); +</script> + +<script type="text/javascript" src="https://www.draw.io/embed2.js?s=arrows2;mscae/cloud;azure;office/users;office/servers&fetch=https%3A%2F%2Fraw.githubusercontent.com%2Fnetdata%2Fnetdata%2Fmaster%2Fdiagrams%2Fnetdata-overview.xml"></script> + +</html> + diff --git a/web/gui/lib/bootstrap-3.3.7.min.js b/web/gui/lib/bootstrap-3.3.7.min.js new file mode 100644 index 0000000..03a9716 --- /dev/null +++ b/web/gui/lib/bootstrap-3.3.7.min.js @@ -0,0 +1,8 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under the MIT license + * SPDX-License-Identifier: MIT + */ +if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()}},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.getItemForDirection=function(a,b){var c=this.getItemIndex(b),d="prev"==a&&0===c||"next"==a&&c==this.$items.length-1;if(d&&!this.options.wrap)return b;var e="prev"==a?-1:1,f=(c+e)%this.$items.length;return this.$items.eq(f)},c.prototype.to=function(a){var b=this,c=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(a>this.$items.length-1||a<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){b.to(a)}):c==a?this.pause().cycle():this.slide(a>c?"next":"prev",this.$items.eq(a))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){if(!this.sliding)return this.slide("next")},c.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},c.prototype.slide=function(b,d){var e=this.$element.find(".item.active"),f=d||this.getItemForDirection(b,e),g=this.interval,h="next"==b?"left":"right",i=this;if(f.hasClass("active"))return this.sliding=!1;var j=f[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:h});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,g&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(f)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:h});return a.support.transition&&this.$element.hasClass("slide")?(f.addClass(b),f[0].offsetWidth,e.addClass(h),f.addClass(h),e.one("bsTransitionEnd",function(){f.removeClass([b,h].join(" ")).addClass("active"),e.removeClass(["active",h].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(c.TRANSITION_DURATION)):(e.removeClass("active"),f.addClass("active"),this.sliding=!1,this.$element.trigger(m)),g&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this};var e=function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}};a(document).on("click.bs.carousel.data-api","[data-slide]",e).on("click.bs.carousel.data-api","[data-slide-to]",e),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){var c,d=b.attr("data-target")||(c=b.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"");return a(d)}function c(b){return this.each(function(){var c=a(this),e=c.data("bs.collapse"),f=a.extend({},d.DEFAULTS,c.data(),"object"==typeof b&&b);!e&&f.toggle&&/show|hide/.test(b)&&(f.toggle=!1),e||c.data("bs.collapse",e=new d(this,f)),"string"==typeof b&&e[b]()})}var d=function(b,c){this.$element=a(b),this.options=a.extend({},d.DEFAULTS,c),this.$trigger=a('[data-toggle="collapse"][href="#'+b.id+'"],[data-toggle="collapse"][data-target="#'+b.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};d.VERSION="3.3.7",d.TRANSITION_DURATION=350,d.DEFAULTS={toggle:!0},d.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},d.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b,e=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(e&&e.length&&(b=e.data("bs.collapse"),b&&b.transitioning))){var f=a.Event("show.bs.collapse");if(this.$element.trigger(f),!f.isDefaultPrevented()){e&&e.length&&(c.call(e,"hide"),b||e.data("bs.collapse",null));var g=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[g](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var h=function(){this.$element.removeClass("collapsing").addClass("collapse in")[g](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return h.call(this);var i=a.camelCase(["scroll",g].join("-"));this.$element.one("bsTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(d.TRANSITION_DURATION)[g](this.$element[0][i])}}}},d.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse in").attr("aria-expanded",!1),this.$trigger.addClass("collapsed").attr("aria-expanded",!1),this.transitioning=1;var e=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(e,this)).emulateTransitionEnd(d.TRANSITION_DURATION):e.call(this)}}},d.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},d.prototype.getParent=function(){return a(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(a.proxy(function(c,d){var e=a(d);this.addAriaAndCollapsedClass(b(e),e)},this)).end()},d.prototype.addAriaAndCollapsedClass=function(a,b){var c=a.hasClass("in");a.attr("aria-expanded",c),b.toggleClass("collapsed",!c).attr("aria-expanded",c)};var e=a.fn.collapse;a.fn.collapse=c,a.fn.collapse.Constructor=d,a.fn.collapse.noConflict=function(){return a.fn.collapse=e,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(d){var e=a(this);e.attr("data-target")||d.preventDefault();var f=b(e),g=f.data("bs.collapse"),h=g?"toggle":e.data();c.call(f,h)})}(jQuery),+function(a){"use strict";function b(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function c(c){c&&3===c.which||(a(e).remove(),a(f).each(function(){var d=a(this),e=b(d),f={relatedTarget:this};e.hasClass("open")&&(c&&"click"==c.type&&/input|textarea/i.test(c.target.tagName)&&a.contains(e[0],c.target)||(e.trigger(c=a.Event("hide.bs.dropdown",f)),c.isDefaultPrevented()||(d.attr("aria-expanded","false"),e.removeClass("open").trigger(a.Event("hidden.bs.dropdown",f)))))}))}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.3.7",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=b(e),g=f.hasClass("open");if(c(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",c);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus").attr("aria-expanded","true"),f.toggleClass("open").trigger(a.Event("shown.bs.dropdown",h))}return!1}},g.prototype.keydown=function(c){if(/(38|40|27|32)/.test(c.which)&&!/input|textarea/i.test(c.target.tagName)){var d=a(this);if(c.preventDefault(),c.stopPropagation(),!d.is(".disabled, :disabled")){var e=b(d),g=e.hasClass("open");if(!g&&27!=c.which||g&&27==c.which)return 27==c.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find(".dropdown-menu"+h);if(i.length){var j=i.index(c.target);38==c.which&&j>0&&j--,40==c.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=d,a.fn.dropdown.Constructor=g,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",c).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",f,g.prototype.toggle).on("keydown.bs.dropdown.data-api",f,g.prototype.keydown).on("keydown.bs.dropdown.data-api",".dropdown-menu",g.prototype.keydown)}(jQuery),+function(a){"use strict";function b(b,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},c.DEFAULTS,e.data(),"object"==typeof b&&b);f||e.data("bs.modal",f=new c(this,g)),"string"==typeof b?f[b](d):g.show&&f.show(d)})}var c=function(b,c){this.options=c,this.$body=a(document.body),this.$element=a(b),this.$dialog=this.$element.find(".modal-dialog"),this.$backdrop=null,this.isShown=null,this.originalBodyPad=null,this.scrollbarWidth=0,this.ignoreBackdropClick=!1,this.options.remote&&this.$element.find(".modal-content").load(this.options.remote,a.proxy(function(){this.$element.trigger("loaded.bs.modal")},this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=300,c.BACKDROP_TRANSITION_DURATION=150,c.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},c.prototype.toggle=function(a){return this.isShown?this.hide():this.show(a)},c.prototype.show=function(b){var d=this,e=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.checkScrollbar(),this.setScrollbar(),this.$body.addClass("modal-open"),this.escape(),this.resize(),this.$element.on("click.dismiss.bs.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.$dialog.on("mousedown.dismiss.bs.modal",function(){d.$element.one("mouseup.dismiss.bs.modal",function(b){a(b.target).is(d.$element)&&(d.ignoreBackdropClick=!0)})}),this.backdrop(function(){var e=a.support.transition&&d.$element.hasClass("fade");d.$element.parent().length||d.$element.appendTo(d.$body),d.$element.show().scrollTop(0),d.adjustDialog(),e&&d.$element[0].offsetWidth,d.$element.addClass("in"),d.enforceFocus();var f=a.Event("shown.bs.modal",{relatedTarget:b});e?d.$dialog.one("bsTransitionEnd",function(){d.$element.trigger("focus").trigger(f)}).emulateTransitionEnd(c.TRANSITION_DURATION):d.$element.trigger("focus").trigger(f)}))},c.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),this.resize(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal"),this.$dialog.off("mousedown.dismiss.bs.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",a.proxy(this.hideModal,this)).emulateTransitionEnd(c.TRANSITION_DURATION):this.hideModal())},c.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){document===a.target||this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.trigger("focus")},this))},c.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keydown.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keydown.dismiss.bs.modal")},c.prototype.resize=function(){this.isShown?a(window).on("resize.bs.modal",a.proxy(this.handleUpdate,this)):a(window).off("resize.bs.modal")},c.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.$body.removeClass("modal-open"),a.resetAdjustments(),a.resetScrollbar(),a.$element.trigger("hidden.bs.modal")})},c.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},c.prototype.backdrop=function(b){var d=this,e=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var f=a.support.transition&&e;if(this.$backdrop=a(document.createElement("div")).addClass("modal-backdrop "+e).appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){return this.ignoreBackdropClick?void(this.ignoreBackdropClick=!1):void(a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus():this.hide()))},this)),f&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;f?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var g=function(){d.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",g).emulateTransitionEnd(c.BACKDROP_TRANSITION_DURATION):g()}else b&&b()},c.prototype.handleUpdate=function(){this.adjustDialog()},c.prototype.adjustDialog=function(){var a=this.$element[0].scrollHeight>document.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&a?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!a?this.scrollbarWidth:""})},c.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},c.prototype.checkScrollbar=function(){var a=window.innerWidth;if(!a){var b=document.documentElement.getBoundingClientRect();a=b.right-Math.abs(b.left)}this.bodyIsOverflowing=document.body.clientWidth<a,this.scrollbarWidth=this.measureScrollbar()},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.originalBodyPad=document.body.style.paddingRight||"",this.bodyIsOverflowing&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right",this.originalBodyPad)},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=null,this.options=null,this.enabled=null,this.timeout=null,this.hoverState=null,this.$element=null,this.inState=null,this.init("tooltip",a,b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){if(this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(a.isFunction(this.options.viewport)?this.options.viewport.call(this,this.$element):this.options.viewport.selector||this.options.viewport),this.inState={click:!1,hover:!1,focus:!1},this.$element[0]instanceof document.constructor&&!this.options.selector)throw new Error("`selector` option must be specified when initializing "+this.type+" on the window.document object!");for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusin"==b.type?"focus":"hover"]=!0),c.tip().hasClass("in")||"in"==c.hoverState?void(c.hoverState="in"):(clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show())},c.prototype.isInStateTrue=function(){for(var a in this.inState)if(this.inState[a])return!0;return!1},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);if(c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),b instanceof a.Event&&(c.inState["focusout"==b.type?"focus":"hover"]=!1),!c.isInStateTrue())return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var d=a.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!d)return;var e=this,f=this.tip(),g=this.getUID(this.type);this.setContent(),f.attr("id",g),this.$element.attr("aria-describedby",g),this.options.animation&&f.addClass("fade");var h="function"==typeof this.options.placement?this.options.placement.call(this,f[0],this.$element[0]):this.options.placement,i=/\s?auto?\s?/i,j=i.test(h);j&&(h=h.replace(i,"")||"top"),f.detach().css({top:0,left:0,display:"block"}).addClass(h).data("bs."+this.type,this),this.options.container?f.appendTo(this.options.container):f.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var k=this.getPosition(),l=f[0].offsetWidth,m=f[0].offsetHeight;if(j){var n=h,o=this.getPosition(this.$viewport);h="bottom"==h&&k.bottom+m>o.bottom?"top":"top"==h&&k.top-m<o.top?"bottom":"right"==h&&k.right+l>o.width?"left":"left"==h&&k.left-l<o.left?"right":h,f.removeClass(n).addClass(h)}var p=this.getCalculatedOffset(h,k,l,m);this.applyPlacement(p,h);var q=function(){var a=e.hoverState;e.$element.trigger("shown.bs."+e.type),e.hoverState=null,"out"==a&&e.leave(e)};a.support.transition&&this.$tip.hasClass("fade")?f.one("bsTransitionEnd",q).emulateTransitionEnd(c.TRANSITION_DURATION):q()}},c.prototype.applyPlacement=function(b,c){var d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),b.top+=g,b.left+=h,a.offset.setOffset(d[0],a.extend({using:function(a){d.css({top:Math.round(a.top),left:Math.round(a.left)})}},b),0),d.addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;"top"==c&&j!=f&&(b.top=b.top+f-j);var k=this.getViewportAdjustedDelta(c,b,i,j);k.left?b.left+=k.left:b.top+=k.top;var l=/top|bottom/.test(c),m=l?2*k.left-e+i:2*k.top-f+j,n=l?"offsetWidth":"offsetHeight";d.offset(b),this.replaceArrow(m,d[0][n],l)},c.prototype.replaceArrow=function(a,b,c){this.arrow().css(c?"left":"top",50*(1-a/b)+"%").css(c?"top":"left","")},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},c.prototype.hide=function(b){function d(){"in"!=e.hoverState&&f.detach(),e.$element&&e.$element.removeAttr("aria-describedby").trigger("hidden.bs."+e.type),b&&b()}var e=this,f=a(this.$tip),g=a.Event("hide.bs."+this.type);if(this.$element.trigger(g),!g.isDefaultPrevented())return f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",d).emulateTransitionEnd(c.TRANSITION_DURATION):d(),this.hoverState=null,this},c.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},c.prototype.hasContent=function(){return this.getTitle()},c.prototype.getPosition=function(b){b=b||this.$element;var c=b[0],d="BODY"==c.tagName,e=c.getBoundingClientRect();null==e.width&&(e=a.extend({},e,{width:e.right-e.left,height:e.bottom-e.top}));var f=window.SVGElement&&c instanceof window.SVGElement,g=d?{top:0,left:0}:f?null:b.offset(),h={scroll:d?document.documentElement.scrollTop||document.body.scrollTop:b.scrollTop()},i=d?{width:a(window).width(),height:a(window).height()}:null;return a.extend({},e,h,i,g)},c.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},c.prototype.getViewportAdjustedDelta=function(a,b,c,d){var e={top:0,left:0};if(!this.$viewport)return e;var f=this.options.viewport&&this.options.viewport.padding||0,g=this.getPosition(this.$viewport);if(/right|left/.test(a)){var h=b.top-f-g.scroll,i=b.top+f-g.scroll+d;h<g.top?e.top=g.top-h:i>g.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;j<g.left?e.left=g.left-j:k>g.right&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){if(!this.$tip&&(this.$tip=a(this.options.template),1!=this.$tip.length))throw new Error(this.type+" `template` option must consist of exactly 1 top-level element!");return this.$tip},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),b?(c.inState.click=!c.inState.click,c.isInStateTrue()?c.enter(c):c.leave(c)):c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){var a=this;clearTimeout(this.timeout),this.hide(function(){a.$element.off("."+a.type).removeData("bs."+a.type),a.$tip&&a.$tip.detach(),a.$tip=null,a.$arrow=null,a.$viewport=null,a.$element=null})};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;!e&&/destroy|hide/.test(b)||(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.3.7",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){this.$body=a(document.body),this.$scrollElement=a(a(c).is(document.body)?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",a.proxy(this.process,this)),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.3.7",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b=this,c="offset",d=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),a.isWindow(this.$scrollElement[0])||(c="position",d=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var b=a(this),e=b.data("target")||b.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[c]().top+d,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<e[0])return this.activeTarget=null,this.clear();for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(void 0===e[a+1]||b<e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){ +this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery); diff --git a/web/gui/lib/bootstrap-slider-10.0.0.min.js b/web/gui/lib/bootstrap-slider-10.0.0.min.js new file mode 100644 index 0000000..87e8349 --- /dev/null +++ b/web/gui/lib/bootstrap-slider-10.0.0.min.js @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +/*! ======================================================= + VERSION 10.0.0 +========================================================= */ +"use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(a){return typeof a}:function(a){return a&&"function"==typeof Symbol&&a.constructor===Symbol&&a!==Symbol.prototype?"symbol":typeof a},windowIsDefined="object"===("undefined"==typeof window?"undefined":_typeof(window));!function(a){if("function"==typeof define&&define.amd)define(["jquery"],a);else if("object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports){var b;try{b=require("jquery")}catch(c){b=null}module.exports=a(b)}else window&&(window.Slider=a(window.jQuery))}(function(a){var b="slider",c="bootstrapSlider";windowIsDefined&&!window.console&&(window.console={}),windowIsDefined&&!window.console.log&&(window.console.log=function(){}),windowIsDefined&&!window.console.warn&&(window.console.warn=function(){});var d;return function(a){function b(){}function c(a){function c(b){b.prototype.option||(b.prototype.option=function(b){a.isPlainObject(b)&&(this.options=a.extend(!0,this.options,b))})}function e(b,c){a.fn[b]=function(e){if("string"==typeof e){for(var g=d.call(arguments,1),h=0,i=this.length;i>h;h++){var j=this[h],k=a.data(j,b);if(k)if(a.isFunction(k[e])&&"_"!==e.charAt(0)){var l=k[e].apply(k,g);if(void 0!==l&&l!==k)return l}else f("no such method '"+e+"' for "+b+" instance");else f("cannot call methods on "+b+" prior to initialization; attempted to call '"+e+"'")}return this}var m=this.map(function(){var d=a.data(this,b);return d?(d.option(e),d._init()):(d=new c(this,e),a.data(this,b,d)),a(this)});return!m||m.length>1?m:m[0]}}if(a){var f="undefined"==typeof console?b:function(a){console.error(a)};return a.bridget=function(a,b){c(b),e(a,b)},a.bridget}}var d=Array.prototype.slice;c(a)}(a),function(a){function e(b,c){function d(a,b){var c="data-slider-"+b.replace(/_/g,"-"),d=a.getAttribute(c);try{return JSON.parse(d)}catch(e){return d}}this._state={value:null,enabled:null,offset:null,size:null,percentage:null,inDrag:!1,over:!1},this.ticksCallbackMap={},this.handleCallbackMap={},"string"==typeof b?this.element=document.querySelector(b):b instanceof HTMLElement&&(this.element=b),c=c?c:{};for(var e=Object.keys(this.defaultOptions),f=0;f<e.length;f++){var h=e[f],i=c[h];i="undefined"!=typeof i?i:d(this.element,h),i=null!==i?i:this.defaultOptions[h],this.options||(this.options={}),this.options[h]=i}"auto"===this.options.rtl&&(this.options.rtl="rtl"===window.getComputedStyle(this.element).direction),"vertical"!==this.options.orientation||"top"!==this.options.tooltip_position&&"bottom"!==this.options.tooltip_position?"horizontal"!==this.options.orientation||"left"!==this.options.tooltip_position&&"right"!==this.options.tooltip_position||(this.options.tooltip_position="top"):this.options.rtl?this.options.tooltip_position="left":this.options.tooltip_position="right";var j,k,l,m,n,o=this.element.style.width,p=!1,q=this.element.parentNode;if(this.sliderElem)p=!0;else{this.sliderElem=document.createElement("div"),this.sliderElem.className="slider";var r=document.createElement("div");r.className="slider-track",k=document.createElement("div"),k.className="slider-track-low",j=document.createElement("div"),j.className="slider-selection",l=document.createElement("div"),l.className="slider-track-high",m=document.createElement("div"),m.className="slider-handle min-slider-handle",m.setAttribute("role","slider"),m.setAttribute("aria-valuemin",this.options.min),m.setAttribute("aria-valuemax",this.options.max),n=document.createElement("div"),n.className="slider-handle max-slider-handle",n.setAttribute("role","slider"),n.setAttribute("aria-valuemin",this.options.min),n.setAttribute("aria-valuemax",this.options.max),r.appendChild(k),r.appendChild(j),r.appendChild(l),this.rangeHighlightElements=[];var s=this.options.rangeHighlights;if(Array.isArray(s)&&s.length>0)for(var t=0;t<s.length;t++){var u=document.createElement("div"),v=s[t]["class"]||"";u.className="slider-rangeHighlight slider-selection "+v,this.rangeHighlightElements.push(u),r.appendChild(u)}var w=Array.isArray(this.options.labelledby);if(w&&this.options.labelledby[0]&&m.setAttribute("aria-labelledby",this.options.labelledby[0]),w&&this.options.labelledby[1]&&n.setAttribute("aria-labelledby",this.options.labelledby[1]),!w&&this.options.labelledby&&(m.setAttribute("aria-labelledby",this.options.labelledby),n.setAttribute("aria-labelledby",this.options.labelledby)),this.ticks=[],Array.isArray(this.options.ticks)&&this.options.ticks.length>0){for(this.ticksContainer=document.createElement("div"),this.ticksContainer.className="slider-tick-container",f=0;f<this.options.ticks.length;f++){var x=document.createElement("div");if(x.className="slider-tick",this.options.ticks_tooltip){var y=this._addTickListener(),z=y.addMouseEnter(this,x,f),A=y.addMouseLeave(this,x);this.ticksCallbackMap[f]={mouseEnter:z,mouseLeave:A}}this.ticks.push(x),this.ticksContainer.appendChild(x)}j.className+=" tick-slider-selection"}if(this.tickLabels=[],Array.isArray(this.options.ticks_labels)&&this.options.ticks_labels.length>0)for(this.tickLabelContainer=document.createElement("div"),this.tickLabelContainer.className="slider-tick-label-container",f=0;f<this.options.ticks_labels.length;f++){var B=document.createElement("div"),C=0===this.options.ticks_positions.length,D=this.options.reversed&&C?this.options.ticks_labels.length-(f+1):f;B.className="slider-tick-label",B.innerHTML=this.options.ticks_labels[D],this.tickLabels.push(B),this.tickLabelContainer.appendChild(B)}var E=function(a){var b=document.createElement("div");b.className="tooltip-arrow";var c=document.createElement("div");c.className="tooltip-inner",a.appendChild(b),a.appendChild(c)},F=document.createElement("div");F.className="tooltip tooltip-main",F.setAttribute("role","presentation"),E(F);var G=document.createElement("div");G.className="tooltip tooltip-min",G.setAttribute("role","presentation"),E(G);var H=document.createElement("div");H.className="tooltip tooltip-max",H.setAttribute("role","presentation"),E(H),this.sliderElem.appendChild(r),this.sliderElem.appendChild(F),this.sliderElem.appendChild(G),this.sliderElem.appendChild(H),this.tickLabelContainer&&this.sliderElem.appendChild(this.tickLabelContainer),this.ticksContainer&&this.sliderElem.appendChild(this.ticksContainer),this.sliderElem.appendChild(m),this.sliderElem.appendChild(n),q.insertBefore(this.sliderElem,this.element),this.element.style.display="none"}if(a&&(this.$element=a(this.element),this.$sliderElem=a(this.sliderElem)),this.eventToCallbackMap={},this.sliderElem.id=this.options.id,this.touchCapable="ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,this.touchX=0,this.touchY=0,this.tooltip=this.sliderElem.querySelector(".tooltip-main"),this.tooltipInner=this.tooltip.querySelector(".tooltip-inner"),this.tooltip_min=this.sliderElem.querySelector(".tooltip-min"),this.tooltipInner_min=this.tooltip_min.querySelector(".tooltip-inner"),this.tooltip_max=this.sliderElem.querySelector(".tooltip-max"),this.tooltipInner_max=this.tooltip_max.querySelector(".tooltip-inner"),g[this.options.scale]&&(this.options.scale=g[this.options.scale]),p===!0&&(this._removeClass(this.sliderElem,"slider-horizontal"),this._removeClass(this.sliderElem,"slider-vertical"),this._removeClass(this.sliderElem,"slider-rtl"),this._removeClass(this.tooltip,"hide"),this._removeClass(this.tooltip_min,"hide"),this._removeClass(this.tooltip_max,"hide"),["left","right","top","width","height"].forEach(function(a){this._removeProperty(this.trackLow,a),this._removeProperty(this.trackSelection,a),this._removeProperty(this.trackHigh,a)},this),[this.handle1,this.handle2].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"right"),this._removeProperty(a,"top")},this),[this.tooltip,this.tooltip_min,this.tooltip_max].forEach(function(a){this._removeProperty(a,"left"),this._removeProperty(a,"right"),this._removeProperty(a,"top"),this._removeClass(a,"right"),this._removeClass(a,"left"),this._removeClass(a,"top")},this)),"vertical"===this.options.orientation?(this._addClass(this.sliderElem,"slider-vertical"),this.stylePos="top",this.mousePos="pageY",this.sizePos="offsetHeight"):(this._addClass(this.sliderElem,"slider-horizontal"),this.sliderElem.style.width=o,this.options.orientation="horizontal",this.options.rtl?this.stylePos="right":this.stylePos="left",this.mousePos="pageX",this.sizePos="offsetWidth"),this.options.rtl&&this._addClass(this.sliderElem,"slider-rtl"),this._setTooltipPosition(),Array.isArray(this.options.ticks)&&this.options.ticks.length>0&&(this.options.max=Math.max.apply(Math,this.options.ticks),this.options.min=Math.min.apply(Math,this.options.ticks)),Array.isArray(this.options.value)?(this.options.range=!0,this._state.value=this.options.value):this.options.range?this._state.value=[this.options.value,this.options.max]:this._state.value=this.options.value,this.trackLow=k||this.trackLow,this.trackSelection=j||this.trackSelection,this.trackHigh=l||this.trackHigh,"none"===this.options.selection?(this._addClass(this.trackLow,"hide"),this._addClass(this.trackSelection,"hide"),this._addClass(this.trackHigh,"hide")):("after"===this.options.selection||"before"===this.options.selection)&&(this._removeClass(this.trackLow,"hide"),this._removeClass(this.trackSelection,"hide"),this._removeClass(this.trackHigh,"hide")),this.handle1=m||this.handle1,this.handle2=n||this.handle2,p===!0)for(this._removeClass(this.handle1,"round triangle"),this._removeClass(this.handle2,"round triangle hide"),f=0;f<this.ticks.length;f++)this._removeClass(this.ticks[f],"round triangle hide");var I=["round","triangle","custom"],J=-1!==I.indexOf(this.options.handle);if(J)for(this._addClass(this.handle1,this.options.handle),this._addClass(this.handle2,this.options.handle),f=0;f<this.ticks.length;f++)this._addClass(this.ticks[f],this.options.handle);if(this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this.setValue(this._state.value),this.handle1Keydown=this._keydown.bind(this,0),this.handle1.addEventListener("keydown",this.handle1Keydown,!1),this.handle2Keydown=this._keydown.bind(this,1),this.handle2.addEventListener("keydown",this.handle2Keydown,!1),this.mousedown=this._mousedown.bind(this),this.touchstart=this._touchstart.bind(this),this.touchmove=this._touchmove.bind(this),this.touchCapable){var K=!1;try{var L=Object.defineProperty({},"passive",{get:function(){K=!0}});window.addEventListener("test",null,L)}catch(M){}var N=K?{passive:!0}:!1;this.sliderElem.addEventListener("touchstart",this.touchstart,N),this.sliderElem.addEventListener("touchmove",this.touchmove,N)}if(this.sliderElem.addEventListener("mousedown",this.mousedown,!1),this.resize=this._resize.bind(this),window.addEventListener("resize",this.resize,!1),"hide"===this.options.tooltip)this._addClass(this.tooltip,"hide"),this._addClass(this.tooltip_min,"hide"),this._addClass(this.tooltip_max,"hide");else if("always"===this.options.tooltip)this._showTooltip(),this._alwaysShowTooltip=!0;else{if(this.showTooltip=this._showTooltip.bind(this),this.hideTooltip=this._hideTooltip.bind(this),this.options.ticks_tooltip){var O=this._addTickListener(),P=O.addMouseEnter(this,this.handle1),Q=O.addMouseLeave(this,this.handle1);this.handleCallbackMap.handle1={mouseEnter:P,mouseLeave:Q},P=O.addMouseEnter(this,this.handle2),Q=O.addMouseLeave(this,this.handle2),this.handleCallbackMap.handle2={mouseEnter:P,mouseLeave:Q}}else this.sliderElem.addEventListener("mouseenter",this.showTooltip,!1),this.sliderElem.addEventListener("mouseleave",this.hideTooltip,!1);this.handle1.addEventListener("focus",this.showTooltip,!1),this.handle1.addEventListener("blur",this.hideTooltip,!1),this.handle2.addEventListener("focus",this.showTooltip,!1),this.handle2.addEventListener("blur",this.hideTooltip,!1)}this.options.enabled?this.enable():this.disable()}var f={formatInvalidInputErrorMsg:function(a){return"Invalid input value '"+a+"' passed in"},callingContextNotSliderInstance:"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"},g={linear:{toValue:function(a){var b=a/100*(this.options.max-this.options.min),c=!0;if(this.options.ticks_positions.length>0){for(var d,e,f,g=0,h=1;h<this.options.ticks_positions.length;h++)if(a<=this.options.ticks_positions[h]){d=this.options.ticks[h-1],f=this.options.ticks_positions[h-1],e=this.options.ticks[h],g=this.options.ticks_positions[h];break}var i=(a-f)/(g-f);b=d+i*(e-d),c=!1}var j=c?this.options.min:0,k=j+Math.round(b/this.options.step)*this.options.step;return k<this.options.min?this.options.min:k>this.options.max?this.options.max:k},toPercentage:function(a){if(this.options.max===this.options.min)return 0;if(this.options.ticks_positions.length>0){for(var b,c,d,e=0,f=0;f<this.options.ticks.length;f++)if(a<=this.options.ticks[f]){b=f>0?this.options.ticks[f-1]:0,d=f>0?this.options.ticks_positions[f-1]:0,c=this.options.ticks[f],e=this.options.ticks_positions[f];break}if(f>0){var g=(a-b)/(c-b);return d+g*(e-d)}}return 100*(a-this.options.min)/(this.options.max-this.options.min)}},logarithmic:{toValue:function(a){var b=0===this.options.min?0:Math.log(this.options.min),c=Math.log(this.options.max),d=Math.exp(b+(c-b)*a/100);return Math.round(d)===this.options.max?this.options.max:(d=this.options.min+Math.round((d-this.options.min)/this.options.step)*this.options.step,d<this.options.min?this.options.min:d>this.options.max?this.options.max:d)},toPercentage:function(a){if(this.options.max===this.options.min)return 0;var b=Math.log(this.options.max),c=0===this.options.min?0:Math.log(this.options.min),d=0===a?0:Math.log(a);return 100*(d-c)/(b-c)}}};if(d=function(a,b){return e.call(this,a,b),this},d.prototype={_init:function(){},constructor:d,defaultOptions:{id:"",min:0,max:10,step:1,precision:0,orientation:"horizontal",value:5,range:!1,selection:"before",tooltip:"show",tooltip_split:!1,handle:"round",reversed:!1,rtl:"auto",enabled:!0,formatter:function(a){return Array.isArray(a)?a[0]+" : "+a[1]:a},natural_arrow_keys:!1,ticks:[],ticks_positions:[],ticks_labels:[],ticks_snap_bounds:0,ticks_tooltip:!1,scale:"linear",focus:!1,tooltip_position:null,labelledby:null,rangeHighlights:[]},getElement:function(){return this.sliderElem},getValue:function(){return this.options.range?this._state.value:this._state.value[0]},setValue:function(a,b,c){a||(a=0);var d=this.getValue();this._state.value=this._validateInputValue(a);var e=this._applyPrecision.bind(this);this.options.range?(this._state.value[0]=e(this._state.value[0]),this._state.value[1]=e(this._state.value[1]),this._state.value[0]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[0])),this._state.value[1]=Math.max(this.options.min,Math.min(this.options.max,this._state.value[1]))):(this._state.value=e(this._state.value),this._state.value=[Math.max(this.options.min,Math.min(this.options.max,this._state.value))],this._addClass(this.handle2,"hide"),"after"===this.options.selection?this._state.value[1]=this.options.max:this._state.value[1]=this.options.min),this.options.max>this.options.min?this._state.percentage=[this._toPercentage(this._state.value[0]),this._toPercentage(this._state.value[1]),100*this.options.step/(this.options.max-this.options.min)]:this._state.percentage=[0,0,100],this._layout();var f=this.options.range?this._state.value:this._state.value[0];return this._setDataVal(f),b===!0&&this._trigger("slide",f),d!==f&&c===!0&&this._trigger("change",{oldValue:d,newValue:f}),this},destroy:function(){this._removeSliderEventHandlers(),this.sliderElem.parentNode.removeChild(this.sliderElem),this.element.style.display="",this._cleanUpEventCallbacksMap(),this.element.removeAttribute("data"),a&&(this._unbindJQueryEventHandlers(),this.$element.removeData("slider"))},disable:function(){return this._state.enabled=!1,this.handle1.removeAttribute("tabindex"),this.handle2.removeAttribute("tabindex"),this._addClass(this.sliderElem,"slider-disabled"),this._trigger("slideDisabled"),this},enable:function(){return this._state.enabled=!0,this.handle1.setAttribute("tabindex",0),this.handle2.setAttribute("tabindex",0),this._removeClass(this.sliderElem,"slider-disabled"),this._trigger("slideEnabled"),this},toggle:function(){return this._state.enabled?this.disable():this.enable(),this},isEnabled:function(){return this._state.enabled},on:function(a,b){return this._bindNonQueryEventHandler(a,b),this},off:function(b,c){a?(this.$element.off(b,c),this.$sliderElem.off(b,c)):this._unbindNonQueryEventHandler(b,c)},getAttribute:function(a){return a?this.options[a]:this.options},setAttribute:function(a,b){return this.options[a]=b,this},refresh:function(){return this._removeSliderEventHandlers(),e.call(this,this.element,this.options),a&&a.data(this.element,"slider",this),this},relayout:function(){return this._resize(),this._layout(),this},_removeSliderEventHandlers:function(){if(this.handle1.removeEventListener("keydown",this.handle1Keydown,!1),this.handle2.removeEventListener("keydown",this.handle2Keydown,!1),this.options.ticks_tooltip){for(var a=this.ticksContainer.getElementsByClassName("slider-tick"),b=0;b<a.length;b++)a[b].removeEventListener("mouseenter",this.ticksCallbackMap[b].mouseEnter,!1),a[b].removeEventListener("mouseleave",this.ticksCallbackMap[b].mouseLeave,!1);this.handle1.removeEventListener("mouseenter",this.handleCallbackMap.handle1.mouseEnter,!1),this.handle2.removeEventListener("mouseenter",this.handleCallbackMap.handle2.mouseEnter,!1),this.handle1.removeEventListener("mouseleave",this.handleCallbackMap.handle1.mouseLeave,!1),this.handle2.removeEventListener("mouseleave",this.handleCallbackMap.handle2.mouseLeave,!1)}this.handleCallbackMap=null,this.ticksCallbackMap=null,this.showTooltip&&(this.handle1.removeEventListener("focus",this.showTooltip,!1),this.handle2.removeEventListener("focus",this.showTooltip,!1)),this.hideTooltip&&(this.handle1.removeEventListener("blur",this.hideTooltip,!1),this.handle2.removeEventListener("blur",this.hideTooltip,!1)),this.showTooltip&&this.sliderElem.removeEventListener("mouseenter",this.showTooltip,!1),this.hideTooltip&&this.sliderElem.removeEventListener("mouseleave",this.hideTooltip,!1),this.sliderElem.removeEventListener("touchstart",this.touchstart,!1),this.sliderElem.removeEventListener("touchmove",this.touchmove,!1),this.sliderElem.removeEventListener("mousedown",this.mousedown,!1),window.removeEventListener("resize",this.resize,!1)},_bindNonQueryEventHandler:function(a,b){void 0===this.eventToCallbackMap[a]&&(this.eventToCallbackMap[a]=[]),this.eventToCallbackMap[a].push(b)},_unbindNonQueryEventHandler:function(a,b){var c=this.eventToCallbackMap[a];if(void 0!==c)for(var d=0;d<c.length;d++)if(c[d]===b){c.splice(d,1);break}},_cleanUpEventCallbacksMap:function(){for(var a=Object.keys(this.eventToCallbackMap),b=0;b<a.length;b++){var c=a[b];delete this.eventToCallbackMap[c]}},_showTooltip:function(){this.options.tooltip_split===!1?(this._addClass(this.tooltip,"in"),this.tooltip_min.style.display="none",this.tooltip_max.style.display="none"):(this._addClass(this.tooltip_min,"in"),this._addClass(this.tooltip_max,"in"),this.tooltip.style.display="none"),this._state.over=!0},_hideTooltip:function(){this._state.inDrag===!1&&this.alwaysShowTooltip!==!0&&(this._removeClass(this.tooltip,"in"),this._removeClass(this.tooltip_min,"in"),this._removeClass(this.tooltip_max,"in")),this._state.over=!1},_setToolTipOnMouseOver:function(a){function b(a,b){return b?[100-a.percentage[0],this.options.range?100-a.percentage[1]:a.percentage[1]]:[a.percentage[0],a.percentage[1]]}var c=this.options.formatter(a?a.value[0]:this._state.value[0]),d=a?b(a,this.options.reversed):b(this._state,this.options.reversed);this._setText(this.tooltipInner,c),this.tooltip.style[this.stylePos]=d[0]+"%"},_addTickListener:function(){return{addMouseEnter:function(a,b,c){var d=function(){var b=a._state,d=c>=0?c:this.attributes["aria-valuenow"].value,e=parseInt(d,10);b.value[0]=e,b.percentage[0]=a.options.ticks_positions[e],a._setToolTipOnMouseOver(b),a._showTooltip()};return b.addEventListener("mouseenter",d,!1),d},addMouseLeave:function(a,b){var c=function(){a._hideTooltip()};return b.addEventListener("mouseleave",c,!1),c}}},_layout:function(){var a;if(a=this.options.reversed?[100-this._state.percentage[0],this.options.range?100-this._state.percentage[1]:this._state.percentage[1]]:[this._state.percentage[0],this._state.percentage[1]],this.handle1.style[this.stylePos]=a[0]+"%",this.handle1.setAttribute("aria-valuenow",this._state.value[0]),isNaN(this.options.formatter(this._state.value[0]))&&this.handle1.setAttribute("aria-valuetext",this.options.formatter(this._state.value[0])),this.handle2.style[this.stylePos]=a[1]+"%",this.handle2.setAttribute("aria-valuenow",this._state.value[1]),isNaN(this.options.formatter(this._state.value[1]))&&this.handle2.setAttribute("aria-valuetext",this.options.formatter(this._state.value[1])),this.rangeHighlightElements.length>0&&Array.isArray(this.options.rangeHighlights)&&this.options.rangeHighlights.length>0)for(var b=0;b<this.options.rangeHighlights.length;b++){var c=this._toPercentage(this.options.rangeHighlights[b].start),d=this._toPercentage(this.options.rangeHighlights[b].end);if(this.options.reversed){var e=100-d;d=100-c,c=e}var f=this._createHighlightRange(c,d);f?"vertical"===this.options.orientation?(this.rangeHighlightElements[b].style.top=f.start+"%",this.rangeHighlightElements[b].style.height=f.size+"%"):(this.options.rtl?this.rangeHighlightElements[b].style.right=f.start+"%":this.rangeHighlightElements[b].style.left=f.start+"%",this.rangeHighlightElements[b].style.width=f.size+"%"):this.rangeHighlightElements[b].style.display="none"}if(Array.isArray(this.options.ticks)&&this.options.ticks.length>0){var g,h="vertical"===this.options.orientation?"height":"width";g="vertical"===this.options.orientation?"marginTop":this.options.rtl?"marginRight":"marginLeft";var i=this._state.size/(this.options.ticks.length-1);if(this.tickLabelContainer){var j=0;if(0===this.options.ticks_positions.length)"vertical"!==this.options.orientation&&(this.tickLabelContainer.style[g]=-i/2+"px"),j=this.tickLabelContainer.offsetHeight;else for(k=0;k<this.tickLabelContainer.childNodes.length;k++)this.tickLabelContainer.childNodes[k].offsetHeight>j&&(j=this.tickLabelContainer.childNodes[k].offsetHeight);"horizontal"===this.options.orientation&&(this.sliderElem.style.marginBottom=j+"px")}for(var k=0;k<this.options.ticks.length;k++){var l=this.options.ticks_positions[k]||this._toPercentage(this.options.ticks[k]);this.options.reversed&&(l=100-l),this.ticks[k].style[this.stylePos]=l+"%",this._removeClass(this.ticks[k],"in-selection"),this.options.range?l>=a[0]&&l<=a[1]&&this._addClass(this.ticks[k],"in-selection"):"after"===this.options.selection&&l>=a[0]?this._addClass(this.ticks[k],"in-selection"):"before"===this.options.selection&&l<=a[0]&&this._addClass(this.ticks[k],"in-selection"),this.tickLabels[k]&&(this.tickLabels[k].style[h]=i+"px","vertical"!==this.options.orientation&&void 0!==this.options.ticks_positions[k]?(this.tickLabels[k].style.position="absolute",this.tickLabels[k].style[this.stylePos]=l+"%",this.tickLabels[k].style[g]=-i/2+"px"):"vertical"===this.options.orientation&&(this.options.rtl?this.tickLabels[k].style.marginRight=this.sliderElem.offsetWidth+"px":this.tickLabels[k].style.marginLeft=this.sliderElem.offsetWidth+"px",this.tickLabelContainer.style[g]=this.sliderElem.offsetWidth/2*-1+"px"))}}var m;if(this.options.range){m=this.options.formatter(this._state.value),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=(a[1]+a[0])/2+"%";var n=this.options.formatter(this._state.value[0]);this._setText(this.tooltipInner_min,n);var o=this.options.formatter(this._state.value[1]);this._setText(this.tooltipInner_max,o),this.tooltip_min.style[this.stylePos]=a[0]+"%",this.tooltip_max.style[this.stylePos]=a[1]+"%"}else m=this.options.formatter(this._state.value[0]),this._setText(this.tooltipInner,m),this.tooltip.style[this.stylePos]=a[0]+"%";if("vertical"===this.options.orientation)this.trackLow.style.top="0",this.trackLow.style.height=Math.min(a[0],a[1])+"%",this.trackSelection.style.top=Math.min(a[0],a[1])+"%",this.trackSelection.style.height=Math.abs(a[0]-a[1])+"%",this.trackHigh.style.bottom="0",this.trackHigh.style.height=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";else{"right"===this.stylePos?this.trackLow.style.right="0":this.trackLow.style.left="0",this.trackLow.style.width=Math.min(a[0],a[1])+"%","right"===this.stylePos?this.trackSelection.style.right=Math.min(a[0],a[1])+"%":this.trackSelection.style.left=Math.min(a[0],a[1])+"%",this.trackSelection.style.width=Math.abs(a[0]-a[1])+"%","right"===this.stylePos?this.trackHigh.style.left="0":this.trackHigh.style.right="0",this.trackHigh.style.width=100-Math.min(a[0],a[1])-Math.abs(a[0]-a[1])+"%";var p=this.tooltip_min.getBoundingClientRect(),q=this.tooltip_max.getBoundingClientRect();"bottom"===this.options.tooltip_position?p.right>q.left?(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top="",this.tooltip_max.style.bottom="22px"):(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top=this.tooltip_min.style.top,this.tooltip_max.style.bottom=""):p.right>q.left?(this._removeClass(this.tooltip_max,"top"),this._addClass(this.tooltip_max,"bottom"),this.tooltip_max.style.top="18px"):(this._removeClass(this.tooltip_max,"bottom"),this._addClass(this.tooltip_max,"top"),this.tooltip_max.style.top=this.tooltip_min.style.top)}},_createHighlightRange:function(a,b){return this._isHighlightRange(a,b)?a>b?{start:b,size:a-b}:{start:a,size:b-a}:null},_isHighlightRange:function(a,b){return a>=0&&100>=a&&b>=0&&100>=b?!0:!1},_resize:function(a){this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos],this._layout()},_removeProperty:function(a,b){a.style.removeProperty?a.style.removeProperty(b):a.style.removeAttribute(b)},_mousedown:function(a){if(!this._state.enabled)return!1;this._state.offset=this._offset(this.sliderElem),this._state.size=this.sliderElem[this.sizePos];var b=this._getPercentage(a);if(this.options.range){var c=Math.abs(this._state.percentage[0]-b),d=Math.abs(this._state.percentage[1]-b);this._state.dragged=d>c?0:1,this._adjustPercentageForRangeSliders(b)}else this._state.dragged=0;this._state.percentage[this._state.dragged]=b,this._layout(),this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),this.mousemove&&document.removeEventListener("mousemove",this.mousemove,!1),this.mouseup&&document.removeEventListener("mouseup",this.mouseup,!1),this.mousemove=this._mousemove.bind(this),this.mouseup=this._mouseup.bind(this),this.touchCapable&&(document.addEventListener("touchmove",this.mousemove,!1),document.addEventListener("touchend",this.mouseup,!1)),document.addEventListener("mousemove",this.mousemove,!1),document.addEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!0;var e=this._calculateValue();return this._trigger("slideStart",e),this._setDataVal(e),this.setValue(e,!1,!0),a.returnValue=!1,this.options.focus&&this._triggerFocusOnHandle(this._state.dragged),!0},_touchstart:function(a){if(void 0===a.changedTouches)return void this._mousedown(a);var b=a.changedTouches[0];this.touchX=b.pageX,this.touchY=b.pageY},_triggerFocusOnHandle:function(a){0===a&&this.handle1.focus(),1===a&&this.handle2.focus()},_keydown:function(a,b){if(!this._state.enabled)return!1;var c;switch(b.keyCode){case 37:case 40:c=-1;break;case 39:case 38:c=1}if(c){if(this.options.natural_arrow_keys){var d="vertical"===this.options.orientation&&!this.options.reversed,e="horizontal"===this.options.orientation&&this.options.reversed;(d||e)&&(c=-c)}var f=this._state.value[a]+c*this.options.step,g=f/this.options.max*100;if(this._state.keyCtrl=a,this.options.range){this._adjustPercentageForRangeSliders(g);var h=this._state.keyCtrl?this._state.value[0]:f,i=this._state.keyCtrl?f:this._state.value[1];f=[h,i]}return this._trigger("slideStart",f),this._setDataVal(f),this.setValue(f,!0,!0),this._setDataVal(f),this._trigger("slideStop",f),this._layout(),this._pauseEvent(b),delete this._state.keyCtrl,!1}},_pauseEvent:function(a){a.stopPropagation&&a.stopPropagation(),a.preventDefault&&a.preventDefault(),a.cancelBubble=!0,a.returnValue=!1},_mousemove:function(a){if(!this._state.enabled)return!1;var b=this._getPercentage(a);this._adjustPercentageForRangeSliders(b),this._state.percentage[this._state.dragged]=b,this._layout();var c=this._calculateValue(!0);return this.setValue(c,!0,!0),!1},_touchmove:function(a){if(void 0!==a.changedTouches){var b=a.changedTouches[0],c=b.pageX-this.touchX,d=b.pageY-this.touchY;this._state.inDrag||("vertical"===this.options.orientation&&5>=c&&c>=-5&&(d>=15||-15>=d)?this._mousedown(a):5>=d&&d>=-5&&(c>=15||-15>=c)&&this._mousedown(a))}},_adjustPercentageForRangeSliders:function(a){if(this.options.range){var b=this._getNumDigitsAfterDecimalPlace(a);b=b?b-1:0;var c=this._applyToFixedAndParseFloat(a,b);0===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[1],b)<c?(this._state.percentage[0]=this._state.percentage[1],this._state.dragged=1):1===this._state.dragged&&this._applyToFixedAndParseFloat(this._state.percentage[0],b)>c?(this._state.percentage[1]=this._state.percentage[0],this._state.dragged=0):0===this._state.keyCtrl&&this._state.value[1]/this.options.max*100<a?(this._state.percentage[0]=this._state.percentage[1],this._state.keyCtrl=1,this.handle2.focus()):1===this._state.keyCtrl&&this._state.value[0]/this.options.max*100>a&&(this._state.percentage[1]=this._state.percentage[0],this._state.keyCtrl=0,this.handle1.focus())}},_mouseup:function(){if(!this._state.enabled)return!1;this.touchCapable&&(document.removeEventListener("touchmove",this.mousemove,!1),document.removeEventListener("touchend",this.mouseup,!1)),document.removeEventListener("mousemove",this.mousemove,!1),document.removeEventListener("mouseup",this.mouseup,!1),this._state.inDrag=!1,this._state.over===!1&&this._hideTooltip();var a=this._calculateValue(!0);return this._layout(),this._setDataVal(a),this._trigger("slideStop",a),!1},_calculateValue:function(a){var b;if(this.options.range?(b=[this.options.min,this.options.max],0!==this._state.percentage[0]&&(b[0]=this._toValue(this._state.percentage[0]),b[0]=this._applyPrecision(b[0])),100!==this._state.percentage[1]&&(b[1]=this._toValue(this._state.percentage[1]),b[1]=this._applyPrecision(b[1]))):(b=this._toValue(this._state.percentage[0]),b=parseFloat(b),b=this._applyPrecision(b)),a){for(var c=[b,1/0],d=0;d<this.options.ticks.length;d++){var e=Math.abs(this.options.ticks[d]-b);e<=c[1]&&(c=[this.options.ticks[d],e])}if(c[1]<=this.options.ticks_snap_bounds)return c[0]}return b},_applyPrecision:function(a){var b=this.options.precision||this._getNumDigitsAfterDecimalPlace(this.options.step);return this._applyToFixedAndParseFloat(a,b)},_getNumDigitsAfterDecimalPlace:function(a){var b=(""+a).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);return b?Math.max(0,(b[1]?b[1].length:0)-(b[2]?+b[2]:0)):0},_applyToFixedAndParseFloat:function(a,b){var c=a.toFixed(b);return parseFloat(c)},_getPercentage:function(a){!this.touchCapable||"touchstart"!==a.type&&"touchmove"!==a.type||(a=a.touches[0]);var b=a[this.mousePos],c=this._state.offset[this.stylePos],d=b-c;"right"===this.stylePos&&(d=-d);var e=d/this._state.size*100;return e=Math.round(e/this._state.percentage[2])*this._state.percentage[2],this.options.reversed&&(e=100-e),Math.max(0,Math.min(100,e))},_validateInputValue:function(a){if(isNaN(+a)){if(Array.isArray(a))return this._validateArray(a),a;throw new Error(f.formatInvalidInputErrorMsg(a))}return+a},_validateArray:function(a){for(var b=0;b<a.length;b++){ +var c=a[b];if("number"!=typeof c)throw new Error(f.formatInvalidInputErrorMsg(c))}},_setDataVal:function(a){this.element.setAttribute("data-value",a),this.element.setAttribute("value",a),this.element.value=a},_trigger:function(b,c){c=c||0===c?c:void 0;var d=this.eventToCallbackMap[b];if(d&&d.length)for(var e=0;e<d.length;e++){var f=d[e];f(c)}a&&this._triggerJQueryEvent(b,c)},_triggerJQueryEvent:function(a,b){var c={type:a,value:b};this.$element.trigger(c),this.$sliderElem.trigger(c)},_unbindJQueryEventHandlers:function(){this.$element.off(),this.$sliderElem.off()},_setText:function(a,b){"undefined"!=typeof a.textContent?a.textContent=b:"undefined"!=typeof a.innerText&&(a.innerText=b)},_removeClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)");d=d.replace(g," ")}a.className=d.trim()},_addClass:function(a,b){for(var c=b.split(" "),d=a.className,e=0;e<c.length;e++){var f=c[e],g=new RegExp("(?:\\s|^)"+f+"(?:\\s|$)"),h=g.test(d);h||(d+=" "+f)}a.className=d.trim()},_offsetLeft:function(a){return a.getBoundingClientRect().left},_offsetRight:function(a){return a.getBoundingClientRect().right},_offsetTop:function(a){for(var b=a.offsetTop;(a=a.offsetParent)&&!isNaN(a.offsetTop);)b+=a.offsetTop,"BODY"!==a.tagName&&(b-=a.scrollTop);return b},_offset:function(a){return{left:this._offsetLeft(a),right:this._offsetRight(a),top:this._offsetTop(a)}},_css:function(b,c,d){if(a)a.style(b,c,d);else{var e=c.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,b){return b.toUpperCase()});b.style[e]=d}},_toValue:function(a){return this.options.scale.toValue.apply(this,[a])},_toPercentage:function(a){return this.options.scale.toPercentage.apply(this,[a])},_setTooltipPosition:function(){var a=[this.tooltip,this.tooltip_min,this.tooltip_max];if("vertical"===this.options.orientation){var b;b=this.options.tooltip_position?this.options.tooltip_position:this.options.rtl?"left":"right";var c="left"===b?"right":"left";a.forEach(function(a){this._addClass(a,b),a.style[c]="100%"}.bind(this))}else"bottom"===this.options.tooltip_position?a.forEach(function(a){this._addClass(a,"bottom"),a.style.top="22px"}.bind(this)):a.forEach(function(a){this._addClass(a,"top"),a.style.top=-this.tooltip.outerHeight-14+"px"}.bind(this))}},a&&a.fn){var h=void 0;a.fn.slider?(windowIsDefined&&window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSlider namespace instead."),h=c):(a.bridget(b,d),h=b),a.bridget(c,d),a(function(){a("input[data-provide=slider]")[h]()})}}(a),d}); diff --git a/web/gui/lib/bootstrap-table-1.11.0.min.js b/web/gui/lib/bootstrap-table-1.11.0.min.js new file mode 100644 index 0000000..f4c2b8a --- /dev/null +++ b/web/gui/lib/bootstrap-table-1.11.0.min.js @@ -0,0 +1,9 @@ +/* +* bootstrap-table - v1.11.0 - 2016-07-02 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2016 zhixin wen +* Licensed MIT License +* SPDX-License-Identifier: MIT +*/ +!function(a){"use strict";var b=null,c=function(a){var b=arguments,c=!0,d=1;return a=a.replace(/%s/g,function(){var a=b[d++];return"undefined"==typeof a?(c=!1,""):a}),c?a:""},d=function(b,c,d,e){var f="";return a.each(b,function(a,b){return b[c]===e?(f=b[d],!1):!0}),f},e=function(b,c){var d=-1;return a.each(b,function(a,b){return b.field===c?(d=a,!1):!0}),d},f=function(b){var c,d,e,f=0,g=[];for(c=0;c<b[0].length;c++)f+=b[0][c].colspan||1;for(c=0;c<b.length;c++)for(g[c]=[],d=0;f>d;d++)g[c][d]=!1;for(c=0;c<b.length;c++)for(d=0;d<b[c].length;d++){var h=b[c][d],i=h.rowspan||1,j=h.colspan||1,k=a.inArray(!1,g[c]);for(1===j&&(h.fieldIndex=k,"undefined"==typeof h.field&&(h.field=k)),e=0;i>e;e++)g[c+e][k]=!0;for(e=0;j>e;e++)g[c][k+e]=!0}},g=function(){if(null===b){var c,d,e=a("<p/>").addClass("fixed-table-scroll-inner"),f=a("<div/>").addClass("fixed-table-scroll-outer");f.append(e),a("body").append(f),c=e[0].offsetWidth,f.css("overflow","scroll"),d=e[0].offsetWidth,c===d&&(d=f[0].clientWidth),f.remove(),b=c-d}return b},h=function(b,d,e,f){var g=d;if("string"==typeof d){var h=d.split(".");h.length>1?(g=window,a.each(h,function(a,b){g=g[b]})):g=window[d]}return"object"==typeof g?g:"function"==typeof g?g.apply(b,e):!g&&"string"==typeof d&&c.apply(this,[d].concat(e))?c.apply(this,[d].concat(e)):f},i=function(b,c,d){var e=Object.getOwnPropertyNames(b),f=Object.getOwnPropertyNames(c),g="";if(d&&e.length!==f.length)return!1;for(var h=0;h<e.length;h++)if(g=e[h],a.inArray(g,f)>-1&&b[g]!==c[g])return!1;return!0},j=function(a){return"string"==typeof a?a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/`/g,"`"):a},k=function(b){var c=0;return b.children().each(function(){c<a(this).outerHeight(!0)&&(c=a(this).outerHeight(!0))}),c},l=function(a){for(var b in a){var c=b.split(/(?=[A-Z])/).join("-").toLowerCase();c!==b&&(a[c]=a[b],delete a[b])}return a},m=function(a,b,c){var d=a;if("string"!=typeof b||a.hasOwnProperty(b))return c?j(a[b]):a[b];var e=b.split(".");for(var f in e)d=d&&d[e[f]];return c?j(d):d},n=function(){return!!(navigator.userAgent.indexOf("MSIE ")>0||navigator.userAgent.match(/Trident.*rv\:11\./))},o=function(){Object.keys||(Object.keys=function(){var a=Object.prototype.hasOwnProperty,b=!{toString:null}.propertyIsEnumerable("toString"),c=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],d=c.length;return function(e){if("object"!=typeof e&&("function"!=typeof e||null===e))throw new TypeError("Object.keys called on non-object");var f,g,h=[];for(f in e)a.call(e,f)&&h.push(f);if(b)for(g=0;d>g;g++)a.call(e,c[g])&&h.push(c[g]);return h}}())},p=function(b,c){this.options=c,this.$el=a(b),this.$el_=this.$el.clone(),this.timeoutId_=0,this.timeoutFooter_=0,this.init()};p.DEFAULTS={classes:"table table-hover",locale:void 0,height:void 0,undefinedText:"-",sortName:void 0,sortOrder:"asc",sortStable:!1,striped:!1,columns:[[]],data:[],dataField:"rows",method:"get",url:void 0,ajax:void 0,cache:!0,contentType:"application/json",dataType:"json",ajaxOptions:{},queryParams:function(a){return a},queryParamsType:"limit",responseHandler:function(a){return a},pagination:!1,onlyInfoPagination:!1,sidePagination:"client",totalRows:0,pageNumber:1,pageSize:10,pageList:[10,25,50,100],paginationHAlign:"right",paginationVAlign:"bottom",paginationDetailHAlign:"left",paginationPreText:"‹",paginationNextText:"›",search:!1,searchOnEnterKey:!1,strictSearch:!1,searchAlign:"right",selectItemName:"btSelectItem",showHeader:!0,showFooter:!1,showColumns:!1,showPaginationSwitch:!1,showRefresh:!1,showToggle:!1,buttonsAlign:"right",smartDisplay:!0,escape:!1,minimumCountColumns:1,idField:void 0,uniqueId:void 0,cardView:!1,detailView:!1,detailFormatter:function(){return""},trimOnSearch:!0,clickToSelect:!1,singleSelect:!1,toolbar:void 0,toolbarAlign:"left",checkboxHeader:!0,sortable:!0,silentSort:!0,maintainSelected:!1,searchTimeOut:500,searchText:"",iconSize:void 0,buttonsClass:"default",iconsPrefix:"glyphicon",icons:{paginationSwitchDown:"glyphicon-collapse-down icon-chevron-down",paginationSwitchUp:"glyphicon-collapse-up icon-chevron-up",refresh:"glyphicon-refresh icon-refresh",toggle:"glyphicon-list-alt icon-list-alt",columns:"glyphicon-th icon-th",detailOpen:"glyphicon-plus icon-plus",detailClose:"glyphicon-minus icon-minus"},customSearch:a.noop,customSort:a.noop,rowStyle:function(){return{}},rowAttributes:function(){return{}},footerStyle:function(){return{}},onAll:function(){return!1},onClickCell:function(){return!1},onDblClickCell:function(){return!1},onClickRow:function(){return!1},onDblClickRow:function(){return!1},onSort:function(){return!1},onCheck:function(){return!1},onUncheck:function(){return!1},onCheckAll:function(){return!1},onUncheckAll:function(){return!1},onCheckSome:function(){return!1},onUncheckSome:function(){return!1},onLoadSuccess:function(){return!1},onLoadError:function(){return!1},onColumnSwitch:function(){return!1},onPageChange:function(){return!1},onSearch:function(){return!1},onToggle:function(){return!1},onPreBody:function(){return!1},onPostBody:function(){return!1},onPostHeader:function(){return!1},onExpandRow:function(){return!1},onCollapseRow:function(){return!1},onRefreshOptions:function(){return!1},onRefresh:function(){return!1},onResetView:function(){return!1}},p.LOCALES={},p.LOCALES["en-US"]=p.LOCALES.en={formatLoadingMessage:function(){return"Loading, please wait..."},formatRecordsPerPage:function(a){return c("%s rows per page",a)},formatShowingRows:function(a,b,d){return c("Showing %s to %s of %s rows",a,b,d)},formatDetailPagination:function(a){return c("Showing %s rows",a)},formatSearch:function(){return"Search"},formatNoMatches:function(){return"No matching records found"},formatPaginationSwitch:function(){return"Hide/Show pagination"},formatRefresh:function(){return"Refresh"},formatToggle:function(){return"Toggle"},formatColumns:function(){return"Columns"},formatAllRows:function(){return"All"}},a.extend(p.DEFAULTS,p.LOCALES["en-US"]),p.COLUMN_DEFAULTS={radio:!1,checkbox:!1,checkboxEnabled:!0,field:void 0,title:void 0,titleTooltip:void 0,"class":void 0,align:void 0,halign:void 0,falign:void 0,valign:void 0,width:void 0,sortable:!1,order:"asc",visible:!0,switchable:!0,clickToSelect:!0,formatter:void 0,footerFormatter:void 0,events:void 0,sorter:void 0,sortName:void 0,cellStyle:void 0,searchable:!0,searchFormatter:!0,cardVisible:!0},p.EVENTS={"all.bs.table":"onAll","click-cell.bs.table":"onClickCell","dbl-click-cell.bs.table":"onDblClickCell","click-row.bs.table":"onClickRow","dbl-click-row.bs.table":"onDblClickRow","sort.bs.table":"onSort","check.bs.table":"onCheck","uncheck.bs.table":"onUncheck","check-all.bs.table":"onCheckAll","uncheck-all.bs.table":"onUncheckAll","check-some.bs.table":"onCheckSome","uncheck-some.bs.table":"onUncheckSome","load-success.bs.table":"onLoadSuccess","load-error.bs.table":"onLoadError","column-switch.bs.table":"onColumnSwitch","page-change.bs.table":"onPageChange","search.bs.table":"onSearch","toggle.bs.table":"onToggle","pre-body.bs.table":"onPreBody","post-body.bs.table":"onPostBody","post-header.bs.table":"onPostHeader","expand-row.bs.table":"onExpandRow","collapse-row.bs.table":"onCollapseRow","refresh-options.bs.table":"onRefreshOptions","reset-view.bs.table":"onResetView","refresh.bs.table":"onRefresh"},p.prototype.init=function(){this.initLocale(),this.initContainer(),this.initTable(),this.initHeader(),this.initData(),this.initFooter(),this.initToolbar(),this.initPagination(),this.initBody(),this.initSearchText(),this.initServer()},p.prototype.initLocale=function(){if(this.options.locale){var b=this.options.locale.split(/-|_/);b[0].toLowerCase(),b[1]&&b[1].toUpperCase(),a.fn.bootstrapTable.locales[this.options.locale]?a.extend(this.options,a.fn.bootstrapTable.locales[this.options.locale]):a.fn.bootstrapTable.locales[b.join("-")]?a.extend(this.options,a.fn.bootstrapTable.locales[b.join("-")]):a.fn.bootstrapTable.locales[b[0]]&&a.extend(this.options,a.fn.bootstrapTable.locales[b[0]])}},p.prototype.initContainer=function(){this.$container=a(['<div class="bootstrap-table">','<div class="fixed-table-toolbar"></div>',"top"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?'<div class="fixed-table-pagination" style="clear: both;"></div>':"",'<div class="fixed-table-container">','<div class="fixed-table-header"><table></table></div>','<div class="fixed-table-body">','<div class="fixed-table-loading">',this.options.formatLoadingMessage(),"</div>","</div>",'<div class="fixed-table-footer"><table><tr></tr></table></div>',"bottom"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?'<div class="fixed-table-pagination"></div>':"","</div>","</div>"].join("")),this.$container.insertAfter(this.$el),this.$tableContainer=this.$container.find(".fixed-table-container"),this.$tableHeader=this.$container.find(".fixed-table-header"),this.$tableBody=this.$container.find(".fixed-table-body"),this.$tableLoading=this.$container.find(".fixed-table-loading"),this.$tableFooter=this.$container.find(".fixed-table-footer"),this.$toolbar=this.$container.find(".fixed-table-toolbar"),this.$pagination=this.$container.find(".fixed-table-pagination"),this.$tableBody.append(this.$el),this.$container.after('<div class="clearfix"></div>'),this.$el.addClass(this.options.classes),this.options.striped&&this.$el.addClass("table-striped"),-1!==a.inArray("table-no-bordered",this.options.classes.split(" "))&&this.$tableContainer.addClass("table-no-bordered")},p.prototype.initTable=function(){var b=this,c=[],d=[];if(this.$header=this.$el.find(">thead"),this.$header.length||(this.$header=a("<thead></thead>").appendTo(this.$el)),this.$header.find("tr").each(function(){var b=[];a(this).find("th").each(function(){"undefined"!=typeof a(this).data("field")&&a(this).data("field",a(this).data("field")+""),b.push(a.extend({},{title:a(this).html(),"class":a(this).attr("class"),titleTooltip:a(this).attr("title"),rowspan:a(this).attr("rowspan")?+a(this).attr("rowspan"):void 0,colspan:a(this).attr("colspan")?+a(this).attr("colspan"):void 0},a(this).data()))}),c.push(b)}),a.isArray(this.options.columns[0])||(this.options.columns=[this.options.columns]),this.options.columns=a.extend(!0,[],c,this.options.columns),this.columns=[],f(this.options.columns),a.each(this.options.columns,function(c,d){a.each(d,function(d,e){e=a.extend({},p.COLUMN_DEFAULTS,e),"undefined"!=typeof e.fieldIndex&&(b.columns[e.fieldIndex]=e),b.options.columns[c][d]=e})}),!this.options.data.length){var e=[];this.$el.find(">tbody>tr").each(function(c){var f={};f._id=a(this).attr("id"),f._class=a(this).attr("class"),f._data=l(a(this).data()),a(this).find(">td").each(function(d){for(var g,h,i=a(this),j=+i.attr("colspan")||1,k=+i.attr("rowspan")||1;e[c]&&e[c][d];d++);for(g=d;d+j>g;g++)for(h=c;c+k>h;h++)e[h]||(e[h]=[]),e[h][g]=!0;var m=b.columns[d].field;f[m]=a(this).html(),f["_"+m+"_id"]=a(this).attr("id"),f["_"+m+"_class"]=a(this).attr("class"),f["_"+m+"_rowspan"]=a(this).attr("rowspan"),f["_"+m+"_colspan"]=a(this).attr("colspan"),f["_"+m+"_title"]=a(this).attr("title"),f["_"+m+"_data"]=l(a(this).data())}),d.push(f)}),this.options.data=d,d.length&&(this.fromHtml=!0)}},p.prototype.initHeader=function(){var b=this,d={},e=[];this.header={fields:[],styles:[],classes:[],formatters:[],events:[],sorters:[],sortNames:[],cellStyles:[],searchables:[]},a.each(this.options.columns,function(f,g){e.push("<tr>"),0===f&&!b.options.cardView&&b.options.detailView&&e.push(c('<th class="detail" rowspan="%s"><div class="fht-cell"></div></th>',b.options.columns.length)),a.each(g,function(a,f){var g="",h="",i="",j="",k=c(' class="%s"',f["class"]),l=(b.options.sortOrder||f.order,"px"),m=f.width;if(void 0===f.width||b.options.cardView||"string"==typeof f.width&&-1!==f.width.indexOf("%")&&(l="%"),f.width&&"string"==typeof f.width&&(m=f.width.replace("%","").replace("px","")),h=c("text-align: %s; ",f.halign?f.halign:f.align),i=c("text-align: %s; ",f.align),j=c("vertical-align: %s; ",f.valign),j+=c("width: %s; ",!f.checkbox&&!f.radio||m?m?m+l:void 0:"36px"),"undefined"!=typeof f.fieldIndex){if(b.header.fields[f.fieldIndex]=f.field,b.header.styles[f.fieldIndex]=i+j,b.header.classes[f.fieldIndex]=k,b.header.formatters[f.fieldIndex]=f.formatter,b.header.events[f.fieldIndex]=f.events,b.header.sorters[f.fieldIndex]=f.sorter,b.header.sortNames[f.fieldIndex]=f.sortName,b.header.cellStyles[f.fieldIndex]=f.cellStyle,b.header.searchables[f.fieldIndex]=f.searchable,!f.visible)return;if(b.options.cardView&&!f.cardVisible)return;d[f.field]=f}e.push("<th"+c(' title="%s"',f.titleTooltip),f.checkbox||f.radio?c(' class="bs-checkbox %s"',f["class"]||""):k,c(' style="%s"',h+j),c(' rowspan="%s"',f.rowspan),c(' colspan="%s"',f.colspan),c(' data-field="%s"',f.field),"tabindex='0'",">"),e.push(c('<div class="th-inner %s">',b.options.sortable&&f.sortable?"sortable both":"")),g=f.title,f.checkbox&&(!b.options.singleSelect&&b.options.checkboxHeader&&(g='<input name="btSelectAll" type="checkbox" />'),b.header.stateField=f.field),f.radio&&(g="",b.header.stateField=f.field,b.options.singleSelect=!0),e.push(g),e.push("</div>"),e.push('<div class="fht-cell"></div>'),e.push("</div>"),e.push("</th>")}),e.push("</tr>")}),this.$header.html(e.join("")),this.$header.find("th[data-field]").each(function(){a(this).data(d[a(this).data("field")])}),this.$container.off("click",".th-inner").on("click",".th-inner",function(c){var d=a(this);return b.options.detailView&&d.closest(".bootstrap-table")[0]!==b.$container[0]?!1:void(b.options.sortable&&d.parent().data().sortable&&b.onSort(c))}),this.$header.children().children().off("keypress").on("keypress",function(c){if(b.options.sortable&&a(this).data().sortable){var d=c.keyCode||c.which;13==d&&b.onSort(c)}}),a(window).off("resize.bootstrap-table"),!this.options.showHeader||this.options.cardView?(this.$header.hide(),this.$tableHeader.hide(),this.$tableLoading.css("top",0)):(this.$header.show(),this.$tableHeader.show(),this.$tableLoading.css("top",this.$header.outerHeight()+1),this.getCaret(),a(window).on("resize.bootstrap-table",a.proxy(this.resetWidth,this))),this.$selectAll=this.$header.find('[name="btSelectAll"]'),this.$selectAll.off("click").on("click",function(){var c=a(this).prop("checked");b[c?"checkAll":"uncheckAll"](),b.updateSelected()})},p.prototype.initFooter=function(){!this.options.showFooter||this.options.cardView?this.$tableFooter.hide():this.$tableFooter.show()},p.prototype.initData=function(a,b){this.data="append"===b?this.data.concat(a):"prepend"===b?[].concat(a).concat(this.data):a||this.options.data,this.options.data="append"===b?this.options.data.concat(a):"prepend"===b?[].concat(a).concat(this.options.data):this.data,"server"!==this.options.sidePagination&&this.initSort()},p.prototype.initSort=function(){var b=this,c=this.options.sortName,d="desc"===this.options.sortOrder?-1:1,e=a.inArray(this.options.sortName,this.header.fields);return this.options.customSort!==a.noop?void this.options.customSort.apply(this,[this.options.sortName,this.options.sortOrder]):void(-1!==e&&(this.options.sortStable&&a.each(this.data,function(a,b){b.hasOwnProperty("_position")||(b._position=a)}),this.data.sort(function(f,g){b.header.sortNames[e]&&(c=b.header.sortNames[e]);var i=m(f,c,b.options.escape),j=m(g,c,b.options.escape),k=h(b.header,b.header.sorters[e],[i,j]);return void 0!==k?d*k:((void 0===i||null===i)&&(i=""),(void 0===j||null===j)&&(j=""),b.options.sortStable&&i===j&&(i=f._position,j=g._position),a.isNumeric(i)&&a.isNumeric(j)?(i=parseFloat(i),j=parseFloat(j),j>i?-1*d:d):i===j?0:("string"!=typeof i&&(i=i.toString()),-1===i.localeCompare(j)?-1*d:d))})))},p.prototype.onSort=function(b){var c="keypress"===b.type?a(b.currentTarget):a(b.currentTarget).parent(),d=this.$header.find("th").eq(c.index());return this.$header.add(this.$header_).find("span.order").remove(),this.options.sortName===c.data("field")?this.options.sortOrder="asc"===this.options.sortOrder?"desc":"asc":(this.options.sortName=c.data("field"),this.options.sortOrder="asc"===c.data("order")?"desc":"asc"),this.trigger("sort",this.options.sortName,this.options.sortOrder),c.add(d).data("order",this.options.sortOrder),this.getCaret(),"server"===this.options.sidePagination?void this.initServer(this.options.silentSort):(this.initSort(),void this.initBody())},p.prototype.initToolbar=function(){var b,d,e=this,f=[],g=0,i=0;this.$toolbar.find(".bs-bars").children().length&&a("body").append(a(this.options.toolbar)),this.$toolbar.html(""),("string"==typeof this.options.toolbar||"object"==typeof this.options.toolbar)&&a(c('<div class="bs-bars pull-%s"></div>',this.options.toolbarAlign)).appendTo(this.$toolbar).append(a(this.options.toolbar)),f=[c('<div class="columns columns-%s btn-group pull-%s">',this.options.buttonsAlign,this.options.buttonsAlign)],"string"==typeof this.options.icons&&(this.options.icons=h(null,this.options.icons)),this.options.showPaginationSwitch&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="paginationSwitch" title="%s">',this.options.formatPaginationSwitch()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.paginationSwitchDown),"</button>"),this.options.showRefresh&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="refresh" title="%s">',this.options.formatRefresh()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.refresh),"</button>"),this.options.showToggle&&f.push(c('<button class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+'" type="button" name="toggle" title="%s">',this.options.formatToggle()),c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.toggle),"</button>"),this.options.showColumns&&(f.push(c('<div class="keep-open btn-group" title="%s">',this.options.formatColumns()),'<button type="button" class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+' dropdown-toggle" data-toggle="dropdown">',c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.columns),' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">'),a.each(this.columns,function(a,b){if(!(b.radio||b.checkbox||e.options.cardView&&!b.cardVisible)){var d=b.visible?' checked="checked"':"";b.switchable&&(f.push(c('<li><label><input type="checkbox" data-field="%s" value="%s"%s> %s</label></li>',b.field,a,d,b.title)),i++)}}),f.push("</ul>","</div>")),f.push("</div>"),(this.showToolbar||f.length>2)&&this.$toolbar.append(f.join("")),this.options.showPaginationSwitch&&this.$toolbar.find('button[name="paginationSwitch"]').off("click").on("click",a.proxy(this.togglePagination,this)),this.options.showRefresh&&this.$toolbar.find('button[name="refresh"]').off("click").on("click",a.proxy(this.refresh,this)),this.options.showToggle&&this.$toolbar.find('button[name="toggle"]').off("click").on("click",function(){e.toggleView()}),this.options.showColumns&&(b=this.$toolbar.find(".keep-open"),i<=this.options.minimumCountColumns&&b.find("input").prop("disabled",!0),b.find("li").off("click").on("click",function(a){a.stopImmediatePropagation()}),b.find("input").off("click").on("click",function(){var b=a(this);e.toggleColumn(a(this).val(),b.prop("checked"),!1),e.trigger("column-switch",a(this).data("field"),b.prop("checked"))})),this.options.search&&(f=[],f.push('<div class="pull-'+this.options.searchAlign+' search">',c('<input class="form-control'+c(" input-%s",this.options.iconSize)+'" type="text" placeholder="%s">',this.options.formatSearch()),"</div>"),this.$toolbar.append(f.join("")),d=this.$toolbar.find(".search input"),d.off("keyup drop").on("keyup drop",function(b){e.options.searchOnEnterKey&&13!==b.keyCode||a.inArray(b.keyCode,[37,38,39,40])>-1||(clearTimeout(g),g=setTimeout(function(){e.onSearch(b)},e.options.searchTimeOut))}),n()&&d.off("mouseup").on("mouseup",function(a){clearTimeout(g),g=setTimeout(function(){e.onSearch(a)},e.options.searchTimeOut)}))},p.prototype.onSearch=function(b){var c=a.trim(a(b.currentTarget).val());this.options.trimOnSearch&&a(b.currentTarget).val()!==c&&a(b.currentTarget).val(c),c!==this.searchText&&(this.searchText=c,this.options.searchText=c,this.options.pageNumber=1,this.initSearch(),this.updatePagination(),this.trigger("search",c))},p.prototype.initSearch=function(){var b=this;if("server"!==this.options.sidePagination){if(this.options.customSearch!==a.noop)return void this.options.customSearch.apply(this,[this.searchText]);var c=this.searchText&&(this.options.escape?j(this.searchText):this.searchText).toLowerCase(),d=a.isEmptyObject(this.filterColumns)?null:this.filterColumns;this.data=d?a.grep(this.options.data,function(b){for(var c in d)if(a.isArray(d[c])&&-1===a.inArray(b[c],d[c])||b[c]!==d[c])return!1;return!0}):this.options.data,this.data=c?a.grep(this.data,function(d,f){for(var g=0;g<b.header.fields.length;g++)if(b.header.searchables[g]){var i,j=a.isNumeric(b.header.fields[g])?parseInt(b.header.fields[g],10):b.header.fields[g],k=b.columns[e(b.columns,j)];if("string"==typeof j){i=d;for(var l=j.split("."),m=0;m<l.length;m++)i=i[l[m]];k&&k.searchFormatter&&(i=h(k,b.header.formatters[g],[i,d,f],i))}else i=d[j];if("string"==typeof i||"number"==typeof i)if(b.options.strictSearch){if((i+"").toLowerCase()===c)return!0}else if(-1!==(i+"").toLowerCase().indexOf(c))return!0}return!1}):this.data}},p.prototype.initPagination=function(){if(!this.options.pagination)return void this.$pagination.hide();this.$pagination.show();var b,d,e,f,g,h,i,j,k,l=this,m=[],n=!1,o=this.getData(),p=this.options.pageList;if("server"!==this.options.sidePagination&&(this.options.totalRows=o.length),this.totalPages=0,this.options.totalRows){if(this.options.pageSize===this.options.formatAllRows())this.options.pageSize=this.options.totalRows,n=!0;else if(this.options.pageSize===this.options.totalRows){var q="string"==typeof this.options.pageList?this.options.pageList.replace("[","").replace("]","").replace(/ /g,"").toLowerCase().split(","):this.options.pageList;a.inArray(this.options.formatAllRows().toLowerCase(),q)>-1&&(n=!0)}this.totalPages=~~((this.options.totalRows-1)/this.options.pageSize)+1,this.options.totalPages=this.totalPages}if(this.totalPages>0&&this.options.pageNumber>this.totalPages&&(this.options.pageNumber=this.totalPages),this.pageFrom=(this.options.pageNumber-1)*this.options.pageSize+1,this.pageTo=this.options.pageNumber*this.options.pageSize,this.pageTo>this.options.totalRows&&(this.pageTo=this.options.totalRows),m.push('<div class="pull-'+this.options.paginationDetailHAlign+' pagination-detail">','<span class="pagination-info">',this.options.onlyInfoPagination?this.options.formatDetailPagination(this.options.totalRows):this.options.formatShowingRows(this.pageFrom,this.pageTo,this.options.totalRows),"</span>"),!this.options.onlyInfoPagination){m.push('<span class="page-list">');var r=[c('<span class="btn-group %s">',"top"===this.options.paginationVAlign||"both"===this.options.paginationVAlign?"dropdown":"dropup"),'<button type="button" class="btn'+c(" btn-%s",this.options.buttonsClass)+c(" btn-%s",this.options.iconSize)+' dropdown-toggle" data-toggle="dropdown">','<span class="page-size">',n?this.options.formatAllRows():this.options.pageSize,"</span>",' <span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">'];if("string"==typeof this.options.pageList){var s=this.options.pageList.replace("[","").replace("]","").replace(/ /g,"").split(",");p=[],a.each(s,function(a,b){p.push(b.toUpperCase()===l.options.formatAllRows().toUpperCase()?l.options.formatAllRows():+b)})}for(a.each(p,function(a,b){if(!l.options.smartDisplay||0===a||p[a-1]<=l.options.totalRows){var d;d=n?b===l.options.formatAllRows()?' class="active"':"":b===l.options.pageSize?' class="active"':"",r.push(c('<li%s><a href="javascript:void(0)">%s</a></li>',d,b))}}),r.push("</ul></span>"),m.push(this.options.formatRecordsPerPage(r.join(""))),m.push("</span>"),m.push("</div>",'<div class="pull-'+this.options.paginationHAlign+' pagination">','<ul class="pagination'+c(" pagination-%s",this.options.iconSize)+'">','<li class="page-pre"><a href="javascript:void(0)">'+this.options.paginationPreText+"</a></li>"),this.totalPages<5?(d=1,e=this.totalPages):(d=this.options.pageNumber-2,e=d+4,1>d&&(d=1,e=5),e>this.totalPages&&(e=this.totalPages,d=e-4)),this.totalPages>=6&&(this.options.pageNumber>=3&&(m.push('<li class="page-first'+(1===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',1,"</a>","</li>"),d++),this.options.pageNumber>=4&&(4==this.options.pageNumber||6==this.totalPages||7==this.totalPages?d--:m.push('<li class="page-first-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),e--)),this.totalPages>=7&&this.options.pageNumber>=this.totalPages-2&&d--,6==this.totalPages?this.options.pageNumber>=this.totalPages-2&&e++:this.totalPages>=7&&(7==this.totalPages||this.options.pageNumber>=this.totalPages-3)&&e++,b=d;e>=b;b++)m.push('<li class="page-number'+(b===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',b,"</a>","</li>");this.totalPages>=8&&this.options.pageNumber<=this.totalPages-4&&m.push('<li class="page-last-separator disabled">','<a href="javascript:void(0)">...</a>',"</li>"),this.totalPages>=6&&this.options.pageNumber<=this.totalPages-3&&m.push('<li class="page-last'+(this.totalPages===this.options.pageNumber?" active":"")+'">','<a href="javascript:void(0)">',this.totalPages,"</a>","</li>"),m.push('<li class="page-next"><a href="javascript:void(0)">'+this.options.paginationNextText+"</a></li>","</ul>","</div>")}this.$pagination.html(m.join("")),this.options.onlyInfoPagination||(f=this.$pagination.find(".page-list a"),g=this.$pagination.find(".page-first"),h=this.$pagination.find(".page-pre"),i=this.$pagination.find(".page-next"),j=this.$pagination.find(".page-last"),k=this.$pagination.find(".page-number"),this.options.smartDisplay&&(this.totalPages<=1&&this.$pagination.find("div.pagination").hide(),(p.length<2||this.options.totalRows<=p[0])&&this.$pagination.find("span.page-list").hide(),this.$pagination[this.getData().length?"show":"hide"]()),n&&(this.options.pageSize=this.options.formatAllRows()),f.off("click").on("click",a.proxy(this.onPageListChange,this)),g.off("click").on("click",a.proxy(this.onPageFirst,this)),h.off("click").on("click",a.proxy(this.onPagePre,this)),i.off("click").on("click",a.proxy(this.onPageNext,this)),j.off("click").on("click",a.proxy(this.onPageLast,this)),k.off("click").on("click",a.proxy(this.onPageNumber,this)))},p.prototype.updatePagination=function(b){b&&a(b.currentTarget).hasClass("disabled")||(this.options.maintainSelected||this.resetRows(),this.initPagination(),"server"===this.options.sidePagination?this.initServer():this.initBody(),this.trigger("page-change",this.options.pageNumber,this.options.pageSize))},p.prototype.onPageListChange=function(b){var c=a(b.currentTarget);c.parent().addClass("active").siblings().removeClass("active"),this.options.pageSize=c.text().toUpperCase()===this.options.formatAllRows().toUpperCase()?this.options.formatAllRows():+c.text(),this.$toolbar.find(".page-size").text(this.options.pageSize),this.updatePagination(b)},p.prototype.onPageFirst=function(a){this.options.pageNumber=1,this.updatePagination(a)},p.prototype.onPagePre=function(a){this.options.pageNumber-1===0?this.options.pageNumber=this.options.totalPages:this.options.pageNumber--,this.updatePagination(a)},p.prototype.onPageNext=function(a){this.options.pageNumber+1>this.options.totalPages?this.options.pageNumber=1:this.options.pageNumber++,this.updatePagination(a)},p.prototype.onPageLast=function(a){this.options.pageNumber=this.totalPages,this.updatePagination(a)},p.prototype.onPageNumber=function(b){this.options.pageNumber!==+a(b.currentTarget).text()&&(this.options.pageNumber=+a(b.currentTarget).text(),this.updatePagination(b))},p.prototype.initBody=function(b){var f=this,g=[],i=this.getData();this.trigger("pre-body",i),this.$body=this.$el.find(">tbody"),this.$body.length||(this.$body=a("<tbody></tbody>").appendTo(this.$el)),this.options.pagination&&"server"!==this.options.sidePagination||(this.pageFrom=1,this.pageTo=i.length);for(var k=this.pageFrom-1;k<this.pageTo;k++){var l,n=i[k],o={},p=[],q="",r={},s=[];if(o=h(this.options,this.options.rowStyle,[n,k],o),o&&o.css)for(l in o.css)p.push(l+": "+o.css[l]);if(r=h(this.options,this.options.rowAttributes,[n,k],r))for(l in r)s.push(c('%s="%s"',l,j(r[l])));n._data&&!a.isEmptyObject(n._data)&&a.each(n._data,function(a,b){"index"!==a&&(q+=c(' data-%s="%s"',a,b))}),g.push("<tr",c(" %s",s.join(" ")),c(' id="%s"',a.isArray(n)?void 0:n._id),c(' class="%s"',o.classes||(a.isArray(n)?void 0:n._class)),c(' data-index="%s"',k),c(' data-uniqueid="%s"',n[this.options.uniqueId]),c("%s",q),">"),this.options.cardView&&g.push(c('<td colspan="%s"><div class="card-views">',this.header.fields.length)),!this.options.cardView&&this.options.detailView&&g.push("<td>",'<a class="detail-icon" href="javascript:">',c('<i class="%s %s"></i>',this.options.iconsPrefix,this.options.icons.detailOpen),"</a>","</td>"),a.each(this.header.fields,function(b,e){var i="",j=m(n,e,f.options.escape),l="",q={},r="",s=f.header.classes[b],t="",u="",v="",w="",x=f.columns[b];if(!(f.fromHtml&&"undefined"==typeof j||!x.visible||f.options.cardView&&!x.cardVisible)){if(o=c('style="%s"',p.concat(f.header.styles[b]).join("; ")),n["_"+e+"_id"]&&(r=c(' id="%s"',n["_"+e+"_id"])),n["_"+e+"_class"]&&(s=c(' class="%s"',n["_"+e+"_class"])),n["_"+e+"_rowspan"]&&(u=c(' rowspan="%s"',n["_"+e+"_rowspan"])),n["_"+e+"_colspan"]&&(v=c(' colspan="%s"',n["_"+e+"_colspan"])),n["_"+e+"_title"]&&(w=c(' title="%s"',n["_"+e+"_title"])),q=h(f.header,f.header.cellStyles[b],[j,n,k,e],q),q.classes&&(s=c(' class="%s"',q.classes)),q.css){var y=[];for(var z in q.css)y.push(z+": "+q.css[z]);o=c('style="%s"',y.concat(f.header.styles[b]).join("; "))}j=h(x,f.header.formatters[b],[j,n,k],j),n["_"+e+"_data"]&&!a.isEmptyObject(n["_"+e+"_data"])&&a.each(n["_"+e+"_data"],function(a,b){"index"!==a&&(t+=c(' data-%s="%s"',a,b))}),x.checkbox||x.radio?(l=x.checkbox?"checkbox":l,l=x.radio?"radio":l,i=[c(f.options.cardView?'<div class="card-view %s">':'<td class="bs-checkbox %s">',x["class"]||""),"<input"+c(' data-index="%s"',k)+c(' name="%s"',f.options.selectItemName)+c(' type="%s"',l)+c(' value="%s"',n[f.options.idField])+c(' checked="%s"',j===!0||j&&j.checked?"checked":void 0)+c(' disabled="%s"',!x.checkboxEnabled||j&&j.disabled?"disabled":void 0)+" />",f.header.formatters[b]&&"string"==typeof j?j:"",f.options.cardView?"</div>":"</td>"].join(""),n[f.header.stateField]=j===!0||j&&j.checked):(j="undefined"==typeof j||null===j?f.options.undefinedText:j,i=f.options.cardView?['<div class="card-view">',f.options.showHeader?c('<span class="title" %s>%s</span>',o,d(f.columns,"field","title",e)):"",c('<span class="value">%s</span>',j),"</div>"].join(""):[c("<td%s %s %s %s %s %s %s>",r,s,o,t,u,v,w),j,"</td>"].join(""),f.options.cardView&&f.options.smartDisplay&&""===j&&(i='<div class="card-view"></div>')),g.push(i)}}),this.options.cardView&&g.push("</div></td>"),g.push("</tr>")}g.length||g.push('<tr class="no-records-found">',c('<td colspan="%s">%s</td>',this.$header.find("th").length,this.options.formatNoMatches()),"</tr>"),this.$body.html(g.join("")),b||this.scrollTo(0),this.$body.find("> tr[data-index] > td").off("click dblclick").on("click dblclick",function(b){var d=a(this),g=d.parent(),h=f.data[g.data("index")],i=d[0].cellIndex,j=f.getVisibleFields(),k=j[f.options.detailView&&!f.options.cardView?i-1:i],l=f.columns[e(f.columns,k)],n=m(h,k,f.options.escape);if(!d.find(".detail-icon").length&&(f.trigger("click"===b.type?"click-cell":"dbl-click-cell",k,n,h,d),f.trigger("click"===b.type?"click-row":"dbl-click-row",h,g,k), +"click"===b.type&&f.options.clickToSelect&&l.clickToSelect)){var o=g.find(c('[name="%s"]',f.options.selectItemName));o.length&&o[0].click()}}),this.$body.find("> tr[data-index] > td > .detail-icon").off("click").on("click",function(){var b=a(this),d=b.parent().parent(),e=d.data("index"),g=i[e];if(d.next().is("tr.detail-view"))b.find("i").attr("class",c("%s %s",f.options.iconsPrefix,f.options.icons.detailOpen)),d.next().remove(),f.trigger("collapse-row",e,g);else{b.find("i").attr("class",c("%s %s",f.options.iconsPrefix,f.options.icons.detailClose)),d.after(c('<tr class="detail-view"><td colspan="%s"></td></tr>',d.find("td").length));var j=d.next().find("td"),k=h(f.options,f.options.detailFormatter,[e,g,j],"");1===j.length&&j.append(k),f.trigger("expand-row",e,g,j)}f.resetView()}),this.$selectItem=this.$body.find(c('[name="%s"]',this.options.selectItemName)),this.$selectItem.off("click").on("click",function(b){b.stopImmediatePropagation();var c=a(this),d=c.prop("checked"),e=f.data[c.data("index")];f.options.maintainSelected&&a(this).is(":radio")&&a.each(f.options.data,function(a,b){b[f.header.stateField]=!1}),e[f.header.stateField]=d,f.options.singleSelect&&(f.$selectItem.not(this).each(function(){f.data[a(this).data("index")][f.header.stateField]=!1}),f.$selectItem.filter(":checked").not(this).prop("checked",!1)),f.updateSelected(),f.trigger(d?"check":"uncheck",e,c)}),a.each(this.header.events,function(b,c){if(c){"string"==typeof c&&(c=h(null,c));var d=f.header.fields[b],e=a.inArray(d,f.getVisibleFields());f.options.detailView&&!f.options.cardView&&(e+=1);for(var g in c)f.$body.find(">tr:not(.no-records-found)").each(function(){var b=a(this),h=b.find(f.options.cardView?".card-view":"td").eq(e),i=g.indexOf(" "),j=g.substring(0,i),k=g.substring(i+1),l=c[g];h.find(k).off(j).on(j,function(a){var c=b.data("index"),e=f.data[c],g=e[d];l.apply(this,[a,g,e,c])})})}}),this.updateSelected(),this.resetView(),this.trigger("post-body",i)},p.prototype.initServer=function(b,c,d){var e,f=this,g={},i={searchText:this.searchText,sortName:this.options.sortName,sortOrder:this.options.sortOrder};this.options.pagination&&(i.pageSize=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize,i.pageNumber=this.options.pageNumber),(d||this.options.url||this.options.ajax)&&("limit"===this.options.queryParamsType&&(i={search:i.searchText,sort:i.sortName,order:i.sortOrder},this.options.pagination&&(i.offset=this.options.pageSize===this.options.formatAllRows()?0:this.options.pageSize*(this.options.pageNumber-1),i.limit=this.options.pageSize===this.options.formatAllRows()?this.options.totalRows:this.options.pageSize)),a.isEmptyObject(this.filterColumnsPartial)||(i.filter=JSON.stringify(this.filterColumnsPartial,null)),g=h(this.options,this.options.queryParams,[i],g),a.extend(g,c||{}),g!==!1&&(b||this.$tableLoading.show(),e=a.extend({},h(null,this.options.ajaxOptions),{type:this.options.method,url:d||this.options.url,data:"application/json"===this.options.contentType&&"post"===this.options.method?JSON.stringify(g):g,cache:this.options.cache,contentType:this.options.contentType,dataType:this.options.dataType,success:function(a){a=h(f.options,f.options.responseHandler,[a],a),f.load(a),f.trigger("load-success",a),b||f.$tableLoading.hide()},error:function(a){f.trigger("load-error",a.status,a),b||f.$tableLoading.hide()}}),this.options.ajax?h(this,this.options.ajax,[e],null):(this._xhr&&4!==this._xhr.readyState&&this._xhr.abort(),this._xhr=a.ajax(e))))},p.prototype.initSearchText=function(){if(this.options.search&&""!==this.options.searchText){var a=this.$toolbar.find(".search input");a.val(this.options.searchText),this.onSearch({currentTarget:a})}},p.prototype.getCaret=function(){var b=this;a.each(this.$header.find("th"),function(c,d){a(d).find(".sortable").removeClass("desc asc").addClass(a(d).data("field")===b.options.sortName?b.options.sortOrder:"both")})},p.prototype.updateSelected=function(){var b=this.$selectItem.filter(":enabled").length&&this.$selectItem.filter(":enabled").length===this.$selectItem.filter(":enabled").filter(":checked").length;this.$selectAll.add(this.$selectAll_).prop("checked",b),this.$selectItem.each(function(){a(this).closest("tr")[a(this).prop("checked")?"addClass":"removeClass"]("selected")})},p.prototype.updateRows=function(){var b=this;this.$selectItem.each(function(){b.data[a(this).data("index")][b.header.stateField]=a(this).prop("checked")})},p.prototype.resetRows=function(){var b=this;a.each(this.data,function(a,c){b.$selectAll.prop("checked",!1),b.$selectItem.prop("checked",!1),b.header.stateField&&(c[b.header.stateField]=!1)})},p.prototype.trigger=function(b){var c=Array.prototype.slice.call(arguments,1);b+=".bs.table",this.options[p.EVENTS[b]].apply(this.options,c),this.$el.trigger(a.Event(b),c),this.options.onAll(b,c),this.$el.trigger(a.Event("all.bs.table"),[b,c])},p.prototype.resetHeader=function(){clearTimeout(this.timeoutId_),this.timeoutId_=setTimeout(a.proxy(this.fitHeader,this),this.$el.is(":hidden")?100:0)},p.prototype.fitHeader=function(){var b,d,e,f,h=this;if(h.$el.is(":hidden"))return void(h.timeoutId_=setTimeout(a.proxy(h.fitHeader,h),100));if(b=this.$tableBody.get(0),d=b.scrollWidth>b.clientWidth&&b.scrollHeight>b.clientHeight+this.$header.outerHeight()?g():0,this.$el.css("margin-top",-this.$header.outerHeight()),e=a(":focus"),e.length>0){var i=e.parents("th");if(i.length>0){var j=i.attr("data-field");if(void 0!==j){var k=this.$header.find("[data-field='"+j+"']");k.length>0&&k.find(":input").addClass("focus-temp")}}}this.$header_=this.$header.clone(!0,!0),this.$selectAll_=this.$header_.find('[name="btSelectAll"]'),this.$tableHeader.css({"margin-right":d}).find("table").css("width",this.$el.outerWidth()).html("").attr("class",this.$el.attr("class")).append(this.$header_),f=a(".focus-temp:visible:eq(0)"),f.length>0&&(f.focus(),this.$header.find(".focus-temp").removeClass("focus-temp")),this.$header.find("th[data-field]").each(function(){h.$header_.find(c('th[data-field="%s"]',a(this).data("field"))).data(a(this).data())});var l=this.getVisibleFields(),m=this.$header_.find("th");this.$body.find(">tr:first-child:not(.no-records-found) > *").each(function(b){var d=a(this),e=b;h.options.detailView&&!h.options.cardView&&(0===b&&h.$header_.find("th.detail").find(".fht-cell").width(d.innerWidth()),e=b-1);var f=h.$header_.find(c('th[data-field="%s"]',l[e]));f.length>1&&(f=a(m[d[0].cellIndex])),f.find(".fht-cell").width(d.innerWidth())}),this.$tableBody.off("scroll").on("scroll",function(){h.$tableHeader.scrollLeft(a(this).scrollLeft()),h.options.showFooter&&!h.options.cardView&&h.$tableFooter.scrollLeft(a(this).scrollLeft())}),h.trigger("post-header")},p.prototype.resetFooter=function(){var b=this,d=b.getData(),e=[];this.options.showFooter&&!this.options.cardView&&(!this.options.cardView&&this.options.detailView&&e.push('<td><div class="th-inner"> </div><div class="fht-cell"></div></td>'),a.each(this.columns,function(a,f){var g,i="",j="",k=[],l={},m=c(' class="%s"',f["class"]);if(f.visible&&(!b.options.cardView||f.cardVisible)){if(i=c("text-align: %s; ",f.falign?f.falign:f.align),j=c("vertical-align: %s; ",f.valign),l=h(null,b.options.footerStyle),l&&l.css)for(g in l.css)k.push(g+": "+l.css[g]);e.push("<td",m,c(' style="%s"',i+j+k.concat().join("; ")),">"),e.push('<div class="th-inner">'),e.push(h(f,f.footerFormatter,[d]," ")||" "),e.push("</div>"),e.push('<div class="fht-cell"></div>'),e.push("</div>"),e.push("</td>")}}),this.$tableFooter.find("tr").html(e.join("")),this.$tableFooter.show(),clearTimeout(this.timeoutFooter_),this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),this.$el.is(":hidden")?100:0))},p.prototype.fitFooter=function(){var b,c,d;return clearTimeout(this.timeoutFooter_),this.$el.is(":hidden")?void(this.timeoutFooter_=setTimeout(a.proxy(this.fitFooter,this),100)):(c=this.$el.css("width"),d=c>this.$tableBody.width()?g():0,this.$tableFooter.css({"margin-right":d}).find("table").css("width",c).attr("class",this.$el.attr("class")),b=this.$tableFooter.find("td"),void this.$body.find(">tr:first-child:not(.no-records-found) > *").each(function(c){var d=a(this);b.eq(c).find(".fht-cell").width(d.innerWidth())}))},p.prototype.toggleColumn=function(a,b,d){if(-1!==a&&(this.columns[a].visible=b,this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns)){var e=this.$toolbar.find(".keep-open input").prop("disabled",!1);d&&e.filter(c('[value="%s"]',a)).prop("checked",b),e.filter(":checked").length<=this.options.minimumCountColumns&&e.filter(":checked").prop("disabled",!0)}},p.prototype.toggleRow=function(a,b,d){-1!==a&&this.$body.find("undefined"!=typeof a?c('tr[data-index="%s"]',a):c('tr[data-uniqueid="%s"]',b))[d?"show":"hide"]()},p.prototype.getVisibleFields=function(){var b=this,c=[];return a.each(this.header.fields,function(a,d){var f=b.columns[e(b.columns,d)];f.visible&&c.push(d)}),c},p.prototype.resetView=function(a){var b=0;if(a&&a.height&&(this.options.height=a.height),this.$selectAll.prop("checked",this.$selectItem.length>0&&this.$selectItem.length===this.$selectItem.filter(":checked").length),this.options.height){var c=k(this.$toolbar),d=k(this.$pagination),e=this.options.height-c-d;this.$tableContainer.css("height",e+"px")}return this.options.cardView?(this.$el.css("margin-top","0"),this.$tableContainer.css("padding-bottom","0"),void this.$tableFooter.hide()):(this.options.showHeader&&this.options.height?(this.$tableHeader.show(),this.resetHeader(),b+=this.$header.outerHeight()):(this.$tableHeader.hide(),this.trigger("post-header")),this.options.showFooter&&(this.resetFooter(),this.options.height&&(b+=this.$tableFooter.outerHeight()+1)),this.getCaret(),this.$tableContainer.css("padding-bottom",b+"px"),void this.trigger("reset-view"))},p.prototype.getData=function(b){return!this.searchText&&a.isEmptyObject(this.filterColumns)&&a.isEmptyObject(this.filterColumnsPartial)?b?this.options.data.slice(this.pageFrom-1,this.pageTo):this.options.data:b?this.data.slice(this.pageFrom-1,this.pageTo):this.data},p.prototype.load=function(b){var c=!1;"server"===this.options.sidePagination?(this.options.totalRows=b.total,c=b.fixedScroll,b=b[this.options.dataField]):a.isArray(b)||(c=b.fixedScroll,b=b.data),this.initData(b),this.initSearch(),this.initPagination(),this.initBody(c)},p.prototype.append=function(a){this.initData(a,"append"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},p.prototype.prepend=function(a){this.initData(a,"prepend"),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0)},p.prototype.remove=function(b){var c,d,e=this.options.data.length;if(b.hasOwnProperty("field")&&b.hasOwnProperty("values")){for(c=e-1;c>=0;c--)d=this.options.data[c],d.hasOwnProperty(b.field)&&-1!==a.inArray(d[b.field],b.values)&&this.options.data.splice(c,1);e!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))}},p.prototype.removeAll=function(){this.options.data.length>0&&(this.options.data.splice(0,this.options.data.length),this.initSearch(),this.initPagination(),this.initBody(!0))},p.prototype.getRowByUniqueId=function(a){var b,c,d,e=this.options.uniqueId,f=this.options.data.length,g=null;for(b=f-1;b>=0;b--){if(c=this.options.data[b],c.hasOwnProperty(e))d=c[e];else{if(!c._data.hasOwnProperty(e))continue;d=c._data[e]}if("string"==typeof d?a=a.toString():"number"==typeof d&&(Number(d)===d&&d%1===0?a=parseInt(a):d===Number(d)&&0!==d&&(a=parseFloat(a))),d===a){g=c;break}}return g},p.prototype.removeByUniqueId=function(a){var b=this.options.data.length,c=this.getRowByUniqueId(a);c&&this.options.data.splice(this.options.data.indexOf(c),1),b!==this.options.data.length&&(this.initSearch(),this.initPagination(),this.initBody(!0))},p.prototype.updateByUniqueId=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){var e;d.hasOwnProperty("id")&&d.hasOwnProperty("row")&&(e=a.inArray(c.getRowByUniqueId(d.id),c.options.data),-1!==e&&a.extend(c.options.data[e],d.row))}),this.initSearch(),this.initSort(),this.initBody(!0)},p.prototype.insertRow=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("row")&&(this.data.splice(a.index,0,a.row),this.initSearch(),this.initPagination(),this.initSort(),this.initBody(!0))},p.prototype.updateRow=function(b){var c=this,d=a.isArray(b)?b:[b];a.each(d,function(b,d){d.hasOwnProperty("index")&&d.hasOwnProperty("row")&&a.extend(c.options.data[d.index],d.row)}),this.initSearch(),this.initSort(),this.initBody(!0)},p.prototype.showRow=function(a){(a.hasOwnProperty("index")||a.hasOwnProperty("uniqueId"))&&this.toggleRow(a.index,a.uniqueId,!0)},p.prototype.hideRow=function(a){(a.hasOwnProperty("index")||a.hasOwnProperty("uniqueId"))&&this.toggleRow(a.index,a.uniqueId,!1)},p.prototype.getRowsHidden=function(b){var c=a(this.$body[0]).children().filter(":hidden"),d=0;if(b)for(;d<c.length;d++)a(c[d]).show();return c},p.prototype.mergeCells=function(b){var c,d,e,f=b.index,g=a.inArray(b.field,this.getVisibleFields()),h=b.rowspan||1,i=b.colspan||1,j=this.$body.find(">tr");if(this.options.detailView&&!this.options.cardView&&(g+=1),e=j.eq(f).find(">td").eq(g),!(0>f||0>g||f>=this.data.length)){for(c=f;f+h>c;c++)for(d=g;g+i>d;d++)j.eq(c).find(">td").eq(d).hide();e.attr("rowspan",h).attr("colspan",i).show()}},p.prototype.updateCell=function(a){a.hasOwnProperty("index")&&a.hasOwnProperty("field")&&a.hasOwnProperty("value")&&(this.data[a.index][a.field]=a.value,a.reinit!==!1&&(this.initSort(),this.initBody(!0)))},p.prototype.getOptions=function(){return this.options},p.prototype.getSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]})},p.prototype.getAllSelections=function(){var b=this;return a.grep(this.options.data,function(a){return a[b.header.stateField]})},p.prototype.checkAll=function(){this.checkAll_(!0)},p.prototype.uncheckAll=function(){this.checkAll_(!1)},p.prototype.checkInvert=function(){var b=this,c=b.$selectItem.filter(":enabled"),d=c.filter(":checked");c.each(function(){a(this).prop("checked",!a(this).prop("checked"))}),b.updateRows(),b.updateSelected(),b.trigger("uncheck-some",d),d=b.getSelections(),b.trigger("check-some",d)},p.prototype.checkAll_=function(a){var b;a||(b=this.getSelections()),this.$selectAll.add(this.$selectAll_).prop("checked",a),this.$selectItem.filter(":enabled").prop("checked",a),this.updateRows(),a&&(b=this.getSelections()),this.trigger(a?"check-all":"uncheck-all",b)},p.prototype.check=function(a){this.check_(!0,a)},p.prototype.uncheck=function(a){this.check_(!1,a)},p.prototype.check_=function(a,b){var d=this.$selectItem.filter(c('[data-index="%s"]',b)).prop("checked",a);this.data[b][this.header.stateField]=a,this.updateSelected(),this.trigger(a?"check":"uncheck",this.data[b],d)},p.prototype.checkBy=function(a){this.checkBy_(!0,a)},p.prototype.uncheckBy=function(a){this.checkBy_(!1,a)},p.prototype.checkBy_=function(b,d){if(d.hasOwnProperty("field")&&d.hasOwnProperty("values")){var e=this,f=[];a.each(this.options.data,function(g,h){if(!h.hasOwnProperty(d.field))return!1;if(-1!==a.inArray(h[d.field],d.values)){var i=e.$selectItem.filter(":enabled").filter(c('[data-index="%s"]',g)).prop("checked",b);h[e.header.stateField]=b,f.push(h),e.trigger(b?"check":"uncheck",h,i)}}),this.updateSelected(),this.trigger(b?"check-some":"uncheck-some",f)}},p.prototype.destroy=function(){this.$el.insertBefore(this.$container),a(this.options.toolbar).insertBefore(this.$el),this.$container.next().remove(),this.$container.remove(),this.$el.html(this.$el_.html()).css("margin-top","0").attr("class",this.$el_.attr("class")||"")},p.prototype.showLoading=function(){this.$tableLoading.show()},p.prototype.hideLoading=function(){this.$tableLoading.hide()},p.prototype.togglePagination=function(){this.options.pagination=!this.options.pagination;var a=this.$toolbar.find('button[name="paginationSwitch"] i');this.options.pagination?a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchDown):a.attr("class",this.options.iconsPrefix+" "+this.options.icons.paginationSwitchUp),this.updatePagination()},p.prototype.refresh=function(a){a&&a.url&&(this.options.pageNumber=1),this.initServer(a&&a.silent,a&&a.query,a&&a.url),this.trigger("refresh",a)},p.prototype.resetWidth=function(){this.options.showHeader&&this.options.height&&this.fitHeader(),this.options.showFooter&&this.fitFooter()},p.prototype.showColumn=function(a){this.toggleColumn(e(this.columns,a),!0,!0)},p.prototype.hideColumn=function(a){this.toggleColumn(e(this.columns,a),!1,!0)},p.prototype.getHiddenColumns=function(){return a.grep(this.columns,function(a){return!a.visible})},p.prototype.getVisibleColumns=function(){return a.grep(this.columns,function(a){return a.visible})},p.prototype.toggleAllColumns=function(b){if(a.each(this.columns,function(a){this.columns[a].visible=b}),this.initHeader(),this.initSearch(),this.initPagination(),this.initBody(),this.options.showColumns){var c=this.$toolbar.find(".keep-open input").prop("disabled",!1);c.filter(":checked").length<=this.options.minimumCountColumns&&c.filter(":checked").prop("disabled",!0)}},p.prototype.showAllColumns=function(){this.toggleAllColumns(!0)},p.prototype.hideAllColumns=function(){this.toggleAllColumns(!1)},p.prototype.filterBy=function(b){this.filterColumns=a.isEmptyObject(b)?{}:b,this.options.pageNumber=1,this.initSearch(),this.updatePagination()},p.prototype.scrollTo=function(a){return"string"==typeof a&&(a="bottom"===a?this.$tableBody[0].scrollHeight:0),"number"==typeof a&&this.$tableBody.scrollTop(a),"undefined"==typeof a?this.$tableBody.scrollTop():void 0},p.prototype.getScrollPosition=function(){return this.scrollTo()},p.prototype.selectPage=function(a){a>0&&a<=this.options.totalPages&&(this.options.pageNumber=a,this.updatePagination())},p.prototype.prevPage=function(){this.options.pageNumber>1&&(this.options.pageNumber--,this.updatePagination())},p.prototype.nextPage=function(){this.options.pageNumber<this.options.totalPages&&(this.options.pageNumber++,this.updatePagination())},p.prototype.toggleView=function(){this.options.cardView=!this.options.cardView,this.initHeader(),this.initBody(),this.trigger("toggle",this.options.cardView)},p.prototype.refreshOptions=function(b){i(this.options,b,!0)||(this.options=a.extend(this.options,b),this.trigger("refresh-options",this.options),this.destroy(),this.init())},p.prototype.resetSearch=function(a){var b=this.$toolbar.find(".search input");b.val(a||""),this.onSearch({currentTarget:b})},p.prototype.expandRow_=function(a,b){var d=this.$body.find(c('> tr[data-index="%s"]',b));d.next().is("tr.detail-view")===(a?!1:!0)&&d.find("> td > .detail-icon").click()},p.prototype.expandRow=function(a){this.expandRow_(!0,a)},p.prototype.collapseRow=function(a){this.expandRow_(!1,a)},p.prototype.expandAllRows=function(b){if(b){var d=this.$body.find(c('> tr[data-index="%s"]',0)),e=this,f=null,g=!1,h=-1;if(d.next().is("tr.detail-view")?d.next().next().is("tr.detail-view")||(d.next().find(".detail-icon").click(),g=!0):(d.find("> td > .detail-icon").click(),g=!0),g)try{h=setInterval(function(){f=e.$body.find("tr.detail-view").last().find(".detail-icon"),f.length>0?f.click():clearInterval(h)},1)}catch(i){clearInterval(h)}}else for(var j=this.$body.children(),k=0;k<j.length;k++)this.expandRow_(!0,a(j[k]).data("index"))},p.prototype.collapseAllRows=function(b){if(b)this.expandRow_(!1,0);else for(var c=this.$body.children(),d=0;d<c.length;d++)this.expandRow_(!1,a(c[d]).data("index"))},p.prototype.updateFormatText=function(a,b){this.options[c("format%s",a)]&&("string"==typeof b?this.options[c("format%s",a)]=function(){return b}:"function"==typeof b&&(this.options[c("format%s",a)]=b)),this.initToolbar(),this.initPagination(),this.initBody()};var q=["getOptions","getSelections","getAllSelections","getData","load","append","prepend","remove","removeAll","insertRow","updateRow","updateCell","updateByUniqueId","removeByUniqueId","getRowByUniqueId","showRow","hideRow","getRowsHidden","mergeCells","checkAll","uncheckAll","checkInvert","check","uncheck","checkBy","uncheckBy","refresh","resetView","resetWidth","destroy","showLoading","hideLoading","showColumn","hideColumn","getHiddenColumns","getVisibleColumns","showAllColumns","hideAllColumns","filterBy","scrollTo","getScrollPosition","selectPage","prevPage","nextPage","togglePagination","toggleView","refreshOptions","resetSearch","expandRow","collapseRow","expandAllRows","collapseAllRows","updateFormatText"];a.fn.bootstrapTable=function(b){var c,d=Array.prototype.slice.call(arguments,1);return this.each(function(){var e=a(this),f=e.data("bootstrap.table"),g=a.extend({},p.DEFAULTS,e.data(),"object"==typeof b&&b);if("string"==typeof b){if(a.inArray(b,q)<0)throw new Error("Unknown method: "+b);if(!f)return;c=f[b].apply(f,d),"destroy"===b&&e.removeData("bootstrap.table")}f||e.data("bootstrap.table",f=new p(this,g))}),"undefined"==typeof c?this:c},a.fn.bootstrapTable.Constructor=p,a.fn.bootstrapTable.defaults=p.DEFAULTS,a.fn.bootstrapTable.columnDefaults=p.COLUMN_DEFAULTS,a.fn.bootstrapTable.locales=p.LOCALES,a.fn.bootstrapTable.methods=q,a.fn.bootstrapTable.utils={sprintf:c,getFieldIndex:e,compareObjects:i,calculateObjectValue:h,getItemField:m,objectKeys:o,isIEBrowser:n},a(function(){a('[data-toggle="table"]').bootstrapTable()})}(jQuery); diff --git a/web/gui/lib/bootstrap-table-export-1.11.0.min.js b/web/gui/lib/bootstrap-table-export-1.11.0.min.js new file mode 100644 index 0000000..afa2d02 --- /dev/null +++ b/web/gui/lib/bootstrap-table-export-1.11.0.min.js @@ -0,0 +1,8 @@ +/* +* bootstrap-table - v1.11.0 - 2016-07-02 +* https://github.com/wenzhixin/bootstrap-table +* Copyright (c) 2016 zhixin wen +* Licensed MIT License +* SPDX-License-Identifier: MIT +*/ +!function(a){"use strict";var b=a.fn.bootstrapTable.utils.sprintf,c={json:"JSON",xml:"XML",png:"PNG",csv:"CSV",txt:"TXT",sql:"SQL",doc:"MS-Word",excel:"MS-Excel",powerpoint:"MS-Powerpoint",pdf:"PDF"};a.extend(a.fn.bootstrapTable.defaults,{showExport:!1,exportDataType:"basic",exportTypes:["json","xml","csv","txt","sql","excel"],exportOptions:{}}),a.extend(a.fn.bootstrapTable.defaults.icons,{"export":"glyphicon-export icon-share"}),a.extend(a.fn.bootstrapTable.locales,{formatExport:function(){return"Export data"}}),a.extend(a.fn.bootstrapTable.defaults,a.fn.bootstrapTable.locales);var d=a.fn.bootstrapTable.Constructor,e=d.prototype.initToolbar;d.prototype.initToolbar=function(){if(this.showToolbar=this.options.showExport,e.apply(this,Array.prototype.slice.apply(arguments)),this.options.showExport){var d=this,f=this.$toolbar.find(">.btn-group"),g=f.find("div.export");if(!g.length){g=a(['<div class="export btn-group">','<button class="btn'+b(" btn-%s",this.options.buttonsClass)+b(" btn-%s",this.options.iconSize)+' dropdown-toggle" title="'+this.options.formatExport()+'" data-toggle="dropdown" type="button">',b('<i class="%s %s"></i> ',this.options.iconsPrefix,this.options.icons["export"]),'<span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">',"</ul>","</div>"].join("")).appendTo(f);var h=g.find(".dropdown-menu"),i=this.options.exportTypes;if("string"==typeof this.options.exportTypes){var j=this.options.exportTypes.slice(1,-1).replace(/ /g,"").split(",");i=[],a.each(j,function(a,b){i.push(b.slice(1,-1))})}a.each(i,function(a,b){c.hasOwnProperty(b)&&h.append(['<li data-type="'+b+'">','<a href="javascript:void(0)">',c[b],"</a>","</li>"].join(""))}),h.find("li").click(function(){var b=a(this).data("type"),c=function(){d.$el.tableExport(a.extend({},d.options.exportOptions,{type:b,escape:!1}))};if("all"===d.options.exportDataType&&d.options.pagination)d.$el.one("server"===d.options.sidePagination?"post-body.bs.table":"page-change.bs.table",function(){c(),d.togglePagination()}),d.togglePagination();else if("selected"===d.options.exportDataType){var e=d.getData(),f=d.getAllSelections();d.load(f),c(),d.load(e)}else c()})}}}}(jQuery); diff --git a/web/gui/lib/bootstrap-toggle-2.2.2.min.js b/web/gui/lib/bootstrap-toggle-2.2.2.min.js new file mode 100644 index 0000000..a11e156 --- /dev/null +++ b/web/gui/lib/bootstrap-toggle-2.2.2.min.js @@ -0,0 +1,10 @@ +/*! ======================================================================== + * Bootstrap Toggle: bootstrap-toggle.js v2.2.0 + * http://www.bootstraptoggle.com + * ======================================================================== + * Copyright 2014 Min Hur, The New York Times Company + * Licensed under MIT + * SPDX-License-Identifier: MIT + * ======================================================================== */ ++function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery); +//# sourceMappingURL=bootstrap-toggle.min.js.map diff --git a/web/gui/lib/clipboard-polyfill-be05dad.js b/web/gui/lib/clipboard-polyfill-be05dad.js new file mode 100644 index 0000000..d1ba02e --- /dev/null +++ b/web/gui/lib/clipboard-polyfill-be05dad.js @@ -0,0 +1,9 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.clipboard=e():t.clipboard=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,r){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,n){"use strict";function r(t,e,n){m("listener called"),t.success=!0,e.forEach(function(e,r){n.clipboardData.setData(r,e),r===b&&n.clipboardData.getData(r)!=e&&(m("setting text/plain failed"),t.success=!1)}),n.preventDefault()}function o(t){var e=new _,n=r.bind(this,e,t);document.addEventListener("copy",n);try{document.execCommand("copy")}finally{document.removeEventListener("copy",n)}return e}function i(t,e){c(t);var n=o(e);return a(),n}function u(t){var e=document.createElement("div");e.textContent="temporary element",document.body.appendChild(e);var n=i(e,t);return document.body.removeChild(e),n}function s(t){m("copyTextUsingDOM");var e=document.createElement("div"),n=e.attachShadow({mode:"open"});document.body.appendChild(e);var r=document.createElement("span");r.innerText=t,n.appendChild(r),c(r);var o=document.execCommand("copy");return a(),document.body.removeChild(e),o}function c(t){var e=document.getSelection(),n=document.createRange();n.selectNodeContents(t),e.removeAllRanges(),e.addRange(n)}function a(){document.getSelection().removeAllRanges()}function l(t){var e=new v.DT;return e.setData("text/plain",t),e}function f(){return"undefined"==typeof ClipboardEvent&&void 0!==window.clipboardData&&void 0!==window.clipboardData.setData}function d(t){var e=t.getData("text/plain");if(void 0!==e)return window.clipboardData.setData("Text",e);throw"No `text/plain` value was specified."}function p(){return new h.Promise(function(t,e){var n=window.clipboardData.getData("Text");""===n?e(new Error("Empty clipboard or could not read plain text from clipboard")):t(n)})}Object.defineProperty(e,"__esModule",{value:!0});var h=n(1),v=n(5),m=function(t){},y=!0,w=(console.warn||console.log).bind(console,"[clipboard-polyfill]"),b="text/plain",g=function(){function t(){}return t.setDebugLog=function(t){m=t},t.suppressWarnings=function(){y=!1,v.suppressDTWarnings()},t.write=function(t){return y&&!t.getData(b)&&w("clipboard.write() was called without a `text/plain` data type. On some platforms, this may result in an empty clipboard. Call clipboard.suppressWarnings() to suppress this warning."),new h.Promise(function(e,n){if(f())return void(d(t)?e():n(new Error("Copying failed, possibly because the user rejected it.")));var r=o(t);if(r.success)return m("regular execCopy worked"),void e();if(navigator.userAgent.indexOf("Edge")>-1)return m('UA "Edge" => assuming success'),void e();if(r=i(document.body,t),r.success)return m("copyUsingTempSelection worked"),void e();if(r=u(t),r.success)return m("copyUsingTempElem worked"),void e();var c=t.getData(b);if(void 0!==c&&s(c))return m("copyTextUsingDOM worked"),void e();n(new Error("Copy command failed."))})},t.writeText=function(t){var e=new v.DT;return e.setData(b,t),this.write(e)},t.read=function(){return new h.Promise(function(t,e){if(f())return void p().then(function(e){return t(l(e))},e);e("Read is not supported in your browser.")})},t.readText=function(){return f()?p():new h.Promise(function(t,e){e("Read is not supported in your browser.")})},t.DT=v.DT,t}();e.default=g;var _=function(){function t(){this.success=!1}return t}();t.exports=g},function(t,e,n){(function(e,r){/*! + * @overview es6-promise - a tiny implementation of Promises/A+. + * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) + * @license Licensed under MIT license + * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE + * @version 4.1.1 + * SPDX-License-Identifier: MIT + */ +!function(e,n){t.exports=n()}(0,function(){"use strict";function t(t){var e=typeof t;return null!==t&&("object"===e||"function"===e)}function o(t){return"function"==typeof t}function i(t){q=t}function u(t){z=t}function s(){return void 0!==K?function(){K(a)}:c()}function c(){var t=setTimeout;return function(){return t(a,1)}}function a(){for(var t=0;t<I;t+=2){(0,Z[t])(Z[t+1]),Z[t]=void 0,Z[t+1]=void 0}I=0}function l(t,e){var n=arguments,r=this,o=new this.constructor(d);void 0===o[tt]&&P(o);var i=r._state;return i?function(){var t=n[i-1];z(function(){return j(i,o,t,r._result)})}():E(r,o,t,e),o}function f(t){var e=this;if(t&&"object"==typeof t&&t.constructor===e)return t;var n=new e(d);return g(n,t),n}function d(){}function p(){return new TypeError("You cannot resolve a promise with itself")}function h(){return new TypeError("A promises callback cannot return that same promise.")}function v(t){try{return t.then}catch(t){return ot.error=t,ot}}function m(t,e,n,r){try{t.call(e,n,r)}catch(t){return t}}function y(t,e,n){z(function(t){var r=!1,o=m(n,e,function(n){r||(r=!0,e!==n?g(t,n):T(t,n))},function(e){r||(r=!0,x(t,e))},"Settle: "+(t._label||" unknown promise"));!r&&o&&(r=!0,x(t,o))},t)}function w(t,e){e._state===nt?T(t,e._result):e._state===rt?x(t,e._result):E(e,void 0,function(e){return g(t,e)},function(e){return x(t,e)})}function b(t,e,n){e.constructor===t.constructor&&n===l&&e.constructor.resolve===f?w(t,e):n===ot?(x(t,ot.error),ot.error=null):void 0===n?T(t,e):o(n)?y(t,e,n):T(t,e)}function g(e,n){e===n?x(e,p()):t(n)?b(e,n,v(n)):T(e,n)}function _(t){t._onerror&&t._onerror(t._result),D(t)}function T(t,e){t._state===et&&(t._result=e,t._state=nt,0!==t._subscribers.length&&z(D,t))}function x(t,e){t._state===et&&(t._state=rt,t._result=e,z(_,t))}function E(t,e,n,r){var o=t._subscribers,i=o.length;t._onerror=null,o[i]=e,o[i+nt]=n,o[i+rt]=r,0===i&&t._state&&z(D,t)}function D(t){var e=t._subscribers,n=t._state;if(0!==e.length){for(var r=void 0,o=void 0,i=t._result,u=0;u<e.length;u+=3)r=e[u],o=e[u+n],r?j(n,r,o,i):o(i);t._subscribers.length=0}}function A(){this.error=null}function C(t,e){try{return t(e)}catch(t){return it.error=t,it}}function j(t,e,n,r){var i=o(n),u=void 0,s=void 0,c=void 0,a=void 0;if(i){if(u=C(n,r),u===it?(a=!0,s=u.error,u.error=null):c=!0,e===u)return void x(e,h())}else u=r,c=!0;e._state!==et||(i&&c?g(e,u):a?x(e,s):t===nt?T(e,u):t===rt&&x(e,u))}function O(t,e){try{e(function(e){g(t,e)},function(e){x(t,e)})}catch(e){x(t,e)}}function S(){return ut++}function P(t){t[tt]=ut++,t._state=void 0,t._result=void 0,t._subscribers=[]}function M(t,e){this._instanceConstructor=t,this.promise=new t(d),this.promise[tt]||P(this.promise),H(e)?(this.length=e.length,this._remaining=e.length,this._result=new Array(this.length),0===this.length?T(this.promise,this._result):(this.length=this.length||0,this._enumerate(e),0===this._remaining&&T(this.promise,this._result))):x(this.promise,L())}function L(){return new Error("Array Methods must be provided an Array")}function k(t){return new M(this,t).promise}function U(t){var e=this;return new e(H(t)?function(n,r){for(var o=t.length,i=0;i<o;i++)e.resolve(t[i]).then(n,r)}:function(t,e){return e(new TypeError("You must pass an array to race."))})}function R(t){var e=this,n=new e(d);return x(n,t),n}function W(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function N(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function F(t){this[tt]=S(),this._result=this._state=void 0,this._subscribers=[],d!==t&&("function"!=typeof t&&W(),this instanceof F?O(this,t):N())}function Y(){var t=void 0;if(void 0!==r)t=r;else if("undefined"!=typeof self)t=self;else try{t=Function("return this")()}catch(t){throw new Error("polyfill failed because global object is unavailable in this environment")}var e=t.Promise;if(e){var n=null;try{n=Object.prototype.toString.call(e.resolve())}catch(t){}if("[object Promise]"===n&&!e.cast)return}t.Promise=F}var X=void 0;X=Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)};var H=X,I=0,K=void 0,q=void 0,z=function(t,e){Z[I]=t,Z[I+1]=e,2===(I+=2)&&(q?q(a):$())},B="undefined"!=typeof window?window:void 0,G=B||{},J=G.MutationObserver||G.WebKitMutationObserver,Q="undefined"==typeof self&&void 0!==e&&"[object process]"==={}.toString.call(e),V="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,Z=new Array(1e3),$=void 0;$=Q?function(){return function(){return e.nextTick(a)}}():J?function(){var t=0,e=new J(a),n=document.createTextNode("");return e.observe(n,{characterData:!0}),function(){n.data=t=++t%2}}():V?function(){var t=new MessageChannel;return t.port1.onmessage=a,function(){return t.port2.postMessage(0)}}():void 0===B?function(){try{var t=n(4);return K=t.runOnLoop||t.runOnContext,s()}catch(t){return c()}}():c();var tt=Math.random().toString(36).substring(16),et=void 0,nt=1,rt=2,ot=new A,it=new A,ut=0;return M.prototype._enumerate=function(t){for(var e=0;this._state===et&&e<t.length;e++)this._eachEntry(t[e],e)},M.prototype._eachEntry=function(t,e){var n=this._instanceConstructor,r=n.resolve;if(r===f){var o=v(t);if(o===l&&t._state!==et)this._settledAt(t._state,e,t._result);else if("function"!=typeof o)this._remaining--,this._result[e]=t;else if(n===F){var i=new n(d);b(i,t,o),this._willSettleAt(i,e)}else this._willSettleAt(new n(function(e){return e(t)}),e)}else this._willSettleAt(r(t),e)},M.prototype._settledAt=function(t,e,n){var r=this.promise;r._state===et&&(this._remaining--,t===rt?x(r,n):this._result[e]=n),0===this._remaining&&T(r,this._result)},M.prototype._willSettleAt=function(t,e){var n=this;E(t,void 0,function(t){return n._settledAt(nt,e,t)},function(t){return n._settledAt(rt,e,t)})},F.all=k,F.race=U,F.resolve=f,F.reject=R,F._setScheduler=i,F._setAsap=u,F._asap=z,F.prototype={constructor:F,then:l,catch:function(t){return this.then(null,t)}},F.polyfill=Y,F.Promise=F,F})}).call(e,n(2),n(3))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(l===setTimeout)return setTimeout(t,0);if((l===n||!l)&&setTimeout)return l=setTimeout,setTimeout(t,0);try{return l(t,0)}catch(e){try{return l.call(null,t,0)}catch(e){return l.call(this,t,0)}}}function i(t){if(f===clearTimeout)return clearTimeout(t);if((f===r||!f)&&clearTimeout)return f=clearTimeout,clearTimeout(t);try{return f(t)}catch(e){try{return f.call(null,t)}catch(e){return f.call(this,t)}}}function u(){v&&p&&(v=!1,p.length?h=p.concat(h):m=-1,h.length&&s())}function s(){if(!v){var t=o(u);v=!0;for(var e=h.length;e;){for(p=h,h=[];++m<e;)p&&p[m].run();m=-1,e=h.length}p=null,v=!1,i(t)}}function c(t,e){this.fun=t,this.array=e}function a(){}var l,f,d=t.exports={};!function(){try{l="function"==typeof setTimeout?setTimeout:n}catch(t){l=n}try{f="function"==typeof clearTimeout?clearTimeout:r}catch(t){f=r}}();var p,h=[],v=!1,m=-1;d.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var n=1;n<arguments.length;n++)e[n-1]=arguments[n];h.push(new c(t,e)),1!==h.length||v||o(s)},c.prototype.run=function(){this.fun.apply(null,this.array)},d.title="browser",d.browser=!0,d.env={},d.argv=[],d.version="",d.versions={},d.on=a,d.addListener=a,d.once=a,d.off=a,d.removeListener=a,d.removeAllListeners=a,d.emit=a,d.prependListener=a,d.prependOnceListener=a,d.listeners=function(t){return[]},d.binding=function(t){throw new Error("process.binding is not supported")},d.cwd=function(){return"/"},d.chdir=function(t){throw new Error("process.chdir is not supported")},d.umask=function(){return 0}},function(t,e){var n;n=function(){return this}();try{n=n||Function("return this")()||(0,eval)("this")}catch(t){"object"==typeof window&&(n=window)}t.exports=n},function(t,e){},function(t,e,n){"use strict";function r(){c=!1}Object.defineProperty(e,"__esModule",{value:!0});var o={TEXT_PLAIN:"text/plain",TEXT_HTML:"text/html"},i=new Set;for(var u in o)i.add(o[u]);var s=(console.warn||console.log).bind(console,"[clipboard-polyfill]"),c=!0;e.suppressDTWarnings=r;var a=function(){function t(){this.m=new Map}return t.prototype.setData=function(t,e){c&&!i.has(t)&&s("Unknown data type: "+t,"Call clipboard.suppressWarnings() to suppress this warning."),this.m.set(t,e)},t.prototype.getData=function(t){return this.m.get(t)},t.prototype.forEach=function(t){return this.m.forEach(t)},t}();e.DT=a}])}); diff --git a/web/gui/lib/d3-4.12.2.min.js b/web/gui/lib/d3-4.12.2.min.js new file mode 100644 index 0000000..3d91d1a --- /dev/null +++ b/web/gui/lib/d3-4.12.2.min.js @@ -0,0 +1,3 @@ +// https://d3js.org Version 4.12.2. Copyright 2017 Mike Bostock. +// SPDX-License-Identifier: BSD-3-Clause +(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function e(t){return 1===t.length&&(t=function(t){return function(e,r){return n(t(e),r)}}(t)),{left:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)<0?r=o+1:i=o}return r},right:function(n,e,r,i){for(null==r&&(r=0),null==i&&(i=n.length);r<i;){var o=r+i>>>1;t(n[o],e)>0?i=o:r=o+1}return r}}}function r(t,n){return[t,n]}function i(t){return null===t?NaN:+t}function o(t,n){var e,r,o=t.length,u=0,a=-1,c=0,s=0;if(null==n)for(;++a<o;)isNaN(e=i(t[a]))||(s+=(r=e-c)*(e-(c+=r/++u)));else for(;++a<o;)isNaN(e=i(n(t[a],a,t)))||(s+=(r=e-c)*(e-(c+=r/++u)));if(u>1)return s/(u-1)}function u(t,n){var e=o(t,n);return e?Math.sqrt(e):e}function a(t,n){var e,r,i,o=t.length,u=-1;if(null==n){for(;++u<o;)if(null!=(e=t[u])&&e>=e)for(r=i=e;++u<o;)null!=(e=t[u])&&(r>e&&(r=e),i<e&&(i=e))}else for(;++u<o;)if(null!=(e=n(t[u],u,t))&&e>=e)for(r=i=e;++u<o;)null!=(e=n(t[u],u,t))&&(r>e&&(r=e),i<e&&(i=e));return[r,i]}function c(t){return function(){return t}}function s(t){return t}function f(t,n,e){t=+t,n=+n,e=(i=arguments.length)<2?(n=t,t=0,1):i<3?1:+e;for(var r=-1,i=0|Math.max(0,Math.ceil((n-t)/e)),o=new Array(i);++r<i;)o[r]=t+r*e;return o}function l(t,n,e){var r,i,o,u,a=-1;if(n=+n,t=+t,e=+e,t===n&&e>0)return[t];if((r=n<t)&&(i=t,t=n,n=i),0===(u=h(t,n,e))||!isFinite(u))return[];if(u>0)for(t=Math.ceil(t/u),n=Math.floor(n/u),o=new Array(i=Math.ceil(n-t+1));++a<i;)o[a]=(t+a)*u;else for(t=Math.floor(t*u),n=Math.ceil(n*u),o=new Array(i=Math.ceil(t-n+1));++a<i;)o[a]=(t-a)/u;return r&&o.reverse(),o}function h(t,n,e){var r=(n-t)/Math.max(0,e),i=Math.floor(Math.log(r)/Math.LN10),o=r/Math.pow(10,i);return i>=0?(o>=Ys?10:o>=Bs?5:o>=Hs?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(o>=Ys?10:o>=Bs?5:o>=Hs?2:1)}function p(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Ys?i*=10:o>=Bs?i*=5:o>=Hs&&(i*=2),n<t?-i:i}function d(t){return Math.ceil(Math.log(t.length)/Math.LN2)+1}function v(t,n,e){if(null==e&&(e=i),r=t.length){if((n=+n)<=0||r<2)return+e(t[0],0,t);if(n>=1)return+e(t[r-1],r-1,t);var r,o=(r-1)*n,u=Math.floor(o),a=+e(t[u],u,t);return a+(+e(t[u+1],u+1,t)-a)*(o-u)}}function g(t){for(var n,e,r,i=t.length,o=-1,u=0;++o<i;)u+=t[o].length;for(e=new Array(u);--i>=0;)for(n=(r=t[i]).length;--n>=0;)e[--u]=r[n];return e}function _(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&r>e&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&r>e&&(r=e);return r}function y(t){if(!(i=t.length))return[];for(var n=-1,e=_(t,m),r=new Array(e);++n<e;)for(var i,o=-1,u=r[n]=new Array(i);++o<i;)u[o]=t[o][n];return r}function m(t){return t.length}function x(t){return t}function b(t){return"translate("+(t+.5)+",0)"}function w(t){return"translate(0,"+(t+.5)+")"}function M(){return!this.__axis}function T(t,n){function e(e){var h=null==i?n.ticks?n.ticks.apply(n,r):n.domain():i,p=null==o?n.tickFormat?n.tickFormat.apply(n,r):x:o,d=Math.max(u,0)+c,v=n.range(),g=+v[0]+.5,_=+v[v.length-1]+.5,y=(n.bandwidth?function(t){var n=Math.max(0,t.bandwidth()-1)/2;return t.round()&&(n=Math.round(n)),function(e){return+t(e)+n}}:function(t){return function(n){return+t(n)}})(n.copy()),m=e.selection?e.selection():e,b=m.selectAll(".domain").data([null]),w=m.selectAll(".tick").data(h,n).order(),T=w.exit(),N=w.enter().append("g").attr("class","tick"),k=w.select("line"),S=w.select("text");b=b.merge(b.enter().insert("path",".tick").attr("class","domain").attr("stroke","#000")),w=w.merge(N),k=k.merge(N.append("line").attr("stroke","#000").attr(f+"2",s*u)),S=S.merge(N.append("text").attr("fill","#000").attr(f,s*d).attr("dy",t===Xs?"0em":t===$s?"0.71em":"0.32em")),e!==m&&(b=b.transition(e),w=w.transition(e),k=k.transition(e),S=S.transition(e),T=T.transition(e).attr("opacity",Zs).attr("transform",function(t){return isFinite(t=y(t))?l(t):this.getAttribute("transform")}),N.attr("opacity",Zs).attr("transform",function(t){var n=this.parentNode.__axis;return l(n&&isFinite(n=n(t))?n:y(t))})),T.remove(),b.attr("d",t===Ws||t==Vs?"M"+s*a+","+g+"H0.5V"+_+"H"+s*a:"M"+g+","+s*a+"V0.5H"+_+"V"+s*a),w.attr("opacity",1).attr("transform",function(t){return l(y(t))}),k.attr(f+"2",s*u),S.attr(f,s*d).text(p),m.filter(M).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===Vs?"start":t===Ws?"end":"middle"),m.each(function(){this.__axis=y})}var r=[],i=null,o=null,u=6,a=6,c=3,s=t===Xs||t===Ws?-1:1,f=t===Ws||t===Vs?"x":"y",l=t===Xs||t===$s?b:w;return e.scale=function(t){return arguments.length?(n=t,e):n},e.ticks=function(){return r=js.call(arguments),e},e.tickArguments=function(t){return arguments.length?(r=null==t?[]:js.call(t),e):r.slice()},e.tickValues=function(t){return arguments.length?(i=null==t?null:js.call(t),e):i&&i.slice()},e.tickFormat=function(t){return arguments.length?(o=t,e):o},e.tickSize=function(t){return arguments.length?(u=a=+t,e):u},e.tickSizeInner=function(t){return arguments.length?(u=+t,e):u},e.tickSizeOuter=function(t){return arguments.length?(a=+t,e):a},e.tickPadding=function(t){return arguments.length?(c=+t,e):c},e}function N(){for(var t,n=0,e=arguments.length,r={};n<e;++n){if(!(t=arguments[n]+"")||t in r)throw new Error("illegal type: "+t);r[t]=[]}return new k(r)}function k(t){this._=t}function S(t,n,e){for(var r=0,i=t.length;r<i;++r)if(t[r].name===n){t[r]=Gs,t=t.slice(0,r).concat(t.slice(r+1));break}return null!=e&&t.push({name:n,value:e}),t}function E(t){var n=t+="",e=n.indexOf(":");return e>=0&&"xmlns"!==(n=t.slice(0,e))&&(t=t.slice(e+1)),Js.hasOwnProperty(n)?{space:Js[n],local:t}:t}function A(t){var n=E(t);return(n.local?function(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}:function(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===Qs&&n.documentElement.namespaceURI===Qs?n.createElement(t):n.createElementNS(e,t)}})(n)}function C(){return new z}function z(){this._="@"+(++Ks).toString(36)}function P(t,n,e){return t=R(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function R(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function L(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function q(t,n,e){var r=of.hasOwnProperty(t.type)?P:R;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function D(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function U(){for(var n,e=t.event;n=e.sourceEvent;)e=n;return e}function O(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();return r.x=n.clientX,r.y=n.clientY,r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var i=t.getBoundingClientRect();return[n.clientX-i.left-t.clientLeft,n.clientY-i.top-t.clientTop]}function F(t){var n=U();return n.changedTouches&&(n=n.changedTouches[0]),O(t,n)}function I(){}function Y(t){return null==t?I:function(){return this.querySelector(t)}}function B(){return[]}function H(t){return null==t?B:function(){return this.querySelectorAll(t)}}function j(t){return new Array(t.length)}function X(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function V(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new X(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function $(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=uf+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)(c=f[s=uf+u.call(t,o[a],a,o)])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new X(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function W(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function Z(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function G(t,n){return t.style.getPropertyValue(n)||Z(t).getComputedStyle(t,null).getPropertyValue(n)}function Q(t){return t.trim().split(/^|\s+/)}function J(t){return t.classList||new K(t)}function K(t){this._node=t,this._names=Q(t.getAttribute("class")||"")}function tt(t,n){for(var e=J(t),r=-1,i=n.length;++r<i;)e.add(n[r])}function nt(t,n){for(var e=J(t),r=-1,i=n.length;++r<i;)e.remove(n[r])}function et(){this.textContent=""}function rt(){this.innerHTML=""}function it(){this.nextSibling&&this.parentNode.appendChild(this)}function ot(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function ut(){return null}function at(){var t=this.parentNode;t&&t.removeChild(this)}function ct(t,n,e){var r=Z(t),i=r.CustomEvent;"function"==typeof i?i=new i(n,e):(i=r.document.createEvent("Event"),e?(i.initEvent(n,e.bubbles,e.cancelable),i.detail=e.detail):i.initEvent(n,!1,!1)),t.dispatchEvent(i)}function st(t,n){this._groups=t,this._parents=n}function ft(){return new st([[document.documentElement]],af)}function lt(t){return"string"==typeof t?new st([[document.querySelector(t)]],[document.documentElement]):new st([[t]],af)}function ht(t,n,e){arguments.length<3&&(e=n,n=U().changedTouches);for(var r,i=0,o=n?n.length:0;i<o;++i)if((r=n[i]).identifier===e)return O(t,r);return null}function pt(){t.event.stopImmediatePropagation()}function dt(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function vt(t){var n=t.document.documentElement,e=lt(t).on("dragstart.drag",dt,!0);"onselectstart"in n?e.on("selectstart.drag",dt,!0):(n.__noselect=n.style.MozUserSelect,n.style.MozUserSelect="none")}function gt(t,n){var e=t.document.documentElement,r=lt(t).on("dragstart.drag",null);n&&(r.on("click.drag",dt,!0),setTimeout(function(){r.on("click.drag",null)},0)),"onselectstart"in e?r.on("selectstart.drag",null):(e.style.MozUserSelect=e.__noselect,delete e.__noselect)}function _t(t){return function(){return t}}function yt(t,n,e,r,i,o,u,a,c,s){this.target=t,this.type=n,this.subject=e,this.identifier=r,this.active=i,this.x=o,this.y=u,this.dx=a,this.dy=c,this._=s}function mt(){return!t.event.button}function xt(){return this.parentNode}function bt(n){return null==n?{x:t.event.x,y:t.event.y}:n}function wt(){return"ontouchstart"in this}function Mt(t,n,e){t.prototype=n.prototype=e,e.constructor=t}function Tt(t,n){var e=Object.create(t.prototype);for(var r in n)e[r]=n[r];return e}function Nt(){}function kt(t){var n;return t=(t+"").trim().toLowerCase(),(n=lf.exec(t))?(n=parseInt(n[1],16),new zt(n>>8&15|n>>4&240,n>>4&15|240&n,(15&n)<<4|15&n,1)):(n=hf.exec(t))?St(parseInt(n[1],16)):(n=pf.exec(t))?new zt(n[1],n[2],n[3],1):(n=df.exec(t))?new zt(255*n[1]/100,255*n[2]/100,255*n[3]/100,1):(n=vf.exec(t))?Et(n[1],n[2],n[3],n[4]):(n=gf.exec(t))?Et(255*n[1]/100,255*n[2]/100,255*n[3]/100,n[4]):(n=_f.exec(t))?Pt(n[1],n[2]/100,n[3]/100,1):(n=yf.exec(t))?Pt(n[1],n[2]/100,n[3]/100,n[4]):mf.hasOwnProperty(t)?St(mf[t]):"transparent"===t?new zt(NaN,NaN,NaN,0):null}function St(t){return new zt(t>>16&255,t>>8&255,255&t,1)}function Et(t,n,e,r){return r<=0&&(t=n=e=NaN),new zt(t,n,e,r)}function At(t){return t instanceof Nt||(t=kt(t)),t?(t=t.rgb(),new zt(t.r,t.g,t.b,t.opacity)):new zt}function Ct(t,n,e,r){return 1===arguments.length?At(t):new zt(t,n,e,null==r?1:r)}function zt(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}function Pt(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new Lt(t,n,e,r)}function Rt(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof Lt)return new Lt(t.h,t.s,t.l,t.opacity);if(t instanceof Nt||(t=kt(t)),!t)return new Lt;if(t instanceof Lt)return t;var n=(t=t.rgb()).r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),u=NaN,a=o-i,c=(o+i)/2;return a?(u=n===o?(e-r)/a+6*(e<r):e===o?(r-n)/a+2:(n-e)/a+4,a/=c<.5?o+i:2-o-i,u*=60):a=c>0&&c<1?0:u,new Lt(u,a,c,t.opacity)}(t):new Lt(t,n,e,null==r?1:r)}function Lt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function qt(t,n,e){return 255*(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)}function Dt(t){if(t instanceof Ot)return new Ot(t.l,t.a,t.b,t.opacity);if(t instanceof jt){var n=t.h*xf;return new Ot(t.l,Math.cos(n)*t.c,Math.sin(n)*t.c,t.opacity)}t instanceof zt||(t=At(t));var e=Bt(t.r),r=Bt(t.g),i=Bt(t.b),o=Ft((.4124564*e+.3575761*r+.1804375*i)/wf),u=Ft((.2126729*e+.7151522*r+.072175*i)/Mf);return new Ot(116*u-16,500*(o-u),200*(u-Ft((.0193339*e+.119192*r+.9503041*i)/Tf)),t.opacity)}function Ut(t,n,e,r){return 1===arguments.length?Dt(t):new Ot(t,n,e,null==r?1:r)}function Ot(t,n,e,r){this.l=+t,this.a=+n,this.b=+e,this.opacity=+r}function Ft(t){return t>Ef?Math.pow(t,1/3):t/Sf+Nf}function It(t){return t>kf?t*t*t:Sf*(t-Nf)}function Yt(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Bt(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Ht(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof jt)return new jt(t.h,t.c,t.l,t.opacity);t instanceof Ot||(t=Dt(t));var n=Math.atan2(t.b,t.a)*bf;return new jt(n<0?n+360:n,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}(t):new jt(t,n,e,null==r?1:r)}function jt(t,n,e,r){this.h=+t,this.c=+n,this.l=+e,this.opacity=+r}function Xt(t,n,e,r){return 1===arguments.length?function(t){if(t instanceof Vt)return new Vt(t.h,t.s,t.l,t.opacity);t instanceof zt||(t=At(t));var n=t.r/255,e=t.g/255,r=t.b/255,i=(Lf*r+Pf*n-Rf*e)/(Lf+Pf-Rf),o=r-i,u=(zf*(e-i)-Af*o)/Cf,a=Math.sqrt(u*u+o*o)/(zf*i*(1-i)),c=a?Math.atan2(u,o)*bf-120:NaN;return new Vt(c<0?c+360:c,a,i,t.opacity)}(t):new Vt(t,n,e,null==r?1:r)}function Vt(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}function $t(t,n,e,r,i){var o=t*t,u=o*t;return((1-3*t+3*o-u)*n+(4-6*o+3*u)*e+(1+3*t+3*o-3*u)*r+u*i)/6}function Wt(t){var n=t.length-1;return function(e){var r=e<=0?e=0:e>=1?(e=1,n-1):Math.floor(e*n),i=t[r],o=t[r+1],u=r>0?t[r-1]:2*i-o,a=r<n-1?t[r+2]:2*o-i;return $t((e-r/n)*n,u,i,o,a)}}function Zt(t){var n=t.length;return function(e){var r=Math.floor(((e%=1)<0?++e:e)*n),i=t[(r+n-1)%n],o=t[r%n],u=t[(r+1)%n],a=t[(r+2)%n];return $t((e-r/n)*n,i,o,u,a)}}function Gt(t){return function(){return t}}function Qt(t,n){return function(e){return t+e*n}}function Jt(t,n){var e=n-t;return e?Qt(t,e>180||e<-180?e-360*Math.round(e/360):e):Gt(isNaN(t)?n:t)}function Kt(t){return 1==(t=+t)?tn:function(n,e){return e-n?function(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}(n,e,t):Gt(isNaN(n)?e:n)}}function tn(t,n){var e=n-t;return e?Qt(t,e):Gt(isNaN(t)?n:t)}function nn(t){return function(n){var e,r,i=n.length,o=new Array(i),u=new Array(i),a=new Array(i);for(e=0;e<i;++e)r=Ct(n[e]),o[e]=r.r||0,u[e]=r.g||0,a[e]=r.b||0;return o=t(o),u=t(u),a=t(a),r.opacity=1,function(t){return r.r=o(t),r.g=u(t),r.b=a(t),r+""}}}function en(t,n){var e,r=n?n.length:0,i=t?Math.min(r,t.length):0,o=new Array(i),u=new Array(r);for(e=0;e<i;++e)o[e]=cn(t[e],n[e]);for(;e<r;++e)u[e]=n[e];return function(t){for(e=0;e<i;++e)u[e]=o[e](t);return u}}function rn(t,n){var e=new Date;return t=+t,n-=t,function(r){return e.setTime(t+n*r),e}}function on(t,n){return t=+t,n-=t,function(e){return t+n*e}}function un(t,n){var e,r={},i={};null!==t&&"object"==typeof t||(t={}),null!==n&&"object"==typeof n||(n={});for(e in n)e in t?r[e]=cn(t[e],n[e]):i[e]=n[e];return function(t){for(e in r)i[e]=r[e](t);return i}}function an(t,n){var e,r,i,o=jf.lastIndex=Xf.lastIndex=0,u=-1,a=[],c=[];for(t+="",n+="";(e=jf.exec(t))&&(r=Xf.exec(n));)(i=r.index)>o&&(i=n.slice(o,i),a[u]?a[u]+=i:a[++u]=i),(e=e[0])===(r=r[0])?a[u]?a[u]+=r:a[++u]=r:(a[++u]=null,c.push({i:u,x:on(e,r)})),o=Xf.lastIndex;return o<n.length&&(i=n.slice(o),a[u]?a[u]+=i:a[++u]=i),a.length<2?c[0]?function(t){return function(n){return t(n)+""}}(c[0].x):function(t){return function(){return t}}(n):(n=c.length,function(t){for(var e,r=0;r<n;++r)a[(e=c[r]).i]=e.x(t);return a.join("")})}function cn(t,n){var e,r=typeof n;return null==n||"boolean"===r?Gt(n):("number"===r?on:"string"===r?(e=kt(n))?(n=e,Yf):an:n instanceof kt?Yf:n instanceof Date?rn:Array.isArray(n)?en:"function"!=typeof n.valueOf&&"function"!=typeof n.toString||isNaN(n)?un:on)(t,n)}function sn(t,n){return t=+t,n-=t,function(e){return Math.round(t+n*e)}}function fn(t,n,e,r,i,o){var u,a,c;return(u=Math.sqrt(t*t+n*n))&&(t/=u,n/=u),(c=t*e+n*r)&&(e-=t*c,r-=n*c),(a=Math.sqrt(e*e+r*r))&&(e/=a,r/=a,c/=a),t*r<n*e&&(t=-t,n=-n,c=-c,u=-u),{translateX:i,translateY:o,rotate:Math.atan2(n,t)*Vf,skewX:Math.atan(c)*Vf,scaleX:u,scaleY:a}}function ln(t,n,e,r){function i(t){return t.length?t.pop()+" ":""}return function(o,u){var a=[],c=[];return o=t(o),u=t(u),function(t,r,i,o,u,a){if(t!==i||r!==o){var c=u.push("translate(",null,n,null,e);a.push({i:c-4,x:on(t,i)},{i:c-2,x:on(r,o)})}else(i||o)&&u.push("translate("+i+n+o+e)}(o.translateX,o.translateY,u.translateX,u.translateY,a,c),function(t,n,e,o){t!==n?(t-n>180?n+=360:n-t>180&&(t+=360),o.push({i:e.push(i(e)+"rotate(",null,r)-2,x:on(t,n)})):n&&e.push(i(e)+"rotate("+n+r)}(o.rotate,u.rotate,a,c),function(t,n,e,o){t!==n?o.push({i:e.push(i(e)+"skewX(",null,r)-2,x:on(t,n)}):n&&e.push(i(e)+"skewX("+n+r)}(o.skewX,u.skewX,a,c),function(t,n,e,r,o,u){if(t!==e||n!==r){var a=o.push(i(o)+"scale(",null,",",null,")");u.push({i:a-4,x:on(t,e)},{i:a-2,x:on(n,r)})}else 1===e&&1===r||o.push(i(o)+"scale("+e+","+r+")")}(o.scaleX,o.scaleY,u.scaleX,u.scaleY,a,c),o=u=null,function(t){for(var n,e=-1,r=c.length;++e<r;)a[(n=c[e]).i]=n.x(t);return a.join("")}}}function hn(t){return((t=Math.exp(t))+1/t)/2}function pn(t,n){var e,r,i=t[0],o=t[1],u=t[2],a=n[0],c=n[1],s=n[2],f=a-i,l=c-o,h=f*f+l*l;if(h<Kf)r=Math.log(s/u)/Gf,e=function(t){return[i+t*f,o+t*l,u*Math.exp(Gf*t*r)]};else{var p=Math.sqrt(h),d=(s*s-u*u+Jf*h)/(2*u*Qf*p),v=(s*s-u*u-Jf*h)/(2*s*Qf*p),g=Math.log(Math.sqrt(d*d+1)-d),_=Math.log(Math.sqrt(v*v+1)-v);r=(_-g)/Gf,e=function(t){var n=t*r,e=hn(g),a=u/(Qf*p)*(e*function(t){return((t=Math.exp(2*t))-1)/(t+1)}(Gf*n+g)-function(t){return((t=Math.exp(t))-1/t)/2}(g));return[i+a*f,o+a*l,u*e/hn(Gf*n+g)]}}return e.duration=1e3*r,e}function dn(t){return function(n,e){var r=t((n=Rt(n)).h,(e=Rt(e)).h),i=tn(n.s,e.s),o=tn(n.l,e.l),u=tn(n.opacity,e.opacity);return function(t){return n.h=r(t),n.s=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function vn(t){return function(n,e){var r=t((n=Ht(n)).h,(e=Ht(e)).h),i=tn(n.c,e.c),o=tn(n.l,e.l),u=tn(n.opacity,e.opacity);return function(t){return n.h=r(t),n.c=i(t),n.l=o(t),n.opacity=u(t),n+""}}}function gn(t){return function n(e){function r(n,r){var i=t((n=Xt(n)).h,(r=Xt(r)).h),o=tn(n.s,r.s),u=tn(n.l,r.l),a=tn(n.opacity,r.opacity);return function(t){return n.h=i(t),n.s=o(t),n.l=u(Math.pow(t,e)),n.opacity=a(t),n+""}}return e=+e,r.gamma=n,r}(1)}function _n(){return ll||(dl(yn),ll=pl.now()+hl)}function yn(){ll=0}function mn(){this._call=this._time=this._next=null}function xn(t,n,e){var r=new mn;return r.restart(t,n,e),r}function bn(){_n(),++ul;for(var t,n=Ff;n;)(t=ll-n._time)>=0&&n._call.call(null,t),n=n._next;--ul}function wn(){ll=(fl=pl.now())+hl,ul=al=0;try{bn()}finally{ul=0,function(){var t,n,e=Ff,r=1/0;for(;e;)e._call?(r>e._time&&(r=e._time),t=e,e=e._next):(n=e._next,e._next=null,e=t?t._next=n:Ff=n);If=t,Tn(r)}(),ll=0}}function Mn(){var t=pl.now(),n=t-fl;n>sl&&(hl-=n,fl=t)}function Tn(t){if(!ul){al&&(al=clearTimeout(al));t-ll>24?(t<1/0&&(al=setTimeout(wn,t-pl.now()-hl)),cl&&(cl=clearInterval(cl))):(cl||(fl=pl.now(),cl=setInterval(Mn,sl)),ul=1,dl(wn))}}function Nn(t,n,e){var r=new mn;return n=null==n?0:+n,r.restart(function(e){r.stop(),t(e+n)},n,e),r}function kn(t,n,e,r,i,o){var u=t.__transition;if(u){if(e in u)return}else t.__transition={};(function(t,n,e){function r(c){var s,f,l,h;if(e.state!==yl)return o();for(s in a)if((h=a[s]).name===e.name){if(h.state===xl)return Nn(r);h.state===bl?(h.state=Ml,h.timer.stop(),h.on.call("interrupt",t,t.__data__,h.index,h.group),delete a[s]):+s<n&&(h.state=Ml,h.timer.stop(),delete a[s])}if(Nn(function(){e.state===xl&&(e.state=bl,e.timer.restart(i,e.delay,e.time),i(c))}),e.state=ml,e.on.call("start",t,t.__data__,e.index,e.group),e.state===ml){for(e.state=xl,u=new Array(l=e.tween.length),s=0,f=-1;s<l;++s)(h=e.tween[s].value.call(t,t.__data__,e.index,e.group))&&(u[++f]=h);u.length=f+1}}function i(n){for(var r=n<e.duration?e.ease.call(null,n/e.duration):(e.timer.restart(o),e.state=wl,1),i=-1,a=u.length;++i<a;)u[i].call(null,r);e.state===wl&&(e.on.call("end",t,t.__data__,e.index,e.group),o())}function o(){e.state=Ml,e.timer.stop(),delete a[n];for(var r in a)return;delete t.__transition}var u,a=t.__transition;a[n]=e,e.timer=xn(function(t){e.state=yl,e.timer.restart(r,e.delay,e.time),e.delay<=t&&r(t-e.delay)},0,e.time)})(t,e,{name:n,index:r,group:i,on:vl,tween:gl,time:o.time,delay:o.delay,duration:o.duration,ease:o.ease,timer:null,state:_l})}function Sn(t,n){var e=An(t,n);if(e.state>_l)throw new Error("too late; already scheduled");return e}function En(t,n){var e=An(t,n);if(e.state>ml)throw new Error("too late; already started");return e}function An(t,n){var e=t.__transition;if(!e||!(e=e[n]))throw new Error("transition not found");return e}function Cn(t,n){var e,r,i,o=t.__transition,u=!0;if(o){n=null==n?null:n+"";for(i in o)(e=o[i]).name===n?(r=e.state>ml&&e.state<wl,e.state=Ml,e.timer.stop(),r&&e.on.call("interrupt",t,t.__data__,e.index,e.group),delete o[i]):u=!1;u&&delete t.__transition}}function zn(t,n,e){var r=t._id;return t.each(function(){var t=En(this,r);(t.value||(t.value={}))[n]=e.apply(this,arguments)}),function(t){return An(t,r).value[n]}}function Pn(t,n){var e;return("number"==typeof n?on:n instanceof kt?Yf:(e=kt(n))?(n=e,Yf):an)(t,n)}function Rn(t,n,e,r){this._groups=t,this._parents=n,this._name=e,this._id=r}function Ln(t){return ft().transition(t)}function qn(){return++Nl}function Dn(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function Un(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function On(t){return(1-Math.cos(Cl*t))/2}function Fn(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function In(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function Yn(t){return(t=+t)<Pl?Yl*t*t:t<Ll?Yl*(t-=Rl)*t+ql:t<Ul?Yl*(t-=Dl)*t+Ol:Yl*(t-=Fl)*t+Il}function Bn(t,n){for(var e;!(e=t.__transition)||!(e=e[n]);)if(!(t=t.parentNode))return Zl.time=_n(),Zl;return e}function Hn(t){return function(){return t}}function jn(){t.event.stopImmediatePropagation()}function Xn(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function Vn(t){return{type:t}}function $n(){return!t.event.button}function Wn(){var t=this.ownerSVGElement||this;return[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]}function Zn(t){for(;!t.__brush;)if(!(t=t.parentNode))return;return t.__brush}function Gn(t){return t[0][0]===t[1][0]||t[0][1]===t[1][1]}function Qn(n){function e(t){var e=t.property("__brush",a).selectAll(".overlay").data([Vn("overlay")]);e.enter().append("rect").attr("class","overlay").attr("pointer-events","all").attr("cursor",ih.overlay).merge(e).each(function(){var t=Zn(this).extent;lt(this).attr("x",t[0][0]).attr("y",t[0][1]).attr("width",t[1][0]-t[0][0]).attr("height",t[1][1]-t[0][1])}),t.selectAll(".selection").data([Vn("selection")]).enter().append("rect").attr("class","selection").attr("cursor",ih.selection).attr("fill","#777").attr("fill-opacity",.3).attr("stroke","#fff").attr("shape-rendering","crispEdges");var i=t.selectAll(".handle").data(n.handles,function(t){return t.type});i.exit().remove(),i.enter().append("rect").attr("class",function(t){return"handle handle--"+t.type}).attr("cursor",function(t){return ih[t.type]}),t.each(r).attr("fill","none").attr("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush touchstart.brush",u)}function r(){var t=lt(this),n=Zn(this).selection;n?(t.selectAll(".selection").style("display",null).attr("x",n[0][0]).attr("y",n[0][1]).attr("width",n[1][0]-n[0][0]).attr("height",n[1][1]-n[0][1]),t.selectAll(".handle").style("display",null).attr("x",function(t){return"e"===t.type[t.type.length-1]?n[1][0]-h/2:n[0][0]-h/2}).attr("y",function(t){return"s"===t.type[0]?n[1][1]-h/2:n[0][1]-h/2}).attr("width",function(t){return"n"===t.type||"s"===t.type?n[1][0]-n[0][0]+h:h}).attr("height",function(t){return"e"===t.type||"w"===t.type?n[1][1]-n[0][1]+h:h})):t.selectAll(".selection,.handle").style("display","none").attr("x",null).attr("y",null).attr("width",null).attr("height",null)}function i(t,n){return t.__brush.emitter||new o(t,n)}function o(t,n){this.that=t,this.args=n,this.state=t.__brush,this.active=0}function u(){function e(){var t=F(w);!L||x||b||(Math.abs(t[0]-D[0])>Math.abs(t[1]-D[1])?b=!0:x=!0),D=t,m=!0,Xn(),o()}function o(){var t;switch(_=D[0]-q[0],y=D[1]-q[1],T){case Jl:case Ql:N&&(_=Math.max(C-a,Math.min(P-p,_)),s=a+_,d=p+_),k&&(y=Math.max(z-l,Math.min(R-v,y)),h=l+y,g=v+y);break;case Kl:N<0?(_=Math.max(C-a,Math.min(P-a,_)),s=a+_,d=p):N>0&&(_=Math.max(C-p,Math.min(P-p,_)),s=a,d=p+_),k<0?(y=Math.max(z-l,Math.min(R-l,y)),h=l+y,g=v):k>0&&(y=Math.max(z-v,Math.min(R-v,y)),h=l,g=v+y);break;case th:N&&(s=Math.max(C,Math.min(P,a-_*N)),d=Math.max(C,Math.min(P,p+_*N))),k&&(h=Math.max(z,Math.min(R,l-y*k)),g=Math.max(z,Math.min(R,v+y*k)))}d<s&&(N*=-1,t=a,a=p,p=t,t=s,s=d,d=t,M in oh&&I.attr("cursor",ih[M=oh[M]])),g<h&&(k*=-1,t=l,l=v,v=t,t=h,h=g,g=t,M in uh&&I.attr("cursor",ih[M=uh[M]])),S.selection&&(A=S.selection),x&&(s=A[0][0],d=A[1][0]),b&&(h=A[0][1],g=A[1][1]),A[0][0]===s&&A[0][1]===h&&A[1][0]===d&&A[1][1]===g||(S.selection=[[s,h],[d,g]],r.call(w),U.brush())}function u(){if(jn(),t.event.touches){if(t.event.touches.length)return;c&&clearTimeout(c),c=setTimeout(function(){c=null},500),O.on("touchmove.brush touchend.brush touchcancel.brush",null)}else gt(t.event.view,m),Y.on("keydown.brush keyup.brush mousemove.brush mouseup.brush",null);O.attr("pointer-events","all"),I.attr("cursor",ih.overlay),S.selection&&(A=S.selection),Gn(A)&&(S.selection=null,r.call(w)),U.end()}if(t.event.touches){if(t.event.changedTouches.length<t.event.touches.length)return Xn()}else if(c)return;if(f.apply(this,arguments)){var a,s,l,h,p,d,v,g,_,y,m,x,b,w=this,M=t.event.target.__data__.type,T="selection"===(t.event.metaKey?M="overlay":M)?Ql:t.event.altKey?th:Kl,N=n===eh?null:ah[M],k=n===nh?null:ch[M],S=Zn(w),E=S.extent,A=S.selection,C=E[0][0],z=E[0][1],P=E[1][0],R=E[1][1],L=N&&k&&t.event.shiftKey,q=F(w),D=q,U=i(w,arguments).beforestart();"overlay"===M?S.selection=A=[[a=n===eh?C:q[0],l=n===nh?z:q[1]],[p=n===eh?P:a,v=n===nh?R:l]]:(a=A[0][0],l=A[0][1],p=A[1][0],v=A[1][1]),s=a,h=l,d=p,g=v;var O=lt(w).attr("pointer-events","none"),I=O.selectAll(".overlay").attr("cursor",ih[M]);if(t.event.touches)O.on("touchmove.brush",e,!0).on("touchend.brush touchcancel.brush",u,!0);else{var Y=lt(t.event.view).on("keydown.brush",function(){switch(t.event.keyCode){case 16:L=N&&k;break;case 18:T===Kl&&(N&&(p=d-_*N,a=s+_*N),k&&(v=g-y*k,l=h+y*k),T=th,o());break;case 32:T!==Kl&&T!==th||(N<0?p=d-_:N>0&&(a=s-_),k<0?v=g-y:k>0&&(l=h-y),T=Jl,I.attr("cursor",ih.selection),o());break;default:return}Xn()},!0).on("keyup.brush",function(){switch(t.event.keyCode){case 16:L&&(x=b=L=!1,o());break;case 18:T===th&&(N<0?p=d:N>0&&(a=s),k<0?v=g:k>0&&(l=h),T=Kl,o());break;case 32:T===Jl&&(t.event.altKey?(N&&(p=d-_*N,a=s+_*N),k&&(v=g-y*k,l=h+y*k),T=th):(N<0?p=d:N>0&&(a=s),k<0?v=g:k>0&&(l=h),T=Kl),I.attr("cursor",ih[M]),o());break;default:return}Xn()},!0).on("mousemove.brush",e,!0).on("mouseup.brush",u,!0);vt(t.event.view)}jn(),Cn(w),r.call(w),U.start()}}function a(){var t=this.__brush||{selection:null};return t.extent=s.apply(this,arguments),t.dim=n,t}var c,s=Wn,f=$n,l=N(e,"start","brush","end"),h=6;return e.move=function(t,e){t.selection?t.on("start.brush",function(){i(this,arguments).beforestart().start()}).on("interrupt.brush end.brush",function(){i(this,arguments).end()}).tween("brush",function(){function t(t){u.selection=1===t&&Gn(s)?null:f(t),r.call(o),a.brush()}var o=this,u=o.__brush,a=i(o,arguments),c=u.selection,s=n.input("function"==typeof e?e.apply(this,arguments):e,u.extent),f=cn(c,s);return c&&s?t:t(1)}):t.each(function(){var t=arguments,o=this.__brush,u=n.input("function"==typeof e?e.apply(this,t):e,o.extent),a=i(this,t).beforestart();Cn(this),o.selection=null==u||Gn(u)?null:u,r.call(this),a.start().brush().end()})},o.prototype={beforestart:function(){return 1==++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0==--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){D(new function(t,n,e){this.target=t,this.type=n,this.selection=e}(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:Hn([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:Hn(!!t),e):f},e.handleSize=function(t){return arguments.length?(h=+t,e):h},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function Jn(t){return function(){return t}}function Kn(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function te(){return new Kn}function ne(t){return t.source}function ee(t){return t.target}function re(t){return t.radius}function ie(t){return t.startAngle}function oe(t){return t.endAngle}function ue(){}function ae(t,n){var e=new ue;if(t instanceof ue)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==n)for(;++i<o;)e.set(i,t[i]);else for(;++i<o;)e.set(n(r=t[i],i,t),r)}else if(t)for(var u in t)e.set(u,t[u]);return e}function ce(){return{}}function se(t,n,e){t[n]=e}function fe(){return ae()}function le(t,n,e){t.set(n,e)}function he(){}function pe(t,n){var e=new he;if(t instanceof he)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function de(t){return new Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}")}function ve(t){function n(t,n){function e(){if(s)return bh;if(f)return f=!1,xh;var n,e,r=a;if(t.charCodeAt(r)===wh){for(;a++<u&&t.charCodeAt(a)!==wh||t.charCodeAt(++a)===wh;);return(n=a)>=u?s=!0:(e=t.charCodeAt(a++))===Mh?f=!0:e===Th&&(f=!0,t.charCodeAt(a)===Mh&&++a),t.slice(r+1,n-1).replace(/""/g,'"')}for(;a<u;){if((e=t.charCodeAt(n=a++))===Mh)f=!0;else if(e===Th)f=!0,t.charCodeAt(a)===Mh&&++a;else if(e!==o)continue;return t.slice(r,n)}return s=!0,t.slice(r,u)}var r,i=[],u=t.length,a=0,c=0,s=u<=0,f=!1;for(t.charCodeAt(u-1)===Mh&&--u,t.charCodeAt(u-1)===Th&&--u;(r=e())!==bh;){for(var l=[];r!==xh&&r!==bh;)l.push(r),r=e();n&&null==(l=n(l,c++))||i.push(l)}return i}function e(n){return n.map(r).join(t)}function r(t){return null==t?"":i.test(t+="")?'"'+t.replace(/"/g,'""')+'"':t}var i=new RegExp('["'+t+"\n\r]"),o=t.charCodeAt(0);return{parse:function(t,e){var r,i,o=n(t,function(t,n){if(r)return r(t,n-1);i=t,r=e?function(t,n){var e=de(t);return function(r,i){return n(e(r),i,t)}}(t,e):de(t)});return o.columns=i||[],o},parseRows:n,format:function(n,e){return null==e&&(e=function(t){var n=Object.create(null),e=[];return t.forEach(function(t){for(var r in t)r in n||e.push(n[r]=r)}),e}(n)),[e.map(r).join(t)].concat(n.map(function(n){return e.map(function(t){return r(n[t])}).join(t)})).join("\n")},formatRows:function(t){return t.map(e).join("\n")}}}function ge(t){return function(){return t}}function _e(){return 1e-6*(Math.random()-.5)}function ye(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,g=t._y0,_=t._x1,y=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+_)/2))?v=o:_=o,(f=e>=(u=(g+y)/2))?g=u:y=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do{i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+_)/2))?v=o:_=o,(f=e>=(u=(g+y)/2))?g=u:y=u}while((l=f<<1|s)==(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function me(t,n,e,r,i){this.node=t,this.x0=n,this.y0=e,this.x1=r,this.y1=i}function xe(t){return t[0]}function be(t){return t[1]}function we(t,n,e){var r=new Me(null==n?xe:n,null==e?be:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Me(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function Te(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function Ne(t){return t.x+t.vx}function ke(t){return t.y+t.vy}function Se(t){return t.index}function Ee(t,n){var e=t.get(n);if(!e)throw new Error("missing: "+n);return e}function Ae(t){return t.x}function Ce(t){return t.y}function ze(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]}function Pe(t){return(t=ze(Math.abs(t)))?t[1]:NaN}function Re(t,n){var e=ze(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}function Le(t){return new qe(t)}function qe(t){if(!(n=Ih.exec(t)))throw new Error("invalid format: "+t);var n,e=n[1]||" ",r=n[2]||">",i=n[3]||"-",o=n[4]||"",u=!!n[5],a=n[6]&&+n[6],c=!!n[7],s=n[8]&&+n[8].slice(1),f=n[9]||"";"n"===f?(c=!0,f="g"):Fh[f]||(f=""),(u||"0"===e&&"="===r)&&(u=!0,e="0",r="="),this.fill=e,this.align=r,this.sign=i,this.symbol=o,this.zero=u,this.width=a,this.comma=c,this.precision=s,this.type=f}function De(t){return t}function Ue(t){function n(t){function n(t){var n,r,u,f=g,x=_;if("c"===v)x=y(t)+x,t="";else{var b=(t=+t)<0;if(t=y(Math.abs(t),d),b&&0==+t&&(b=!1),f=(b?"("===s?s:"-":"-"===s||"("===s?"":s)+f,x=x+("s"===v?Bh[8+Dh/3]:"")+(b&&"("===s?")":""),m)for(n=-1,r=t.length;++n<r;)if(48>(u=t.charCodeAt(n))||u>57){x=(46===u?i+t.slice(n+1):t.slice(n))+x,t=t.slice(0,n);break}}p&&!l&&(t=e(t,1/0));var w=f.length+t.length+x.length,M=w<h?new Array(h-w+1).join(a):"";switch(p&&l&&(t=e(M+t,M.length?h-x.length:1/0),M=""),c){case"<":t=f+t+x+M;break;case"=":t=f+M+t+x;break;case"^":t=M.slice(0,w=M.length>>1)+f+t+x+M.slice(w);break;default:t=M+f+t+x}return o(t)}var a=(t=Le(t)).fill,c=t.align,s=t.sign,f=t.symbol,l=t.zero,h=t.width,p=t.comma,d=t.precision,v=t.type,g="$"===f?r[0]:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?r[1]:/[%p]/.test(v)?u:"",y=Fh[v],m=!v||/[defgprs%]/.test(v);return d=null==d?v?6:12:/[gprs]/.test(v)?Math.max(1,Math.min(21,d)):Math.max(0,Math.min(20,d)),n.toString=function(){return t+""},n}var e=t.grouping&&t.thousands?function(t,n){return function(e,r){for(var i=e.length,o=[],u=0,a=t[0],c=0;i>0&&a>0&&(c+a+1>r&&(a=Math.max(1,r-c)),o.push(e.substring(i-=a,i+a)),!((c+=a+1)>r));)a=t[u=(u+1)%t.length];return o.reverse().join(n)}}(t.grouping,t.thousands):De,r=t.currency,i=t.decimal,o=t.numerals?function(t){return function(n){return n.replace(/[0-9]/g,function(n){return t[+n]})}}(t.numerals):De,u=t.percent||"%";return{format:n,formatPrefix:function(t,e){var r=n((t=Le(t),t.type="f",t)),i=3*Math.max(-8,Math.min(8,Math.floor(Pe(e)/3))),o=Math.pow(10,-i),u=Bh[8+i/3];return function(t){return r(o*t)+u}}}}function Oe(n){return Yh=Ue(n),t.format=Yh.format,t.formatPrefix=Yh.formatPrefix,Yh}function Fe(t){return Math.max(0,-Pe(Math.abs(t)))}function Ie(t,n){return Math.max(0,3*Math.max(-8,Math.min(8,Math.floor(Pe(n)/3)))-Pe(Math.abs(t)))}function Ye(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,Pe(n)-Pe(t))+1}function Be(){return new He}function He(){this.reset()}function je(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Xe(t){return t>1?0:t<-1?Mp:Math.acos(t)}function Ve(t){return t>1?Tp:t<-1?-Tp:Math.asin(t)}function $e(t){return(t=Up(t/2))*t}function We(){}function Ze(t,n){t&&Bp.hasOwnProperty(t.type)&&Bp[t.type](t,n)}function Ge(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function Qe(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)Ge(t[e],n,1);n.polygonEnd()}function Je(t,n){t&&Yp.hasOwnProperty(t.type)?Yp[t.type](t,n):Ze(t,n)}function Ke(){Xp.point=nr}function tr(){er(Hh,jh)}function nr(t,n){Xp.point=er,Hh=t,jh=n,Xh=t*=Ep,Vh=Pp(n=(n*=Ep)/2+Np),$h=Up(n)}function er(t,n){n=(n*=Ep)/2+Np;var e=(t*=Ep)-Xh,r=e>=0?1:-1,i=r*e,o=Pp(n),u=Up(n),a=$h*u,c=Vh*o+a*Pp(i),s=a*r*Up(i);Hp.add(zp(s,c)),Xh=t,Vh=o,$h=u}function rr(t){return[zp(t[1],t[0]),Ve(t[2])]}function ir(t){var n=t[0],e=t[1],r=Pp(e);return[r*Pp(n),r*Up(n),Up(e)]}function or(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function ur(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function ar(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function cr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function sr(t){var n=Fp(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function fr(t,n){ep.push(rp=[Wh=t,Gh=t]),n<Zh&&(Zh=n),n>Qh&&(Qh=n)}function lr(t,n){var e=ir([t*Ep,n*Ep]);if(np){var r=ur(np,e),i=ur([r[1],-r[0],0],r);sr(i),i=rr(i);var o,u=t-Jh,a=u>0?1:-1,c=i[0]*Sp*a,s=Ap(u)>180;s^(a*Jh<c&&c<a*t)?(o=i[1]*Sp)>Qh&&(Qh=o):(c=(c+360)%360-180,s^(a*Jh<c&&c<a*t)?(o=-i[1]*Sp)<Zh&&(Zh=o):(n<Zh&&(Zh=n),n>Qh&&(Qh=n))),s?t<Jh?_r(Wh,t)>_r(Wh,Gh)&&(Gh=t):_r(t,Gh)>_r(Wh,Gh)&&(Wh=t):Gh>=Wh?(t<Wh&&(Wh=t),t>Gh&&(Gh=t)):t>Jh?_r(Wh,t)>_r(Wh,Gh)&&(Gh=t):_r(t,Gh)>_r(Wh,Gh)&&(Wh=t)}else ep.push(rp=[Wh=t,Gh=t]);n<Zh&&(Zh=n),n>Qh&&(Qh=n),np=e,Jh=t}function hr(){$p.point=lr}function pr(){rp[0]=Wh,rp[1]=Gh,$p.point=fr,np=null}function dr(t,n){if(np){var e=t-Jh;Vp.add(Ap(e)>180?e+(e>0?360:-360):e)}else Kh=t,tp=n;Xp.point(t,n),lr(t,n)}function vr(){Xp.lineStart()}function gr(){dr(Kh,tp),Xp.lineEnd(),Ap(Vp)>bp&&(Wh=-(Gh=180)),rp[0]=Wh,rp[1]=Gh,np=null}function _r(t,n){return(n-=t)<0?n+360:n}function yr(t,n){return t[0]-n[0]}function mr(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function xr(t,n){t*=Ep;var e=Pp(n*=Ep);br(e*Pp(t),e*Up(t),Up(n))}function br(t,n,e){up+=(t-up)/++ip,ap+=(n-ap)/ip,cp+=(e-cp)/ip}function wr(){Wp.point=Mr}function Mr(t,n){t*=Ep;var e=Pp(n*=Ep);_p=e*Pp(t),yp=e*Up(t),mp=Up(n),Wp.point=Tr,br(_p,yp,mp)}function Tr(t,n){t*=Ep;var e=Pp(n*=Ep),r=e*Pp(t),i=e*Up(t),o=Up(n),u=zp(Fp((u=yp*o-mp*i)*u+(u=mp*r-_p*o)*u+(u=_p*i-yp*r)*u),_p*r+yp*i+mp*o);op+=u,sp+=u*(_p+(_p=r)),fp+=u*(yp+(yp=i)),lp+=u*(mp+(mp=o)),br(_p,yp,mp)}function Nr(){Wp.point=xr}function kr(){Wp.point=Er}function Sr(){Ar(vp,gp),Wp.point=xr}function Er(t,n){vp=t,gp=n,t*=Ep,n*=Ep,Wp.point=Ar;var e=Pp(n);_p=e*Pp(t),yp=e*Up(t),mp=Up(n),br(_p,yp,mp)}function Ar(t,n){t*=Ep;var e=Pp(n*=Ep),r=e*Pp(t),i=e*Up(t),o=Up(n),u=yp*o-mp*i,a=mp*r-_p*o,c=_p*i-yp*r,s=Fp(u*u+a*a+c*c),f=Ve(s),l=s&&-f/s;hp+=l*u,pp+=l*a,dp+=l*c,op+=f,sp+=f*(_p+(_p=r)),fp+=f*(yp+(yp=i)),lp+=f*(mp+(mp=o)),br(_p,yp,mp)}function Cr(t){return function(){return t}}function zr(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return(e=n.invert(e,r))&&t.invert(e[0],e[1])}),e}function Pr(t,n){return[t>Mp?t-kp:t<-Mp?t+kp:t,n]}function Rr(t,n,e){return(t%=kp)?n||e?zr(qr(t),Dr(n,e)):qr(t):n||e?Dr(n,e):Pr}function Lr(t){return function(n,e){return n+=t,[n>Mp?n-kp:n<-Mp?n+kp:n,e]}}function qr(t){var n=Lr(t);return n.invert=Lr(-t),n}function Dr(t,n){function e(t,n){var e=Pp(n),a=Pp(t)*e,c=Up(t)*e,s=Up(n),f=s*r+a*i;return[zp(c*o-f*u,a*r-s*i),Ve(f*o+c*u)]}var r=Pp(t),i=Up(t),o=Pp(n),u=Up(n);return e.invert=function(t,n){var e=Pp(n),a=Pp(t)*e,c=Up(t)*e,s=Up(n),f=s*o-c*u;return[zp(c*o+s*u,a*r+f*i),Ve(f*r-a*i)]},e}function Ur(t){function n(n){return n=t(n[0]*Ep,n[1]*Ep),n[0]*=Sp,n[1]*=Sp,n}return t=Rr(t[0]*Ep,t[1]*Ep,t.length>2?t[2]*Ep:0),n.invert=function(n){return n=t.invert(n[0]*Ep,n[1]*Ep),n[0]*=Sp,n[1]*=Sp,n},n}function Or(t,n,e,r,i,o){if(e){var u=Pp(n),a=Up(n),c=r*e;null==i?(i=n+r*kp,o=n-c/2):(i=Fr(u,i),o=Fr(u,o),(r>0?i<o:i>o)&&(i+=r*kp));for(var s,f=i;r>0?f>o:f<o;f-=c)s=rr([u,-a*Pp(f),-a*Up(f)]),t.point(s[0],s[1])}}function Fr(t,n){(n=ir(n))[0]-=t,sr(n);var e=Xe(-n[1]);return((-n[2]<0?-e:e)+kp-bp)%kp}function Ir(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:We,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}}function Yr(t,n){return Ap(t[0]-n[0])<bp&&Ap(t[1]-n[1])<bp}function Br(t,n,e,r){this.x=t,this.z=n,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Hr(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if(Yr(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);i.lineEnd()}else a.push(e=new Br(r,t,null,!0)),c.push(e.o=new Br(r,null,e,!1)),a.push(e=new Br(u,t,null,!1)),c.push(e.o=new Br(u,null,e,!0))}}),a.length){for(c.sort(n),jr(a),jr(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}s=(h=h.o).z,p=!p}while(!h.v);i.lineEnd()}}}function jr(t){if(n=t.length){for(var n,e,r=0,i=t[0];++r<n;)i.n=e=t[r],e.p=i,i=e;i.n=e=t[0],e.p=i}}function Xr(t,n){var e=n[0],r=n[1],i=[Up(e),-Pp(e),0],o=0,u=0;ud.reset();for(var a=0,c=t.length;a<c;++a)if(f=(s=t[a]).length)for(var s,f,l=s[f-1],h=l[0],p=l[1]/2+Np,d=Up(p),v=Pp(p),g=0;g<f;++g,h=y,d=x,v=b,l=_){var _=s[g],y=_[0],m=_[1]/2+Np,x=Up(m),b=Pp(m),w=y-h,M=w>=0?1:-1,T=M*w,N=T>Mp,k=d*x;if(ud.add(zp(k*M*Up(T),v*b+k*Pp(T))),o+=N?w+M*kp:w,N^h>=e^y>=e){var S=ur(ir(l),ir(_));sr(S);var E=ur(i,S);sr(E);var A=(N^w>=0?-1:1)*Ve(E[2]);(r>A||r===A&&(S[0]||S[1]))&&(u+=N^w>=0?1:-1)}}return(o<-bp||o<bp&&ud<-bp)^1&u}function Vr(t,n,e,r){return function(i){function o(n,e){t(n,e)&&i.point(n,e)}function u(t,n){v.point(t,n)}function a(){x.point=u,v.lineStart()}function c(){x.point=o,v.lineEnd()}function s(t,n){d.push([t,n]),y.point(t,n)}function f(){y.lineStart(),d=[]}function l(){s(d[0][0],d[0][1]),y.lineEnd();var t,n,e,r,o=y.clean(),u=_.result(),a=u.length;if(d.pop(),h.push(d),d=null,a)if(1&o){if(e=u[0],(n=e.length-1)>0){for(m||(i.polygonStart(),m=!0),i.lineStart(),t=0;t<n;++t)i.point((r=e[t])[0],r[1]);i.lineEnd()}}else a>1&&2&o&&u.push(u.pop().concat(u.shift())),p.push(u.filter($r))}var h,p,d,v=n(i),_=Ir(),y=n(_),m=!1,x={point:o,lineStart:a,lineEnd:c,polygonStart:function(){x.point=s,x.lineStart=f,x.lineEnd=l,p=[],h=[]},polygonEnd:function(){x.point=o,x.lineStart=a,x.lineEnd=c,p=g(p);var t=Xr(h,r);p.length?(m||(i.polygonStart(),m=!0),Hr(p,Wr,t,e,i)):t&&(m||(i.polygonStart(),m=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),m&&(i.polygonEnd(),m=!1),p=h=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}};return x}}function $r(t){return t.length>1}function Wr(t,n){return((t=t.x)[0]<0?t[1]-Tp-bp:Tp-t[1])-((n=n.x)[0]<0?n[1]-Tp-bp:Tp-n[1])}function Zr(t){function n(t,n){return Pp(t)*Pp(n)>i}function e(t,n,e){var r=[1,0,0],o=ur(ir(t),ir(n)),u=or(o,o),a=o[0],c=u-a*a;if(!c)return!e&&t;var s=i*u/c,f=-i*a/c,l=ur(r,o),h=cr(r,s);ar(h,cr(o,f));var p=l,d=or(h,p),v=or(p,p),g=d*d-v*(or(h,h)-1);if(!(g<0)){var _=Fp(g),y=cr(p,(-d-_)/v);if(ar(y,h),y=rr(y),!e)return y;var m,x=t[0],b=n[0],w=t[1],M=n[1];b<x&&(m=x,x=b,b=m);var T=b-x,N=Ap(T-Mp)<bp;if(!N&&M<w&&(m=w,w=M,M=m),N||T<bp?N?w+M>0^y[1]<(Ap(y[0]-x)<bp?w:M):w<=y[1]&&y[1]<=M:T>Mp^(x<=y[0]&&y[0]<=b)){var k=cr(p,(-d+_)/v);return ar(k,h),[y,rr(k)]}}}function r(n,e){var r=u?t:Mp-t,i=0;return n<-r?i|=1:n>r&&(i|=2),e<-r?i|=4:e>r&&(i|=8),i}var i=Pp(t),o=6*Ep,u=i>0,a=Ap(i)>bp;return Vr(n,function(t){var i,o,c,s,f;return{lineStart:function(){s=c=!1,f=1},point:function(l,h){var p,d=[l,h],v=n(l,h),g=u?v?0:r(l,h):v?r(l+(l<0?Mp:-Mp),h):0;if(!i&&(s=c=v)&&t.lineStart(),v!==c&&(!(p=e(i,d))||Yr(i,p)||Yr(d,p))&&(d[0]+=bp,d[1]+=bp,v=n(d[0],d[1])),v!==c)f=0,v?(t.lineStart(),p=e(d,i),t.point(p[0],p[1])):(p=e(i,d),t.point(p[0],p[1]),t.lineEnd()),i=p;else if(a&&i&&u^v){var _;g&o||!(_=e(d,i,!0))||(f=0,u?(t.lineStart(),t.point(_[0][0],_[0][1]),t.point(_[1][0],_[1][1]),t.lineEnd()):(t.point(_[1][0],_[1][1]),t.lineEnd(),t.lineStart(),t.point(_[0][0],_[0][1])))}!v||i&&Yr(i,d)||t.point(d[0],d[1]),i=d,c=v,o=g},lineEnd:function(){c&&t.lineEnd(),i=null},clean:function(){return f|(s&&c)<<1}}},function(n,e,r,i){Or(i,t,o,r,n,e)},u?[0,-t]:[-Mp,t-Mp])}function Gr(t,n,e,r){function i(i,o){return t<=i&&i<=e&&n<=o&&o<=r}function o(i,o,a,s){var f=0,l=0;if(null==i||(f=u(i,a))!==(l=u(o,a))||c(i,o)<0^a>0)do{s.point(0===f||3===f?t:e,f>1?r:n)}while((f=(f+a+4)%4)!==l);else s.point(o[0],o[1])}function u(r,i){return Ap(r[0]-t)<bp?i>0?0:3:Ap(r[0]-e)<bp?i>0?2:1:Ap(r[1]-n)<bp?i>0?1:0:i>0?3:2}function a(t,n){return c(t.x,n.x)}function c(t,n){var e=u(t,1),r=u(n,1);return e!==r?e-r:0===e?n[1]-t[1]:1===e?t[0]-n[0]:2===e?t[1]-n[1]:n[0]-t[0]}return function(u){function c(t,n){i(t,n)&&w.point(t,n)}function s(o,u){var a=i(o,u);if(l&&h.push([o,u]),x)p=o,d=u,v=a,x=!1,a&&(w.lineStart(),w.point(o,u));else if(a&&m)w.point(o,u);else{var c=[_=Math.max(sd,Math.min(cd,_)),y=Math.max(sd,Math.min(cd,y))],s=[o=Math.max(sd,Math.min(cd,o)),u=Math.max(sd,Math.min(cd,u))];!function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=0,f=1,l=n[0]-a,h=n[1]-c;if(u=e-a,l||!(u>0)){if(u/=l,l<0){if(u<s)return;u<f&&(f=u)}else if(l>0){if(u>f)return;u>s&&(s=u)}if(u=i-a,l||!(u<0)){if(u/=l,l<0){if(u>f)return;u>s&&(s=u)}else if(l>0){if(u<s)return;u<f&&(f=u)}if(u=r-c,h||!(u>0)){if(u/=h,h<0){if(u<s)return;u<f&&(f=u)}else if(h>0){if(u>f)return;u>s&&(s=u)}if(u=o-c,h||!(u<0)){if(u/=h,h<0){if(u>f)return;u>s&&(s=u)}else if(h>0){if(u<s)return;u<f&&(f=u)}return s>0&&(t[0]=a+s*l,t[1]=c+s*h),f<1&&(n[0]=a+f*l,n[1]=c+f*h),!0}}}}}(c,s,t,n,e,r)?a&&(w.lineStart(),w.point(o,u),b=!1):(m||(w.lineStart(),w.point(c[0],c[1])),w.point(s[0],s[1]),a||w.lineEnd(),b=!1)}_=o,y=u,m=a}var f,l,h,p,d,v,_,y,m,x,b,w=u,M=Ir(),T={point:c,lineStart:function(){T.point=s,l&&l.push(h=[]),x=!0,m=!1,_=y=NaN},lineEnd:function(){f&&(s(p,d),v&&m&&M.rejoin(),f.push(M.result())),T.point=c,m&&w.lineEnd()},polygonStart:function(){w=M,f=[],l=[],b=!0},polygonEnd:function(){var n=function(){for(var n=0,e=0,i=l.length;e<i;++e)for(var o,u,a=l[e],c=1,s=a.length,f=a[0],h=f[0],p=f[1];c<s;++c)o=h,u=p,h=(f=a[c])[0],p=f[1],u<=r?p>r&&(h-o)*(r-u)>(p-u)*(t-o)&&++n:p<=r&&(h-o)*(r-u)<(p-u)*(t-o)&&--n;return n}(),e=b&&n,i=(f=g(f)).length;(e||i)&&(u.polygonStart(),e&&(u.lineStart(),o(null,null,1,u),u.lineEnd()),i&&Hr(f,a,n,o,u),u.polygonEnd()),w=u,f=l=h=null}};return T}}function Qr(){ld.point=ld.lineEnd=We}function Jr(t,n){Zp=t*=Ep,Gp=Up(n*=Ep),Qp=Pp(n),ld.point=Kr}function Kr(t,n){t*=Ep;var e=Up(n*=Ep),r=Pp(n),i=Ap(t-Zp),o=Pp(i),u=r*Up(i),a=Qp*e-Gp*r*o,c=Gp*e+Qp*r*o;fd.add(zp(Fp(u*u+a*a),c)),Zp=t,Gp=e,Qp=r}function ti(t){return fd.reset(),Je(t,ld),+fd}function ni(t,n){return hd[0]=t,hd[1]=n,ti(pd)}function ei(t,n){return!(!t||!vd.hasOwnProperty(t.type))&&vd[t.type](t,n)}function ri(t,n){return 0===ni(t,n)}function ii(t,n){var e=ni(t[0],t[1]);return ni(t[0],n)+ni(n,t[1])<=e+bp}function oi(t,n){return!!Xr(t.map(ui),ai(n))}function ui(t){return(t=t.map(ai)).pop(),t}function ai(t){return[t[0]*Ep,t[1]*Ep]}function ci(t,n,e){var r=f(t,n-bp,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function si(t,n,e){var r=f(t,n-bp,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function fi(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return f(Rp(o/_)*_,i,_).map(p).concat(f(Rp(s/y)*y,c,y).map(d)).concat(f(Rp(r/v)*v,e,v).filter(function(t){return Ap(t%_)>bp}).map(l)).concat(f(Rp(a/g)*g,u,g).filter(function(t){return Ap(t%y)>bp}).map(h))}var e,r,i,o,u,a,c,s,l,h,p,d,v=10,g=v,_=90,y=360,m=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[p(o).concat(d(c).slice(1),p(i).reverse().slice(1),d(s).reverse().slice(1))]}},t.extent=function(n){return arguments.length?t.extentMajor(n).extentMinor(n):t.extentMinor()},t.extentMajor=function(n){return arguments.length?(o=+n[0][0],i=+n[1][0],s=+n[0][1],c=+n[1][1],o>i&&(n=o,o=i,i=n),s>c&&(n=s,s=c,c=n),t.precision(m)):[[o,s],[i,c]]},t.extentMinor=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],a=+n[0][1],u=+n[1][1],r>e&&(n=r,r=e,e=n),a>u&&(n=a,a=u,u=n),t.precision(m)):[[r,a],[e,u]]},t.step=function(n){return arguments.length?t.stepMajor(n).stepMinor(n):t.stepMinor()},t.stepMajor=function(n){return arguments.length?(_=+n[0],y=+n[1],t):[_,y]},t.stepMinor=function(n){return arguments.length?(v=+n[0],g=+n[1],t):[v,g]},t.precision=function(n){return arguments.length?(m=+n,l=ci(a,u,90),h=si(r,e,m),p=ci(s,c,90),d=si(o,i,m),t):m},t.extentMajor([[-180,-90+bp],[180,90-bp]]).extentMinor([[-180,-80-bp],[180,80+bp]])}function li(t){return t}function hi(){yd.point=pi}function pi(t,n){yd.point=di,Jp=td=t,Kp=nd=n}function di(t,n){_d.add(nd*t-td*n),td=t,nd=n}function vi(){di(Jp,Kp)}function gi(t,n){Td+=t,Nd+=n,++kd}function _i(){Rd.point=yi}function yi(t,n){Rd.point=mi,gi(id=t,od=n)}function mi(t,n){var e=t-id,r=n-od,i=Fp(e*e+r*r);Sd+=i*(id+t)/2,Ed+=i*(od+n)/2,Ad+=i,gi(id=t,od=n)}function xi(){Rd.point=gi}function bi(){Rd.point=Mi}function wi(){Ti(ed,rd)}function Mi(t,n){Rd.point=Ti,gi(ed=id=t,rd=od=n)}function Ti(t,n){var e=t-id,r=n-od,i=Fp(e*e+r*r);Sd+=i*(id+t)/2,Ed+=i*(od+n)/2,Ad+=i,Cd+=(i=od*t-id*n)*(id+t),zd+=i*(od+n),Pd+=3*i,gi(id=t,od=n)}function Ni(t){this._context=t}function ki(t,n){Id.point=Si,qd=Ud=t,Dd=Od=n}function Si(t,n){Ud-=t,Od-=n,Fd.add(Fp(Ud*Ud+Od*Od)),Ud=t,Od=n}function Ei(){this._string=[]}function Ai(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Ci(t){return function(n){var e=new zi;for(var r in t)e[r]=t[r];return e.stream=n,e}}function zi(){}function Pi(t,n,e){var r=t.clipExtent&&t.clipExtent();return t.scale(150).translate([0,0]),null!=r&&t.clipExtent(null),Je(e,t.stream(Md)),n(Md.result()),null!=r&&t.clipExtent(r),t}function Ri(t,n,e){return Pi(t,function(e){var r=n[1][0]-n[0][0],i=n[1][1]-n[0][1],o=Math.min(r/(e[1][0]-e[0][0]),i/(e[1][1]-e[0][1])),u=+n[0][0]+(r-o*(e[1][0]+e[0][0]))/2,a=+n[0][1]+(i-o*(e[1][1]+e[0][1]))/2;t.scale(150*o).translate([u,a])},e)}function Li(t,n,e){return Ri(t,[[0,0],n],e)}function qi(t,n,e){return Pi(t,function(e){var r=+n,i=r/(e[1][0]-e[0][0]),o=(r-i*(e[1][0]+e[0][0]))/2,u=-i*e[0][1];t.scale(150*i).translate([o,u])},e)}function Di(t,n,e){return Pi(t,function(e){var r=+n,i=r/(e[1][1]-e[0][1]),o=-i*e[0][0],u=(r-i*(e[1][1]+e[0][1]))/2;t.scale(150*i).translate([o,u])},e)}function Ui(t,n){return+n?function(t,n){function e(r,i,o,u,a,c,s,f,l,h,p,d,v,g){var _=s-r,y=f-i,m=_*_+y*y;if(m>4*n&&v--){var x=u+h,b=a+p,w=c+d,M=Fp(x*x+b*b+w*w),T=Ve(w/=M),N=Ap(Ap(w)-1)<bp||Ap(o-l)<bp?(o+l)/2:zp(b,x),k=t(N,T),S=k[0],E=k[1],A=S-r,C=E-i,z=y*A-_*C;(z*z/m>n||Ap((_*A+y*C)/m-.5)>.3||u*h+a*p+c*d<Bd)&&(e(r,i,o,u,a,c,S,E,N,x/=M,b/=M,w,v,g),g.point(S,E),e(S,E,N,x,b,w,s,f,l,h,p,d,v,g))}}return function(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function i(){_=NaN,w.point=o,n.lineStart()}function o(r,i){var o=ir([r,i]),u=t(r,i);e(_,y,g,m,x,b,_=u[0],y=u[1],g=r,m=o[0],x=o[1],b=o[2],Yd,n),n.point(_,y)}function u(){w.point=r,n.lineEnd()}function a(){i(),w.point=c,w.lineEnd=s}function c(t,n){o(f=t,n),l=_,h=y,p=m,d=x,v=b,w.point=o}function s(){e(_,y,g,m,x,b,l,h,f,p,d,v,Yd,n),w.lineEnd=u,u()}var f,l,h,p,d,v,g,_,y,m,x,b,w={point:r,lineStart:i,lineEnd:u,polygonStart:function(){n.polygonStart(),w.lineStart=a},polygonEnd:function(){n.polygonEnd(),w.lineStart=i}};return w}}(t,n):function(t){return Ci({point:function(n,e){n=t(n,e),this.stream.point(n[0],n[1])}})}(t)}function Oi(t){return Fi(function(){return t})()}function Fi(t){function n(t){return t=s(t[0]*Ep,t[1]*Ep),[t[0]*v+u,a-t[1]*v]}function e(t,n){return t=o(t,n),[t[0]*v+u,a-t[1]*v]}function r(){s=zr(c=Rr(x,b,w),o);var t=o(y,m);return u=g-t[0]*v,a=_+t[1]*v,i()}function i(){return p=d=null,n}var o,u,a,c,s,f,l,h,p,d,v=150,g=480,_=250,y=0,m=0,x=0,b=0,w=0,M=null,T=ad,N=null,k=li,S=.5,E=Ui(e,S);return n.stream=function(t){return p&&d===t?p:p=Hd(function(t){return Ci({point:function(n,e){var r=t(n,e);return this.stream.point(r[0],r[1])}})}(c)(T(E(k(d=t)))))},n.preclip=function(t){return arguments.length?(T=t,M=void 0,i()):T},n.postclip=function(t){return arguments.length?(k=t,N=f=l=h=null,i()):k},n.clipAngle=function(t){return arguments.length?(T=+t?Zr(M=t*Ep):(M=null,ad),i()):M*Sp},n.clipExtent=function(t){return arguments.length?(k=null==t?(N=f=l=h=null,li):Gr(N=+t[0][0],f=+t[0][1],l=+t[1][0],h=+t[1][1]),i()):null==N?null:[[N,f],[l,h]]},n.scale=function(t){return arguments.length?(v=+t,r()):v},n.translate=function(t){return arguments.length?(g=+t[0],_=+t[1],r()):[g,_]},n.center=function(t){return arguments.length?(y=t[0]%360*Ep,m=t[1]%360*Ep,r()):[y*Sp,m*Sp]},n.rotate=function(t){return arguments.length?(x=t[0]%360*Ep,b=t[1]%360*Ep,w=t.length>2?t[2]%360*Ep:0,r()):[x*Sp,b*Sp,w*Sp]},n.precision=function(t){return arguments.length?(E=Ui(e,S=t*t),i()):Fp(S)},n.fitExtent=function(t,e){return Ri(n,t,e)},n.fitSize=function(t,e){return Li(n,t,e)},n.fitWidth=function(t,e){return qi(n,t,e)},n.fitHeight=function(t,e){return Di(n,t,e)},function(){return o=t.apply(this,arguments),n.invert=o.invert&&function(t){return(t=s.invert((t[0]-u)/v,(a-t[1])/v))&&[t[0]*Sp,t[1]*Sp]},r()}}function Ii(t){var n=0,e=Mp/3,r=Fi(t),i=r(n,e);return i.parallels=function(t){return arguments.length?r(n=t[0]*Ep,e=t[1]*Ep):[n*Sp,e*Sp]},i}function Yi(t,n){function e(t,n){var e=Fp(o-2*i*Up(n))/i;return[e*Up(t*=i),u-e*Pp(t)]}var r=Up(t),i=(r+Up(n))/2;if(Ap(i)<bp)return function(t){function n(t,n){return[t*e,Up(n)/e]}var e=Pp(t);return n.invert=function(t,n){return[t/e,Ve(n*e)]},n}(t);var o=1+r*(2*i-r),u=Fp(o)/i;return e.invert=function(t,n){var e=u-n;return[zp(t,Ap(e))/i*Op(e),Ve((o-(t*t+e*e)*i*i)/(2*i))]},e}function Bi(){return Ii(Yi).scale(155.424).center([0,33.6442])}function Hi(){return Bi().parallels([29.5,45.5]).scale(1070).translate([480,250]).rotate([96,0]).center([-.6,38.7])}function ji(t){return function(n,e){var r=Pp(n),i=Pp(e),o=t(r*i);return[o*i*Up(n),o*Up(e)]}}function Xi(t){return function(n,e){var r=Fp(n*n+e*e),i=t(r),o=Up(i),u=Pp(i);return[zp(n*o,r*u),Ve(r&&e*o/r)]}}function Vi(t,n){return[t,qp(Ip((Tp+n)/2))]}function $i(t){function n(){var n=Mp*a(),u=o(Ur(o.rotate()).invert([0,0]));return s(null==f?[[u[0]-n,u[1]-n],[u[0]+n,u[1]+n]]:t===Vi?[[Math.max(u[0]-n,f),e],[Math.min(u[0]+n,r),i]]:[[f,Math.max(u[1]-n,e)],[r,Math.min(u[1]+n,i)]])}var e,r,i,o=Oi(t),u=o.center,a=o.scale,c=o.translate,s=o.clipExtent,f=null;return o.scale=function(t){return arguments.length?(a(t),n()):a()},o.translate=function(t){return arguments.length?(c(t),n()):c()},o.center=function(t){return arguments.length?(u(t),n()):u()},o.clipExtent=function(t){return arguments.length?(null==t?f=e=r=i=null:(f=+t[0][0],e=+t[0][1],r=+t[1][0],i=+t[1][1]),n()):null==f?null:[[f,e],[r,i]]},n()}function Wi(t){return Ip((Tp+t)/2)}function Zi(t,n){function e(t,n){o>0?n<-Tp+bp&&(n=-Tp+bp):n>Tp-bp&&(n=Tp-bp);var e=o/Dp(Wi(n),i);return[e*Up(i*t),o-e*Pp(i*t)]}var r=Pp(t),i=t===n?Up(t):qp(r/Pp(n))/qp(Wi(n)/Wi(t)),o=r*Dp(Wi(t),i)/i;return i?(e.invert=function(t,n){var e=o-n,r=Op(i)*Fp(t*t+e*e);return[zp(t,Ap(e))/i*Op(e),2*Cp(Dp(o/r,1/i))-Tp]},e):Vi}function Gi(t,n){return[t,n]}function Qi(t,n){function e(t,n){var e=o-n,r=i*t;return[e*Up(r),o-e*Pp(r)]}var r=Pp(t),i=t===n?Up(t):(r-Pp(n))/(n-t),o=r/i+t;return Ap(i)<bp?Gi:(e.invert=function(t,n){var e=o-n;return[zp(t,Ap(e))/i*Op(e),o-Op(i)*Fp(t*t+e*e)]},e)}function Ji(t,n){var e=Pp(n),r=Pp(t)*e;return[e*Up(t)/r,Up(n)/r]}function Ki(t,n,e,r){return 1===t&&1===n&&0===e&&0===r?li:Ci({point:function(i,o){this.stream.point(i*t+e,o*n+r)}})}function to(t,n){var e=n*n,r=e*e;return[t*(.8707-.131979*e+r*(r*(.003971*e-.001529*r)-.013791)),n*(1.007226+e*(.015085+r*(.028874*e-.044475-.005916*r)))]}function no(t,n){return[Pp(n)*Up(t),Up(n)]}function eo(t,n){var e=Pp(n),r=1+Pp(t)*e;return[e*Up(t)/r,Up(n)/r]}function ro(t,n){return[qp(Ip((Tp+n)/2)),-t]}function io(t,n){return t.parent===n.parent?1:2}function oo(t,n){return t+n.x}function uo(t,n){return Math.max(t,n.y)}function ao(t){var n=0,e=t.children,r=e&&e.length;if(r)for(;--r>=0;)n+=e[r].value;else n=1;t.value=n}function co(t,n){var e,r,i,o,u,a=new ho(t),c=+t.value&&(a.value=t.value),s=[a];for(null==n&&(n=so);e=s.pop();)if(c&&(e.value=+e.data.value),(i=n(e.data))&&(u=i.length))for(e.children=new Array(u),o=u-1;o>=0;--o)s.push(r=e.children[o]=new ho(i[o])),r.parent=e,r.depth=e.depth+1;return a.eachBefore(lo)}function so(t){return t.children}function fo(t){t.data=t.data.data}function lo(t){var n=0;do{t.height=n}while((t=t.parent)&&t.height<++n)}function ho(t){this.data=t,this.depth=this.height=0,this.parent=null}function po(t){for(var n,e,r=0,i=(t=function(t){for(var n,e,r=t.length;r;)e=Math.random()*r--|0,n=t[r],t[r]=t[e],t[e]=n;return t}(Vd.call(t))).length,o=[];r<i;)n=t[r],e&&go(e,n)?++r:(e=function(t){switch(t.length){case 1:return function(t){return{x:t.x,y:t.y,r:t.r}}(t[0]);case 2:return yo(t[0],t[1]);case 3:return mo(t[0],t[1],t[2])}}(o=function(t,n){var e,r;if(_o(n,t))return[n];for(e=0;e<t.length;++e)if(vo(n,t[e])&&_o(yo(t[e],n),t))return[t[e],n];for(e=0;e<t.length-1;++e)for(r=e+1;r<t.length;++r)if(vo(yo(t[e],t[r]),n)&&vo(yo(t[e],n),t[r])&&vo(yo(t[r],n),t[e])&&_o(mo(t[e],t[r],n),t))return[t[e],t[r],n];throw new Error}(o,n)),r=0);return e}function vo(t,n){var e=t.r-n.r,r=n.x-t.x,i=n.y-t.y;return e<0||e*e<r*r+i*i}function go(t,n){var e=t.r-n.r+1e-6,r=n.x-t.x,i=n.y-t.y;return e>0&&e*e>r*r+i*i}function _o(t,n){for(var e=0;e<n.length;++e)if(!go(t,n[e]))return!1;return!0}function yo(t,n){var e=t.x,r=t.y,i=t.r,o=n.x,u=n.y,a=n.r,c=o-e,s=u-r,f=a-i,l=Math.sqrt(c*c+s*s);return{x:(e+o+c/l*f)/2,y:(r+u+s/l*f)/2,r:(l+i+a)/2}}function mo(t,n,e){var r=t.x,i=t.y,o=t.r,u=n.x,a=n.y,c=n.r,s=e.x,f=e.y,l=e.r,h=r-u,p=r-s,d=i-a,v=i-f,g=c-o,_=l-o,y=r*r+i*i-o*o,m=y-u*u-a*a+c*c,x=y-s*s-f*f+l*l,b=p*d-h*v,w=(d*x-v*m)/(2*b)-r,M=(v*g-d*_)/b,T=(p*m-h*x)/(2*b)-i,N=(h*_-p*g)/b,k=M*M+N*N-1,S=2*(o+w*M+T*N),E=w*w+T*T-o*o,A=-(k?(S+Math.sqrt(S*S-4*k*E))/(2*k):E/S);return{x:r+w+M*A,y:i+T+N*A,r:A}}function xo(t,n,e){var r=t.x,i=t.y,o=n.r+e.r,u=t.r+e.r,a=n.x-r,c=n.y-i,s=a*a+c*c;if(s){var f=.5+((u*=u)-(o*=o))/(2*s),l=Math.sqrt(Math.max(0,2*o*(u+s)-(u-=s)*u-o*o))/(2*s);e.x=r+f*a+l*c,e.y=i+f*c-l*a}else e.x=r+u,e.y=i}function bo(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i-1e-6>e*e+r*r}function wo(t){var n=t._,e=t.next._,r=n.r+e.r,i=(n.x*e.r+e.x*n.r)/r,o=(n.y*e.r+e.y*n.r)/r;return i*i+o*o}function Mo(t){this._=t,this.next=null,this.previous=null}function To(t){if(!(i=t.length))return 0;var n,e,r,i,o,u,a,c,s,f,l;if(n=t[0],n.x=0,n.y=0,!(i>1))return n.r;if(e=t[1],n.x=-e.r,e.x=n.r,e.y=0,!(i>2))return n.r+e.r;xo(e,n,r=t[2]),n=new Mo(n),e=new Mo(e),r=new Mo(r),n.next=r.previous=e,e.next=n.previous=r,r.next=e.previous=n;t:for(a=3;a<i;++a){xo(n._,e._,r=t[a]),r=new Mo(r),c=e.next,s=n.previous,f=e._.r,l=n._.r;do{if(f<=l){if(bo(c._,r._)){e=c,n.next=e,e.previous=n,--a;continue t}f+=c._.r,c=c.next}else{if(bo(s._,r._)){(n=s).next=e,e.previous=n,--a;continue t}l+=s._.r,s=s.previous}}while(c!==s.next);for(r.previous=n,r.next=e,n.next=e.previous=e=r,o=wo(n);(r=r.next)!==e;)(u=wo(r))<o&&(n=r,o=u);e=n.next}for(n=[e._],r=e;(r=r.next)!==e;)n.push(r._);for(r=po(n),a=0;a<i;++a)n=t[a],n.x-=r.x,n.y-=r.y;return r.r}function No(t){if("function"!=typeof t)throw new Error;return t}function ko(){return 0}function So(t){return function(){return t}}function Eo(t){return Math.sqrt(t.value)}function Ao(t){return function(n){n.children||(n.r=Math.max(0,+t(n)||0))}}function Co(t,n){return function(e){if(r=e.children){var r,i,o,u=r.length,a=t(e)*n||0;if(a)for(i=0;i<u;++i)r[i].r+=a;if(o=To(r),a)for(i=0;i<u;++i)r[i].r-=a;e.r=o+a}}}function zo(t){return function(n){var e=n.parent;n.r*=t,e&&(n.x=e.x+t*n.x,n.y=e.y+t*n.y)}}function Po(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function Ro(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)(o=u[a]).y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s}function Lo(t){return t.id}function qo(t){return t.parentId}function Do(t,n){return t.parent===n.parent?1:2}function Uo(t){var n=t.children;return n?n[0]:t.t}function Oo(t){var n=t.children;return n?n[n.length-1]:t.t}function Fo(t,n,e){var r=e/(n.i-t.i);n.c-=r,n.s+=e,t.c+=r,n.z+=e,n.m+=e}function Io(t,n,e){return t.a.parent===n.parent?t.a:e}function Yo(t,n){this._=t,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=n}function Bo(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(i-e)/t.value;++a<c;)(o=u[a]).x0=n,o.x1=r,o.y0=e,o.y1=e+=o.value*s}function Ho(t,n,e,r,i,o){for(var u,a,c,s,f,l,h,p,d,v,g,_=[],y=n.children,m=0,x=0,b=y.length,w=n.value;m<b;){c=i-e,s=o-r;do{f=y[x++].value}while(!f&&x<b);for(l=h=f,g=f*f*(v=Math.max(s/c,c/s)/(w*t)),d=Math.max(h/g,g/l);x<b;++x){if(f+=a=y[x].value,a<l&&(l=a),a>h&&(h=a),g=f*f*v,(p=Math.max(h/g,g/l))>d){f-=a;break}d=p}_.push(u={value:f,dice:c<s,children:y.slice(m,x)}),u.dice?Ro(u,e,r,i,w?r+=s*f/w:o):Bo(u,e,r,w?e+=c*f/w:i,o),w-=f,m=x}return _}function jo(t,n,e){return(n[0]-t[0])*(e[1]-t[1])-(n[1]-t[1])*(e[0]-t[0])}function Xo(t,n){return t[0]-n[0]||t[1]-n[1]}function Vo(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&jo(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function $o(t){this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function Wo(t){if(!t._start)try{(function(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=function(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?Zo(t,e):(t._data[n]=r,t._waiting?Wo(t):Go(t))))}}(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||tv)}})(t)}catch(n){if(t._tasks[t._ended+t._active-1])Zo(t,n);else if(!t._data)throw n}}function Zo(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(n){}t._active=NaN,Go(t)}function Go(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Qo(t){if(null==t)t=1/0;else if(!((t=+t)>=1))throw new Error("invalid concurrency");return new $o(t)}function Jo(){return Math.random()}function Ko(t,n){function e(t){var n,e=s.status;if(!e&&function(t){var n=t.responseType;return n&&"text"!==n?t.response:t.responseText}(s)||e>=200&&e<300||304===e){if(o)try{n=o.call(r,s)}catch(t){return void a.call("error",r,t)}else n=s;a.call("load",r,n)}else a.call("error",r,t)}var r,i,o,u,a=N("beforesend","progress","load","error"),c=ae(),s=new XMLHttpRequest,f=null,l=null,h=0;if("undefined"==typeof XDomainRequest||"withCredentials"in s||!/^(http(s)?:)?\/\//.test(t)||(s=new XDomainRequest),"onload"in s?s.onload=s.onerror=s.ontimeout=e:s.onreadystatechange=function(t){s.readyState>3&&e(t)},s.onprogress=function(t){a.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?c.get(t):(null==n?c.remove(t):c.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(u=t,r):u},timeout:function(t){return arguments.length?(h=+t,r):h},user:function(t){return arguments.length<1?f:(f=null==t?null:t+"",r)},password:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},response:function(t){return o=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return s.open(n,t,!0,f,l),null==i||c.has("accept")||c.set("accept",i+",*/*"),s.setRequestHeader&&c.each(function(t,n){s.setRequestHeader(n,t)}),null!=i&&s.overrideMimeType&&s.overrideMimeType(i),null!=u&&(s.responseType=u),h>0&&(s.timeout=h),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=function(t){return function(n,e){t(null==n?e:null)}}(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),a.call("beforesend",r,s),s.send(null==e?null:e),r},abort:function(){return s.abort(),r},on:function(){var t=a.on.apply(a,arguments);return t===a?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r}function tu(t,n){return function(e,r){var i=Ko(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}}function nu(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=Ko(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(function(t,n){return function(e){return t(e.responseText,n)}}(n,r=t)):r},o.row(r),i?o.get(i):o}}function eu(t){function n(n){var o=n+"",u=e.get(o);if(!u){if(i!==gv)return i;e.set(o,u=r.push(n))}return t[(u-1)%t.length]}var e=ae(),r=[],i=gv;return t=null==t?[]:vv.call(t),n.domain=function(t){if(!arguments.length)return r.slice();r=[],e=ae();for(var i,o,u=-1,a=t.length;++u<a;)e.has(o=(i=t[u])+"")||e.set(o,r.push(i));return n},n.range=function(e){return arguments.length?(t=vv.call(e),n):t.slice()},n.unknown=function(t){return arguments.length?(i=t,n):i},n.copy=function(){return eu().domain(r).range(t).unknown(i)},n}function ru(){function t(){var t=i().length,r=u[1]<u[0],h=u[r-0],p=u[1-r];n=(p-h)/Math.max(1,t-c+2*s),a&&(n=Math.floor(n)),h+=(p-h-n*(t-c))*l,e=n*(1-c),a&&(h=Math.round(h),e=Math.round(e));var d=f(t).map(function(t){return h+n*t});return o(r?d.reverse():d)}var n,e,r=eu().unknown(void 0),i=r.domain,o=r.range,u=[0,1],a=!1,c=0,s=0,l=.5;return delete r.unknown,r.domain=function(n){return arguments.length?(i(n),t()):i()},r.range=function(n){return arguments.length?(u=[+n[0],+n[1]],t()):u.slice()},r.rangeRound=function(n){return u=[+n[0],+n[1]],a=!0,t()},r.bandwidth=function(){return e},r.step=function(){return n},r.round=function(n){return arguments.length?(a=!!n,t()):a},r.padding=function(n){return arguments.length?(c=s=Math.max(0,Math.min(1,n)),t()):c},r.paddingInner=function(n){return arguments.length?(c=Math.max(0,Math.min(1,n)),t()):c},r.paddingOuter=function(n){return arguments.length?(s=Math.max(0,Math.min(1,n)),t()):s},r.align=function(n){return arguments.length?(l=Math.max(0,Math.min(1,n)),t()):l},r.copy=function(){return ru().domain(i()).range(u).round(a).paddingInner(c).paddingOuter(s).align(l)},t()}function iu(t){var n=t.copy;return t.padding=t.paddingOuter,delete t.paddingInner,delete t.paddingOuter,t.copy=function(){return iu(n())},t}function ou(t){return function(){return t}}function uu(t){return+t}function au(t,n){return(n-=t=+t)?function(e){return(e-t)/n}:ou(n)}function cu(t,n,e,r){var i=t[0],o=t[1],u=n[0],a=n[1];return o<i?(i=e(o,i),u=r(a,u)):(i=e(i,o),u=r(u,a)),function(t){return u(i(t))}}function su(t,n,e,r){var i=Math.min(t.length,n.length)-1,o=new Array(i),u=new Array(i),a=-1;for(t[i]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());++a<i;)o[a]=e(t[a],t[a+1]),u[a]=r(n[a],n[a+1]);return function(n){var e=Ds(t,n,1,i)-1;return u[e](o[e](n))}}function fu(t,n){return n.domain(t.domain()).range(t.range()).interpolate(t.interpolate()).clamp(t.clamp())}function lu(t,n){function e(){return i=Math.min(a.length,c.length)>2?su:cu,o=u=null,r}function r(n){return(o||(o=i(a,c,f?function(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=n?0:t>=e?1:r(t)}}}(t):t,s)))(+n)}var i,o,u,a=_v,c=_v,s=cn,f=!1;return r.invert=function(t){return(u||(u=i(c,a,au,f?function(t){return function(n,e){var r=t(n=+n,e=+e);return function(t){return t<=0?n:t>=1?e:r(t)}}}(n):n)))(+t)},r.domain=function(t){return arguments.length?(a=dv.call(t,uu),e()):a.slice()},r.range=function(t){return arguments.length?(c=vv.call(t),e()):c.slice()},r.rangeRound=function(t){return c=vv.call(t),s=sn,e()},r.clamp=function(t){return arguments.length?(f=!!t,e()):f},r.interpolate=function(t){return arguments.length?(s=t,e()):s},e()}function hu(n){var e=n.domain;return n.ticks=function(t){var n=e();return l(n[0],n[n.length-1],null==t?10:t)},n.tickFormat=function(n,r){return function(n,e,r){var i,o=n[0],u=n[n.length-1],a=p(o,u,null==e?10:e);switch((r=Le(null==r?",f":r)).type){case"s":var c=Math.max(Math.abs(o),Math.abs(u));return null!=r.precision||isNaN(i=Ie(a,c))||(r.precision=i),t.formatPrefix(r,c);case"":case"e":case"g":case"p":case"r":null!=r.precision||isNaN(i=Ye(a,Math.max(Math.abs(o),Math.abs(u))))||(r.precision=i-("e"===r.type));break;case"f":case"%":null!=r.precision||isNaN(i=Fe(a))||(r.precision=i-2*("%"===r.type))}return t.format(r)}(e(),n,r)},n.nice=function(t){null==t&&(t=10);var r,i=e(),o=0,u=i.length-1,a=i[o],c=i[u];return c<a&&(r=a,a=c,c=r,r=o,o=u,u=r),(r=h(a,c,t))>0?r=h(a=Math.floor(a/r)*r,c=Math.ceil(c/r)*r,t):r<0&&(r=h(a=Math.ceil(a*r)/r,c=Math.floor(c*r)/r,t)),r>0?(i[o]=Math.floor(a/r)*r,i[u]=Math.ceil(c/r)*r,e(i)):r<0&&(i[o]=Math.ceil(a*r)/r,i[u]=Math.floor(c*r)/r,e(i)),n},n}function pu(){var t=lu(au,on);return t.copy=function(){return fu(t,pu())},hu(t)}function du(){function t(t){return+t}var n=[0,1];return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=dv.call(e,uu),t):n.slice()},t.copy=function(){return du().domain(n)},hu(t)}function vu(t,n){var e,r=0,i=(t=t.slice()).length-1,o=t[r],u=t[i];return u<o&&(e=r,r=i,i=e,e=o,o=u,u=e),t[r]=n.floor(o),t[i]=n.ceil(u),t}function gu(t,n){return(n=Math.log(n/t))?function(e){return Math.log(e/t)/n}:ou(n)}function _u(t,n){return t<0?function(e){return-Math.pow(-n,e)*Math.pow(-t,1-e)}:function(e){return Math.pow(n,e)*Math.pow(t,1-e)}}function yu(t){return isFinite(t)?+("1e"+t):t<0?0:t}function mu(t){return 10===t?yu:t===Math.E?Math.exp:function(n){return Math.pow(t,n)}}function xu(t){return t===Math.E?Math.log:10===t&&Math.log10||2===t&&Math.log2||(t=Math.log(t),function(n){return Math.log(n)/t})}function bu(t){return function(n){return-t(-n)}}function wu(){function n(){return o=xu(i),u=mu(i),r()[0]<0&&(o=bu(o),u=bu(u)),e}var e=lu(gu,_u).domain([1,10]),r=e.domain,i=10,o=xu(10),u=mu(10);return e.base=function(t){return arguments.length?(i=+t,n()):i},e.domain=function(t){return arguments.length?(r(t),n()):r()},e.ticks=function(t){var n,e=r(),a=e[0],c=e[e.length-1];(n=c<a)&&(p=a,a=c,c=p);var s,f,h,p=o(a),d=o(c),v=null==t?10:+t,g=[];if(!(i%1)&&d-p<v){if(p=Math.round(p)-1,d=Math.round(d)+1,a>0){for(;p<d;++p)for(f=1,s=u(p);f<i;++f)if(!((h=s*f)<a)){if(h>c)break;g.push(h)}}else for(;p<d;++p)for(f=i-1,s=u(p);f>=1;--f)if(!((h=s*f)<a)){if(h>c)break;g.push(h)}}else g=l(p,d,Math.min(d-p,v)).map(u);return n?g.reverse():g},e.tickFormat=function(n,r){if(null==r&&(r=10===i?".0e":","),"function"!=typeof r&&(r=t.format(r)),n===1/0)return r;null==n&&(n=10);var a=Math.max(1,i*n/e.ticks().length);return function(t){var n=t/u(Math.round(o(t)));return n*i<i-.5&&(n*=i),n<=a?r(t):""}},e.nice=function(){return r(vu(r(),{floor:function(t){return u(Math.floor(o(t)))},ceil:function(t){return u(Math.ceil(o(t)))}}))},e.copy=function(){return fu(e,wu().base(i))},e}function Mu(t,n){return t<0?-Math.pow(-t,n):Math.pow(t,n)}function Tu(){var t=1,n=lu(function(n,e){return(e=Mu(e,t)-(n=Mu(n,t)))?function(r){return(Mu(r,t)-n)/e}:ou(e)},function(n,e){return e=Mu(e,t)-(n=Mu(n,t)),function(r){return Mu(n+e*r,1/t)}}),e=n.domain;return n.exponent=function(n){return arguments.length?(t=+n,e(e())):t},n.copy=function(){return fu(n,Tu().exponent(t))},hu(n)}function Nu(){function t(){var t=0,n=Math.max(1,i.length);for(o=new Array(n-1);++t<n;)o[t-1]=v(r,t/n);return e}function e(t){if(!isNaN(t=+t))return i[Ds(o,t)]}var r=[],i=[],o=[];return e.invertExtent=function(t){var n=i.indexOf(t);return n<0?[NaN,NaN]:[n>0?o[n-1]:r[0],n<o.length?o[n]:r[r.length-1]]},e.domain=function(e){if(!arguments.length)return r.slice();r=[];for(var i,o=0,u=e.length;o<u;++o)null==(i=e[o])||isNaN(i=+i)||r.push(i);return r.sort(n),t()},e.range=function(n){return arguments.length?(i=vv.call(n),t()):i.slice()},e.quantiles=function(){return o.slice()},e.copy=function(){return Nu().domain(r).range(i)},e}function ku(){function t(t){if(t<=t)return u[Ds(o,t,0,i)]}function n(){var n=-1;for(o=new Array(i);++n<i;)o[n]=((n+1)*r-(n-i)*e)/(i+1);return t}var e=0,r=1,i=1,o=[.5],u=[0,1];return t.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n()):[e,r]},t.range=function(t){return arguments.length?(i=(u=vv.call(t)).length-1,n()):u.slice()},t.invertExtent=function(t){var n=u.indexOf(t);return n<0?[NaN,NaN]:n<1?[e,o[0]]:n>=i?[o[i-1],r]:[o[n-1],o[n]]},t.copy=function(){return ku().domain([e,r]).range(u)},hu(t)}function Su(){function t(t){if(t<=t)return e[Ds(n,t,0,r)]}var n=[.5],e=[0,1],r=1;return t.domain=function(i){return arguments.length?(n=vv.call(i),r=Math.min(n.length,e.length-1),t):n.slice()},t.range=function(i){return arguments.length?(e=vv.call(i),r=Math.min(n.length,e.length-1),t):e.slice()},t.invertExtent=function(t){var r=e.indexOf(t);return[n[r-1],n[r]]},t.copy=function(){return Su().domain(n).range(e)},t}function Eu(t,n,e,r){function i(n){return t(n=new Date(+n)),n}return i.floor=i,i.ceil=function(e){return t(e=new Date(e-1)),n(e,1),t(e),e},i.round=function(t){var n=i(t),e=i.ceil(t);return t-n<e-t?n:e},i.offset=function(t,e){return n(t=new Date(+t),null==e?1:Math.floor(e)),t},i.range=function(e,r,o){var u,a=[];if(e=i.ceil(e),o=null==o?1:Math.floor(o),!(e<r&&o>0))return a;do{a.push(u=new Date(+e)),n(e,o),t(e)}while(u<e&&e<r);return a},i.filter=function(e){return Eu(function(n){if(n>=n)for(;t(n),!e(n);)n.setTime(n-1)},function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;n(t,-1),!e(t););else for(;--r>=0;)for(;n(t,1),!e(t););})},e&&(i.count=function(n,r){return yv.setTime(+n),mv.setTime(+r),t(yv),t(mv),Math.floor(e(yv,mv))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(n){return r(n)%t==0}:function(n){return i.count(0,n)%t==0}):i:null}),i}function Au(t){return Eu(function(n){n.setDate(n.getDate()-(n.getDay()+7-t)%7),n.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+7*n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*wv)/Mv})}function Cu(t){return Eu(function(n){n.setUTCDate(n.getUTCDate()-(n.getUTCDay()+7-t)%7),n.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+7*n)},function(t,n){return(n-t)/Mv})}function zu(t){if(0<=t.y&&t.y<100){var n=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return n.setFullYear(t.y),n}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Pu(t){if(0<=t.y&&t.y<100){var n=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return n.setUTCFullYear(t.y),n}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Ru(t){return{y:t,m:0,d:1,H:0,M:0,S:0,L:0}}function Lu(t){function n(t,n){return function(e){var r,i,o,u=[],a=-1,c=0,s=t.length;for(e instanceof Date||(e=new Date(+e));++a<s;)37===t.charCodeAt(a)&&(u.push(t.slice(c,a)),null!=(i=bg[r=t.charAt(++a)])?r=t.charAt(++a):i="e"===r?" ":"0",(o=n[r])&&(r=o(e,i)),u.push(r),c=a+1);return u.push(t.slice(c,a)),u.join("")}}function e(t,n){return function(e){var i,o,u=Ru(1900);if(r(u,t,e+="",0)!=e.length)return null;if("Q"in u)return new Date(u.Q);if("p"in u&&(u.H=u.H%12+12*u.p),"V"in u){if(u.V<1||u.V>53)return null;"w"in u||(u.w=1),"Z"in u?(i=(o=(i=Pu(Ru(u.y))).getUTCDay())>4||0===o?rg.ceil(i):rg(i),i=tg.offset(i,7*(u.V-1)),u.y=i.getUTCFullYear(),u.m=i.getUTCMonth(),u.d=i.getUTCDate()+(u.w+6)%7):(i=(o=(i=n(Ru(u.y))).getDay())>4||0===o?Rv.ceil(i):Rv(i),i=Cv.offset(i,7*(u.V-1)),u.y=i.getFullYear(),u.m=i.getMonth(),u.d=i.getDate()+(u.w+6)%7)}else("W"in u||"U"in u)&&("w"in u||(u.w="u"in u?u.u%7:"W"in u?1:0),o="Z"in u?Pu(Ru(u.y)).getUTCDay():n(Ru(u.y)).getDay(),u.m=0,u.d="W"in u?(u.w+6)%7+7*u.W-(o+5)%7:u.w+7*u.U-(o+6)%7);return"Z"in u?(u.H+=u.Z/100|0,u.M+=u.Z%100,Pu(u)):n(u)}}function r(t,n,e,r){for(var i,o,u=0,a=n.length,c=e.length;u<a;){if(r>=c)return-1;if(37===(i=n.charCodeAt(u++))){if(i=n.charAt(u++),!(o=T[i in bg?n.charAt(u++):i])||(r=o(t,e,r))<0)return-1}else if(i!=e.charCodeAt(r++))return-1}return r}var i=t.dateTime,o=t.date,u=t.time,a=t.periods,c=t.days,s=t.shortDays,f=t.months,l=t.shortMonths,h=Uu(a),p=Ou(a),d=Uu(c),v=Ou(c),g=Uu(s),_=Ou(s),y=Uu(f),m=Ou(f),x=Uu(l),b=Ou(l),w={a:function(t){return s[t.getDay()]},A:function(t){return c[t.getDay()]},b:function(t){return l[t.getMonth()]},B:function(t){return f[t.getMonth()]},c:null,d:ia,e:ia,f:sa,H:oa,I:ua,j:aa,L:ca,m:fa,M:la,p:function(t){return a[+(t.getHours()>=12)]},Q:Fa,s:Ia,S:ha,u:pa,U:da,V:va,w:ga,W:_a,x:null,X:null,y:ya,Y:ma,Z:xa,"%":Oa},M={a:function(t){return s[t.getUTCDay()]},A:function(t){return c[t.getUTCDay()]},b:function(t){return l[t.getUTCMonth()]},B:function(t){return f[t.getUTCMonth()]},c:null,d:ba,e:ba,f:ka,H:wa,I:Ma,j:Ta,L:Na,m:Sa,M:Ea,p:function(t){return a[+(t.getUTCHours()>=12)]},Q:Fa,s:Ia,S:Aa,u:Ca,U:za,V:Pa,w:Ra,W:La,x:null,X:null,y:qa,Y:Da,Z:Ua,"%":Oa},T={a:function(t,n,e){var r=g.exec(n.slice(e));return r?(t.w=_[r[0].toLowerCase()],e+r[0].length):-1},A:function(t,n,e){var r=d.exec(n.slice(e));return r?(t.w=v[r[0].toLowerCase()],e+r[0].length):-1},b:function(t,n,e){var r=x.exec(n.slice(e));return r?(t.m=b[r[0].toLowerCase()],e+r[0].length):-1},B:function(t,n,e){var r=y.exec(n.slice(e));return r?(t.m=m[r[0].toLowerCase()],e+r[0].length):-1},c:function(t,n,e){return r(t,i,n,e)},d:Wu,e:Wu,f:ta,H:Gu,I:Gu,j:Zu,L:Ku,m:$u,M:Qu,p:function(t,n,e){var r=h.exec(n.slice(e));return r?(t.p=p[r[0].toLowerCase()],e+r[0].length):-1},Q:ea,s:ra,S:Ju,u:Iu,U:Yu,V:Bu,w:Fu,W:Hu,x:function(t,n,e){return r(t,o,n,e)},X:function(t,n,e){return r(t,u,n,e)},y:Xu,Y:ju,Z:Vu,"%":na};return w.x=n(o,w),w.X=n(u,w),w.c=n(i,w),M.x=n(o,M),M.X=n(u,M),M.c=n(i,M),{format:function(t){var e=n(t+="",w);return e.toString=function(){return t},e},parse:function(t){var n=e(t+="",zu);return n.toString=function(){return t},n},utcFormat:function(t){var e=n(t+="",M);return e.toString=function(){return t},e},utcParse:function(t){var n=e(t,Pu);return n.toString=function(){return t},n}}}function qu(t,n,e){var r=t<0?"-":"",i=(r?-t:t)+"",o=i.length;return r+(o<e?new Array(e-o+1).join(n)+i:i)}function Du(t){return t.replace(Tg,"\\$&")}function Uu(t){return new RegExp("^(?:"+t.map(Du).join("|")+")","i")}function Ou(t){for(var n={},e=-1,r=t.length;++e<r;)n[t[e].toLowerCase()]=e;return n}function Fu(t,n,e){var r=wg.exec(n.slice(e,e+1));return r?(t.w=+r[0],e+r[0].length):-1}function Iu(t,n,e){var r=wg.exec(n.slice(e,e+1));return r?(t.u=+r[0],e+r[0].length):-1}function Yu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.U=+r[0],e+r[0].length):-1}function Bu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.V=+r[0],e+r[0].length):-1}function Hu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.W=+r[0],e+r[0].length):-1}function ju(t,n,e){var r=wg.exec(n.slice(e,e+4));return r?(t.y=+r[0],e+r[0].length):-1}function Xu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),e+r[0].length):-1}function Vu(t,n,e){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(n.slice(e,e+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),e+r[0].length):-1}function $u(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.m=r[0]-1,e+r[0].length):-1}function Wu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.d=+r[0],e+r[0].length):-1}function Zu(t,n,e){var r=wg.exec(n.slice(e,e+3));return r?(t.m=0,t.d=+r[0],e+r[0].length):-1}function Gu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.H=+r[0],e+r[0].length):-1}function Qu(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.M=+r[0],e+r[0].length):-1}function Ju(t,n,e){var r=wg.exec(n.slice(e,e+2));return r?(t.S=+r[0],e+r[0].length):-1}function Ku(t,n,e){var r=wg.exec(n.slice(e,e+3));return r?(t.L=+r[0],e+r[0].length):-1}function ta(t,n,e){var r=wg.exec(n.slice(e,e+6));return r?(t.L=Math.floor(r[0]/1e3),e+r[0].length):-1}function na(t,n,e){var r=Mg.exec(n.slice(e,e+1));return r?e+r[0].length:-1}function ea(t,n,e){var r=wg.exec(n.slice(e));return r?(t.Q=+r[0],e+r[0].length):-1}function ra(t,n,e){var r=wg.exec(n.slice(e));return r?(t.Q=1e3*+r[0],e+r[0].length):-1}function ia(t,n){return qu(t.getDate(),n,2)}function oa(t,n){return qu(t.getHours(),n,2)}function ua(t,n){return qu(t.getHours()%12||12,n,2)}function aa(t,n){return qu(1+Cv.count(Wv(t),t),n,3)}function ca(t,n){return qu(t.getMilliseconds(),n,3)}function sa(t,n){return ca(t,n)+"000"}function fa(t,n){return qu(t.getMonth()+1,n,2)}function la(t,n){return qu(t.getMinutes(),n,2)}function ha(t,n){return qu(t.getSeconds(),n,2)}function pa(t){var n=t.getDay();return 0===n?7:n}function da(t,n){return qu(Pv.count(Wv(t),t),n,2)}function va(t,n){var e=t.getDay();return t=e>=4||0===e?Dv(t):Dv.ceil(t),qu(Dv.count(Wv(t),t)+(4===Wv(t).getDay()),n,2)}function ga(t){return t.getDay()}function _a(t,n){return qu(Rv.count(Wv(t),t),n,2)}function ya(t,n){return qu(t.getFullYear()%100,n,2)}function ma(t,n){return qu(t.getFullYear()%1e4,n,4)}function xa(t){var n=t.getTimezoneOffset();return(n>0?"-":(n*=-1,"+"))+qu(n/60|0,"0",2)+qu(n%60,"0",2)}function ba(t,n){return qu(t.getUTCDate(),n,2)}function wa(t,n){return qu(t.getUTCHours(),n,2)}function Ma(t,n){return qu(t.getUTCHours()%12||12,n,2)}function Ta(t,n){return qu(1+tg.count(yg(t),t),n,3)}function Na(t,n){return qu(t.getUTCMilliseconds(),n,3)}function ka(t,n){return Na(t,n)+"000"}function Sa(t,n){return qu(t.getUTCMonth()+1,n,2)}function Ea(t,n){return qu(t.getUTCMinutes(),n,2)}function Aa(t,n){return qu(t.getUTCSeconds(),n,2)}function Ca(t){var n=t.getUTCDay();return 0===n?7:n}function za(t,n){return qu(eg.count(yg(t),t),n,2)}function Pa(t,n){var e=t.getUTCDay();return t=e>=4||0===e?ug(t):ug.ceil(t),qu(ug.count(yg(t),t)+(4===yg(t).getUTCDay()),n,2)}function Ra(t){return t.getUTCDay()}function La(t,n){return qu(rg.count(yg(t),t),n,2)}function qa(t,n){return qu(t.getUTCFullYear()%100,n,2)}function Da(t,n){return qu(t.getUTCFullYear()%1e4,n,4)}function Ua(){return"+0000"}function Oa(){return"%"}function Fa(t){return+t}function Ia(t){return Math.floor(+t/1e3)}function Ya(n){return mg=Lu(n),t.timeFormat=mg.format,t.timeParse=mg.parse,t.utcFormat=mg.utcFormat,t.utcParse=mg.utcParse,mg}function Ba(t){return new Date(t)}function Ha(t){return t instanceof Date?+t:+new Date(+t)}function ja(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?g:u(e)<e?_:o(e)<e?y:i(e)<e?m:n(e)<e?r(e)<e?x:b:t(e)<e?w:M)(e)}function l(n,r,i,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(i-r)/n,a=e(function(t){return t[2]}).right(T,u);a===T.length?(o=p(r/Lg,i/Lg,n),n=t):a?(o=(a=T[u/T[a-1][2]<T[a][2]/u?a-1:a])[1],n=a[0]):(o=Math.max(p(r,i,n),1),n=c)}return null==o?n:n.every(o)}var h=lu(au,on),d=h.invert,v=h.domain,g=s(".%L"),_=s(":%S"),y=s("%I:%M"),m=s("%I %p"),x=s("%a %d"),b=s("%b %d"),w=s("%B"),M=s("%Y"),T=[[a,1,Eg],[a,5,5*Eg],[a,15,15*Eg],[a,30,30*Eg],[u,1,Ag],[u,5,5*Ag],[u,15,15*Ag],[u,30,30*Ag],[o,1,Cg],[o,3,3*Cg],[o,6,6*Cg],[o,12,12*Cg],[i,1,zg],[i,2,2*zg],[r,1,Pg],[n,1,Rg],[n,3,3*Rg],[t,1,Lg]];return h.invert=function(t){return new Date(d(t))},h.domain=function(t){return arguments.length?v(dv.call(t,Ha)):v().map(Ba)},h.ticks=function(t,n){var e,r=v(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=v();return(t=l(t,e[0],e[e.length-1],n))?v(vu(e,t)):h},h.copy=function(){return fu(h,ja(t,n,r,i,o,u,a,c,s))},h}function Xa(t){return t.match(/.{6}/g).map(function(t){return"#"+t})}function Va(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function $a(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return $a(t).domain([e,r]).clamp(i)},hu(n)}function Wa(t){return function(){return t}}function Za(t){return t>=1?e_:t<=-1?-e_:Math.asin(t)}function Ga(t){return t.innerRadius}function Qa(t){return t.outerRadius}function Ja(t){return t.startAngle}function Ka(t){return t.endAngle}function tc(t){return t&&t.padAngle}function nc(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Kg(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,g=(h+d)/2,_=(p+v)/2,y=d-h,m=v-p,x=y*y+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*Kg(Gg(0,b*b*x-w*w)),T=(w*m-y*M)/x,N=(-w*y-m*M)/x,k=(w*m+y*M)/x,S=(-w*y+m*M)/x,E=T-g,A=N-_,C=k-g,z=S-_;return E*E+A*A>C*C+z*z&&(T=k,N=S),{cx:T,cy:N,x01:-f,y01:-l,x11:T*(i/b-1),y11:N*(i/b-1)}}function ec(t){this._context=t}function rc(t){return new ec(t)}function ic(t){return t[0]}function oc(t){return t[1]}function uc(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=te())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=ic,e=oc,r=Wa(!0),i=null,o=rc,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:Wa(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:Wa(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:Wa(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t}function ac(){function t(t){var n,f,l,h,p,d=t.length,v=!1,g=new Array(d),_=new Array(d);for(null==a&&(s=c(p=te())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(g[l],_[l]);s.lineEnd(),s.areaEnd()}v&&(g[n]=+e(h,n,t),_[n]=+i(h,n,t),s.point(r?+r(h,n,t):g[n],o?+o(h,n,t):_[n]))}if(p)return s=null,p+""||null}function n(){return uc().defined(u).curve(c).context(a)}var e=ic,r=null,i=Wa(0),o=oc,u=Wa(!0),a=null,c=rc,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:Wa(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:Wa(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:Wa(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:Wa(+n),o=null,t):i},t.y0=function(n){return arguments.length?(i="function"==typeof n?n:Wa(+n),t):i},t.y1=function(n){return arguments.length?(o=null==n?null:"function"==typeof n?n:Wa(+n),t):o},t.lineX0=t.lineY0=function(){return n().x(e).y(i)},t.lineY1=function(){return n().x(e).y(o)},t.lineX1=function(){return n().x(r).y(i)},t.defined=function(n){return arguments.length?(u="function"==typeof n?n:Wa(!!n),t):u},t.curve=function(n){return arguments.length?(c=n,null!=a&&(s=c(a)),t):c},t.context=function(n){return arguments.length?(null==n?a=s=null:s=c(a=n),t):a},t}function cc(t,n){return n<t?-1:n>t?1:n>=t?0:NaN}function sc(t){return t}function fc(t){this._curve=t}function lc(t){function n(n){return new fc(t(n))}return n._curve=t,n}function hc(t){var n=t.curve;return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t.curve=function(t){return arguments.length?n(lc(t)):n()._curve},t}function pc(){return hc(uc().curve(i_))}function dc(){var t=ac().curve(i_),n=t.curve,e=t.lineX0,r=t.lineX1,i=t.lineY0,o=t.lineY1;return t.angle=t.x,delete t.x,t.startAngle=t.x0,delete t.x0,t.endAngle=t.x1,delete t.x1,t.radius=t.y,delete t.y,t.innerRadius=t.y0,delete t.y0,t.outerRadius=t.y1,delete t.y1,t.lineStartAngle=function(){return hc(e())},delete t.lineX0,t.lineEndAngle=function(){return hc(r())},delete t.lineX1,t.lineInnerRadius=function(){return hc(i())},delete t.lineY0,t.lineOuterRadius=function(){return hc(o())},delete t.lineY1,t.curve=function(t){return arguments.length?n(lc(t)):n()._curve},t}function vc(t,n){return[(n=+n)*Math.cos(t-=Math.PI/2),n*Math.sin(t)]}function gc(t){return t.source}function _c(t){return t.target}function yc(t){function n(){var n,a=o_.call(arguments),c=e.apply(this,a),s=r.apply(this,a);if(u||(u=n=te()),t(u,+i.apply(this,(a[0]=c,a)),+o.apply(this,a),+i.apply(this,(a[0]=s,a)),+o.apply(this,a)),n)return u=null,n+""||null}var e=gc,r=_c,i=ic,o=oc,u=null;return n.source=function(t){return arguments.length?(e=t,n):e},n.target=function(t){return arguments.length?(r=t,n):r},n.x=function(t){return arguments.length?(i="function"==typeof t?t:Wa(+t),n):i},n.y=function(t){return arguments.length?(o="function"==typeof t?t:Wa(+t),n):o},n.context=function(t){return arguments.length?(u=null==t?null:t,n):u},n}function mc(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n=(n+r)/2,e,n,i,r,i)}function xc(t,n,e,r,i){t.moveTo(n,e),t.bezierCurveTo(n,e=(e+i)/2,r,e,r,i)}function bc(t,n,e,r,i){var o=vc(n,e),u=vc(n,e=(e+i)/2),a=vc(r,e),c=vc(r,i);t.moveTo(o[0],o[1]),t.bezierCurveTo(u[0],u[1],a[0],a[1],c[0],c[1])}function wc(){}function Mc(t,n,e){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+n)/6,(t._y0+4*t._y1+e)/6)}function Tc(t){this._context=t}function Nc(t){this._context=t}function kc(t){this._context=t}function Sc(t,n){this._basis=new Tc(t),this._beta=n}function Ec(t,n,e){t._context.bezierCurveTo(t._x1+t._k*(t._x2-t._x0),t._y1+t._k*(t._y2-t._y0),t._x2+t._k*(t._x1-n),t._y2+t._k*(t._y1-e),t._x2,t._y2)}function Ac(t,n){this._context=t,this._k=(1-n)/6}function Cc(t,n){this._context=t,this._k=(1-n)/6}function zc(t,n){this._context=t,this._k=(1-n)/6}function Pc(t,n,e){var r=t._x1,i=t._y1,o=t._x2,u=t._y2;if(t._l01_a>t_){var a=2*t._l01_2a+3*t._l01_a*t._l12_a+t._l12_2a,c=3*t._l01_a*(t._l01_a+t._l12_a);r=(r*a-t._x0*t._l12_2a+t._x2*t._l01_2a)/c,i=(i*a-t._y0*t._l12_2a+t._y2*t._l01_2a)/c}if(t._l23_a>t_){var s=2*t._l23_2a+3*t._l23_a*t._l12_a+t._l12_2a,f=3*t._l23_a*(t._l23_a+t._l12_a);o=(o*s+t._x1*t._l23_2a-n*t._l12_2a)/f,u=(u*s+t._y1*t._l23_2a-e*t._l12_2a)/f}t._context.bezierCurveTo(r,i,o,u,t._x2,t._y2)}function Rc(t,n){this._context=t,this._alpha=n}function Lc(t,n){this._context=t,this._alpha=n}function qc(t,n){this._context=t,this._alpha=n}function Dc(t){this._context=t}function Uc(t){return t<0?-1:1}function Oc(t,n,e){var r=t._x1-t._x0,i=n-t._x1,o=(t._y1-t._y0)/(r||i<0&&-0),u=(e-t._y1)/(i||r<0&&-0),a=(o*i+u*r)/(r+i);return(Uc(o)+Uc(u))*Math.min(Math.abs(o),Math.abs(u),.5*Math.abs(a))||0}function Fc(t,n){var e=t._x1-t._x0;return e?(3*(t._y1-t._y0)/e-n)/2:n}function Ic(t,n,e){var r=t._x0,i=t._y0,o=t._x1,u=t._y1,a=(o-r)/3;t._context.bezierCurveTo(r+a,i+a*n,o-a,u-a*e,o,u)}function Yc(t){this._context=t}function Bc(t){this._context=new Hc(t)}function Hc(t){this._context=t}function jc(t){this._context=t}function Xc(t){var n,e,r=t.length-1,i=new Array(r),o=new Array(r),u=new Array(r);for(i[0]=0,o[0]=2,u[0]=t[0]+2*t[1],n=1;n<r-1;++n)i[n]=1,o[n]=4,u[n]=4*t[n]+2*t[n+1];for(i[r-1]=2,o[r-1]=7,u[r-1]=8*t[r-1]+t[r],n=1;n<r;++n)e=i[n]/o[n-1],o[n]-=e,u[n]-=e*u[n-1];for(i[r-1]=u[r-1]/o[r-1],n=r-2;n>=0;--n)i[n]=(u[n]-i[n+1])/o[n];for(o[r-1]=(t[r]+i[r-1])/2,n=0;n<r-1;++n)o[n]=2*t[n+1]-i[n+1];return[i,o]}function Vc(t,n){this._context=t,this._t=n}function $c(t,n){if((i=t.length)>1)for(var e,r,i,o=1,u=t[n[0]],a=u.length;o<i;++o)for(r=u,u=t[n[o]],e=0;e<a;++e)u[e][1]+=u[e][0]=isNaN(r[e][1])?r[e][0]:r[e][1]}function Wc(t){for(var n=t.length,e=new Array(n);--n>=0;)e[n]=n;return e}function Zc(t,n){return t[n]}function Gc(t){var n=t.map(Qc);return Wc(t).sort(function(t,e){return n[t]-n[e]})}function Qc(t){for(var n,e=0,r=-1,i=t.length;++r<i;)(n=+t[r][1])&&(e+=n);return e}function Jc(t){return function(){return t}}function Kc(t){return t[0]}function ts(t){return t[1]}function ns(){this._=null}function es(t){t.U=t.C=t.L=t.R=t.P=t.N=null}function rs(t,n){var e=n,r=n.R,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function is(t,n){var e=n,r=n.L,i=e.U;i?i.L===e?i.L=r:i.R=r:t._=r,r.U=i,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function os(t){for(;t.L;)t=t.L;return t}function us(t,n,e,r){var i=[null,null],o=L_.push(i)-1;return i.left=t,i.right=n,e&&cs(i,t,n,e),r&&cs(i,n,t,r),P_[t.index].halfedges.push(o),P_[n.index].halfedges.push(o),i}function as(t,n,e){var r=[n,e];return r.left=t,r}function cs(t,n,e,r){t[0]||t[1]?t.left===e?t[1]=r:t[0]=r:(t[0]=r,t.left=n,t.right=e)}function ss(t,n,e,r,i){var o,u=t[0],a=t[1],c=u[0],s=u[1],f=0,l=1,h=a[0]-c,p=a[1]-s;if(o=n-c,h||!(o>0)){if(o/=h,h<0){if(o<f)return;o<l&&(l=o)}else if(h>0){if(o>l)return;o>f&&(f=o)}if(o=r-c,h||!(o<0)){if(o/=h,h<0){if(o>l)return;o>f&&(f=o)}else if(h>0){if(o<f)return;o<l&&(l=o)}if(o=e-s,p||!(o>0)){if(o/=p,p<0){if(o<f)return;o<l&&(l=o)}else if(p>0){if(o>l)return;o>f&&(f=o)}if(o=i-s,p||!(o<0)){if(o/=p,p<0){if(o>l)return;o>f&&(f=o)}else if(p>0){if(o<f)return;o<l&&(l=o)}return!(f>0||l<1)||(f>0&&(t[0]=[c+f*h,s+f*p]),l<1&&(t[1]=[c+l*h,s+l*p]),!0)}}}}}function fs(t,n,e,r,i){var o=t[1];if(o)return!0;var u,a,c=t[0],s=t.left,f=t.right,l=s[0],h=s[1],p=f[0],d=f[1],v=(l+p)/2,g=(h+d)/2;if(d===h){if(v<n||v>=r)return;if(l>p){if(c){if(c[1]>=i)return}else c=[v,e];o=[v,i]}else{if(c){if(c[1]<e)return}else c=[v,i];o=[v,e]}}else if(u=(l-p)/(d-h),a=g-u*v,u<-1||u>1)if(l>p){if(c){if(c[1]>=i)return}else c=[(e-a)/u,e];o=[(i-a)/u,i]}else{if(c){if(c[1]<e)return}else c=[(i-a)/u,i];o=[(e-a)/u,e]}else if(h<d){if(c){if(c[0]>=r)return}else c=[n,u*n+a];o=[r,u*r+a]}else{if(c){if(c[0]<n)return}else c=[r,u*r+a];o=[n,u*n+a]}return t[0]=c,t[1]=o,!0}function ls(t,n){var e=t.site,r=n.left,i=n.right;return e===i&&(i=r,r=e),i?Math.atan2(i[1]-r[1],i[0]-r[0]):(e===r?(r=n[1],i=n[0]):(r=n[0],i=n[1]),Math.atan2(r[0]-i[0],i[1]-r[1]))}function hs(t,n){return n[+(n.left!==t.site)]}function ps(t,n){return n[+(n.left===t.site)]}function ds(t){var n=t.P,e=t.N;if(n&&e){var r=n.site,i=t.site,o=e.site;if(r!==o){var u=i[0],a=i[1],c=r[0]-u,s=r[1]-a,f=o[0]-u,l=o[1]-a,h=2*(c*l-s*f);if(!(h>=-O_)){var p=c*c+s*s,d=f*f+l*l,v=(l*p-s*d)/h,g=(c*d-f*p)/h,_=q_.pop()||new function(){es(this),this.x=this.y=this.arc=this.site=this.cy=null};_.arc=t,_.site=i,_.x=v+u,_.y=(_.cy=g+a)+Math.sqrt(v*v+g*g),t.circle=_;for(var y=null,m=R_._;m;)if(_.y<m.y||_.y===m.y&&_.x<=m.x){if(!m.L){y=m.P;break}m=m.L}else{if(!m.R){y=m;break}m=m.R}R_.insert(y,_),y||(C_=_)}}}}function vs(t){var n=t.circle;n&&(n.P||(C_=n.N),R_.remove(n),q_.push(n),es(n),t.circle=null)}function gs(t){var n=D_.pop()||new function(){es(this),this.edge=this.site=this.circle=null};return n.site=t,n}function _s(t){vs(t),z_.remove(t),D_.push(t),es(t)}function ys(t){var n=t.circle,e=n.x,r=n.cy,i=[e,r],o=t.P,u=t.N,a=[t];_s(t);for(var c=o;c.circle&&Math.abs(e-c.circle.x)<U_&&Math.abs(r-c.circle.cy)<U_;)o=c.P,a.unshift(c),_s(c),c=o;a.unshift(c),vs(c);for(var s=u;s.circle&&Math.abs(e-s.circle.x)<U_&&Math.abs(r-s.circle.cy)<U_;)u=s.N,a.push(s),_s(s),s=u;a.push(s),vs(s);var f,l=a.length;for(f=1;f<l;++f)s=a[f],c=a[f-1],cs(s.edge,c.site,s.site,i);c=a[0],(s=a[l-1]).edge=us(c.site,s.site,null,i),ds(c),ds(s)}function ms(t){for(var n,e,r,i,o=t[0],u=t[1],a=z_._;a;)if((r=xs(a,u)-o)>U_)a=a.L;else{if(!((i=o-function(t,n){var e=t.N;if(e)return xs(e,n);var r=t.site;return r[1]===n?r[0]:1/0}(a,u))>U_)){r>-U_?(n=a.P,e=a):i>-U_?(n=a,e=a.N):n=e=a;break}if(!a.R){n=a;break}a=a.R}(function(t){P_[t.index]={site:t,halfedges:[]}})(t);var c=gs(t);if(z_.insert(n,c),n||e){if(n===e)return vs(n),e=gs(n.site),z_.insert(c,e),c.edge=e.edge=us(n.site,c.site),ds(n),void ds(e);if(e){vs(n),vs(e);var s=n.site,f=s[0],l=s[1],h=t[0]-f,p=t[1]-l,d=e.site,v=d[0]-f,g=d[1]-l,_=2*(h*g-p*v),y=h*h+p*p,m=v*v+g*g,x=[(g*y-p*m)/_+f,(h*m-v*y)/_+l];cs(e.edge,s,d,x),c.edge=us(s,t,null,x),e.edge=us(t,d,null,x),ds(n),ds(e)}else c.edge=us(n.site,c.site)}}function xs(t,n){var e=t.site,r=e[0],i=e[1],o=i-n;if(!o)return r;var u=t.P;if(!u)return-1/0;var a=(e=u.site)[0],c=e[1],s=c-n;if(!s)return a;var f=a-r,l=1/o-1/s,h=f/s;return l?(-h+Math.sqrt(h*h-2*l*(f*f/(-2*s)-c+s/2+i-o/2)))/l+r:(r+a)/2}function bs(t,n,e){return(t[0]-e[0])*(n[1]-t[1])-(t[0]-n[0])*(e[1]-t[1])}function ws(t,n){return n[1]-t[1]||n[0]-t[0]}function Ms(t,n){var e,r,i,o=t.sort(ws).pop();for(L_=[],P_=new Array(t.length),z_=new ns,R_=new ns;;)if(i=C_,o&&(!i||o[1]<i.y||o[1]===i.y&&o[0]<i.x))o[0]===e&&o[1]===r||(ms(o),e=o[0],r=o[1]),o=t.pop();else{if(!i)break;ys(i.arc)}if(function(){for(var t,n,e,r,i=0,o=P_.length;i<o;++i)if((t=P_[i])&&(r=(n=t.halfedges).length)){var u=new Array(r),a=new Array(r);for(e=0;e<r;++e)u[e]=e,a[e]=ls(t,L_[n[e]]);for(u.sort(function(t,n){return a[n]-a[t]}),e=0;e<r;++e)a[e]=n[u[e]];for(e=0;e<r;++e)n[e]=a[e]}}(),n){var u=+n[0][0],a=+n[0][1],c=+n[1][0],s=+n[1][1];(function(t,n,e,r){for(var i,o=L_.length;o--;)fs(i=L_[o],t,n,e,r)&&ss(i,t,n,e,r)&&(Math.abs(i[0][0]-i[1][0])>U_||Math.abs(i[0][1]-i[1][1])>U_)||delete L_[o]})(u,a,c,s),function(t,n,e,r){var i,o,u,a,c,s,f,l,h,p,d,v,g=P_.length,_=!0;for(i=0;i<g;++i)if(o=P_[i]){for(u=o.site,a=(c=o.halfedges).length;a--;)L_[c[a]]||c.splice(a,1);for(a=0,s=c.length;a<s;)d=(p=ps(o,L_[c[a]]))[0],v=p[1],l=(f=hs(o,L_[c[++a%s]]))[0],h=f[1],(Math.abs(d-l)>U_||Math.abs(v-h)>U_)&&(c.splice(a,0,L_.push(as(u,p,Math.abs(d-t)<U_&&r-v>U_?[t,Math.abs(l-t)<U_?h:r]:Math.abs(v-r)<U_&&e-d>U_?[Math.abs(h-r)<U_?l:e,r]:Math.abs(d-e)<U_&&v-n>U_?[e,Math.abs(l-e)<U_?h:n]:Math.abs(v-n)<U_&&d-t>U_?[Math.abs(h-n)<U_?l:t,n]:null))-1),++s);s&&(_=!1)}if(_){var y,m,x,b=1/0;for(i=0,_=null;i<g;++i)(o=P_[i])&&(x=(y=(u=o.site)[0]-t)*y+(m=u[1]-n)*m)<b&&(b=x,_=o);if(_){var w=[t,n],M=[t,r],T=[e,r],N=[e,n];_.halfedges.push(L_.push(as(u=_.site,w,M))-1,L_.push(as(u,M,T))-1,L_.push(as(u,T,N))-1,L_.push(as(u,N,w))-1)}}for(i=0;i<g;++i)(o=P_[i])&&(o.halfedges.length||delete P_[i])}(u,a,c,s)}this.edges=L_,this.cells=P_,z_=R_=L_=P_=null}function Ts(t){return function(){return t}}function Ns(t,n,e){this.k=t,this.x=n,this.y=e}function ks(t){return t.__zoom||F_}function Ss(){t.event.stopImmediatePropagation()}function Es(){t.event.preventDefault(),t.event.stopImmediatePropagation()}function As(){return!t.event.button}function Cs(){var t,n,e=this;return e instanceof SVGElement?(t=(e=e.ownerSVGElement||e).width.baseVal.value,n=e.height.baseVal.value):(t=e.clientWidth,n=e.clientHeight),[[0,0],[t,n]]}function zs(){return this.__zoom||F_}function Ps(){return-t.event.deltaY*(t.event.deltaMode?120:1)/500}function Rs(){return"ontouchstart"in this}function Ls(t,n,e){var r=t.invertX(n[0][0])-e[0][0],i=t.invertX(n[1][0])-e[1][0],o=t.invertY(n[0][1])-e[0][1],u=t.invertY(n[1][1])-e[1][1];return t.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),u>o?(o+u)/2:Math.min(0,o)||Math.max(0,u))}var qs=e(n),Ds=qs.right,Us=qs.left,Os=Array.prototype,Fs=Os.slice,Is=Os.map,Ys=Math.sqrt(50),Bs=Math.sqrt(10),Hs=Math.sqrt(2),js=Array.prototype.slice,Xs=1,Vs=2,$s=3,Ws=4,Zs=1e-6,Gs={value:function(){}};k.prototype=N.prototype={constructor:k,on:function(t,n){var e,r=this._,i=function(t,n){return t.trim().split(/^|\s+/).map(function(t){var e="",r=t.indexOf(".");if(r>=0&&(e=t.slice(r+1),t=t.slice(0,r)),t&&!n.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:e}})}(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=S(r[e],t.name,n);else if(null==n)for(e in r)r[e]=S(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=function(t,n){for(var e,r=0,i=t.length;r<i;++r)if((e=t[r]).name===n)return e.value}(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new k(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(o=0,e=(r=this._[t]).length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var Qs="http://www.w3.org/1999/xhtml",Js={svg:"http://www.w3.org/2000/svg",xhtml:Qs,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},Ks=0;z.prototype=C.prototype={constructor:z,get:function(t){for(var n=this._;!(n in t);)if(!(t=t.parentNode))return;return t[n]},set:function(t,n){return t[this._]=n},remove:function(t){return this._ in t&&delete t[this._]},toString:function(){return this._}};var tf=function(t){return function(){return this.matches(t)}};if("undefined"!=typeof document){var nf=document.documentElement;if(!nf.matches){var ef=nf.webkitMatchesSelector||nf.msMatchesSelector||nf.mozMatchesSelector||nf.oMatchesSelector;tf=function(t){return function(){return ef.call(this,t)}}}}var rf=tf,of={};if(t.event=null,"undefined"!=typeof document){"onmouseenter"in document.documentElement||(of={mouseenter:"mouseover",mouseleave:"mouseout"})}X.prototype={constructor:X,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,n){return this._parent.insertBefore(t,n)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var uf="$";K.prototype={add:function(t){this._names.indexOf(t)<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var af=[null];st.prototype=ft.prototype={constructor:st,select:function(t){"function"!=typeof t&&(t=Y(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u,a=n[i],c=a.length,s=r[i]=new Array(c),f=0;f<c;++f)(o=a[f])&&(u=t.call(o,o.__data__,f,a))&&("__data__"in o&&(u.__data__=o.__data__),s[f]=u);return new st(r,this._parents)},selectAll:function(t){"function"!=typeof t&&(t=H(t));for(var n=this._groups,e=n.length,r=[],i=[],o=0;o<e;++o)for(var u,a=n[o],c=a.length,s=0;s<c;++s)(u=a[s])&&(r.push(t.call(u,u.__data__,s,a)),i.push(u));return new st(r,i)},filter:function(t){"function"!=typeof t&&(t=rf(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new st(r,this._parents)},data:function(t,n){if(!t)return p=new Array(this.size()),s=-1,this.each(function(t){p[++s]=t}),p;var e=n?$:V,r=this._parents,i=this._groups;"function"!=typeof t&&(t=function(t){return function(){return t}}(t));for(var o=i.length,u=new Array(o),a=new Array(o),c=new Array(o),s=0;s<o;++s){var f=r[s],l=i[s],h=l.length,p=t.call(f,f&&f.__data__,s,r),d=p.length,v=a[s]=new Array(d),g=u[s]=new Array(d);e(f,l,v,g,c[s]=new Array(h),p,n);for(var _,y,m=0,x=0;m<d;++m)if(_=v[m]){for(m>=x&&(x=m+1);!(y=g[x])&&++x<d;);_._next=y||null}}return u=new st(u,r),u._enter=a,u._exit=c,u},enter:function(){return new st(this._enter||this._groups.map(j),this._parents)},exit:function(){return new st(this._exit||this._groups.map(j),this._parents)},merge:function(t){for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new st(u,this._parents)},order:function(){for(var t=this._groups,n=-1,e=t.length;++n<e;)for(var r,i=t[n],o=i.length-1,u=i[o];--o>=0;)(r=i[o])&&(u&&u!==r.nextSibling&&u.parentNode.insertBefore(r,u),u=r);return this},sort:function(t){function n(n,e){return n&&e?t(n.__data__,e.__data__):!n-!e}t||(t=W);for(var e=this._groups,r=e.length,i=new Array(r),o=0;o<r;++o){for(var u,a=e[o],c=a.length,s=i[o]=new Array(c),f=0;f<c;++f)(u=a[f])&&(s[f]=u);s.sort(n)}return new st(i,this._parents).order()},call:function(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this},nodes:function(){var t=new Array(this.size()),n=-1;return this.each(function(){t[++n]=this}),t},node:function(){for(var t=this._groups,n=0,e=t.length;n<e;++n)for(var r=t[n],i=0,o=r.length;i<o;++i){var u=r[i];if(u)return u}return null},size:function(){var t=0;return this.each(function(){++t}),t},empty:function(){return!this.node()},each:function(t){for(var n=this._groups,e=0,r=n.length;e<r;++e)for(var i,o=n[e],u=0,a=o.length;u<a;++u)(i=o[u])&&t.call(i,i.__data__,u,o);return this},attr:function(t,n){var e=E(t);if(arguments.length<2){var r=this.node();return e.local?r.getAttributeNS(e.space,e.local):r.getAttribute(e)}return this.each((null==n?e.local?function(t){return function(){this.removeAttributeNS(t.space,t.local)}}:function(t){return function(){this.removeAttribute(t)}}:"function"==typeof n?e.local?function(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}:function(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}:e.local?function(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}:function(t,n){return function(){this.setAttribute(t,n)}})(e,n))},style:function(t,n,e){return arguments.length>1?this.each((null==n?function(t){return function(){this.style.removeProperty(t)}}:"function"==typeof n?function(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}:function(t,n,e){return function(){this.style.setProperty(t,n,e)}})(t,n,null==e?"":e)):G(this.node(),t)},property:function(t,n){return arguments.length>1?this.each((null==n?function(t){return function(){delete this[t]}}:"function"==typeof n?function(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}:function(t,n){return function(){this[t]=n}})(t,n)):this.node()[t]},classed:function(t,n){var e=Q(t+"");if(arguments.length<2){for(var r=J(this.node()),i=-1,o=e.length;++i<o;)if(!r.contains(e[i]))return!1;return!0}return this.each(("function"==typeof n?function(t,n){return function(){(n.apply(this,arguments)?tt:nt)(this,t)}}:n?function(t){return function(){tt(this,t)}}:function(t){return function(){nt(this,t)}})(e,n))},text:function(t){return arguments.length?this.each(null==t?et:("function"==typeof t?function(t){return function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}}:function(t){return function(){this.textContent=t}})(t)):this.node().textContent},html:function(t){return arguments.length?this.each(null==t?rt:("function"==typeof t?function(t){return function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}}:function(t){return function(){this.innerHTML=t}})(t)):this.node().innerHTML},raise:function(){return this.each(it)},lower:function(){return this.each(ot)},append:function(t){var n="function"==typeof t?t:A(t);return this.select(function(){return this.appendChild(n.apply(this,arguments))})},insert:function(t,n){var e="function"==typeof t?t:A(t),r=null==n?ut:"function"==typeof n?n:Y(n);return this.select(function(){return this.insertBefore(e.apply(this,arguments),r.apply(this,arguments)||null)})},remove:function(){return this.each(at)},datum:function(t){return arguments.length?this.property("__data__",t):this.node().__data__},on:function(t,n,e){var r,i,o=function(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}(t+""),u=o.length;if(!(arguments.length<2)){for(a=n?q:L,null==e&&(e=!1),r=0;r<u;++r)this.each(a(o[r],n,e));return this}var a=this.node().__on;if(a)for(var c,s=0,f=a.length;s<f;++s)for(r=0,c=a[s];r<u;++r)if((i=o[r]).type===c.type&&i.name===c.name)return c.value},dispatch:function(t,n){return this.each(("function"==typeof n?function(t,n){return function(){return ct(this,t,n.apply(this,arguments))}}:function(t,n){return function(){return ct(this,t,n)}})(t,n))}},yt.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var cf="\\s*([+-]?\\d+)\\s*",sf="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",ff="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",lf=/^#([0-9a-f]{3})$/,hf=/^#([0-9a-f]{6})$/,pf=new RegExp("^rgb\\("+[cf,cf,cf]+"\\)$"),df=new RegExp("^rgb\\("+[ff,ff,ff]+"\\)$"),vf=new RegExp("^rgba\\("+[cf,cf,cf,sf]+"\\)$"),gf=new RegExp("^rgba\\("+[ff,ff,ff,sf]+"\\)$"),_f=new RegExp("^hsl\\("+[sf,ff,ff]+"\\)$"),yf=new RegExp("^hsla\\("+[sf,ff,ff,sf]+"\\)$"),mf={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Mt(Nt,kt,{displayable:function(){return this.rgb().displayable()},toString:function(){return this.rgb()+""}}),Mt(zt,Ct,Tt(Nt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new zt(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new zt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return 0<=this.r&&this.r<=255&&0<=this.g&&this.g<=255&&0<=this.b&&this.b<=255&&0<=this.opacity&&this.opacity<=1},toString:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}})),Mt(Lt,Rt,Tt(Nt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Lt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Lt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new zt(qt(t>=240?t-240:t+120,i,r),qt(t,i,r),qt(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1}}));var xf=Math.PI/180,bf=180/Math.PI,wf=.95047,Mf=1,Tf=1.08883,Nf=4/29,kf=6/29,Sf=3*kf*kf,Ef=kf*kf*kf;Mt(Ot,Ut,Tt(Nt,{brighter:function(t){return new Ot(this.l+18*(null==t?1:t),this.a,this.b,this.opacity)},darker:function(t){return new Ot(this.l-18*(null==t?1:t),this.a,this.b,this.opacity)},rgb:function(){var t=(this.l+16)/116,n=isNaN(this.a)?t:t+this.a/500,e=isNaN(this.b)?t:t-this.b/200;return t=Mf*It(t),n=wf*It(n),e=Tf*It(e),new zt(Yt(3.2404542*n-1.5371385*t-.4985314*e),Yt(-.969266*n+1.8760108*t+.041556*e),Yt(.0556434*n-.2040259*t+1.0572252*e),this.opacity)}})),Mt(jt,Ht,Tt(Nt,{brighter:function(t){return new jt(this.h,this.c,this.l+18*(null==t?1:t),this.opacity)},darker:function(t){return new jt(this.h,this.c,this.l-18*(null==t?1:t),this.opacity)},rgb:function(){return Dt(this).rgb()}}));var Af=-.29227,Cf=-.90649,zf=1.97294,Pf=zf*Cf,Rf=1.78277*zf,Lf=1.78277*Af- -.14861*Cf;Mt(Vt,Xt,Tt(Nt,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Vt(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=isNaN(this.h)?0:(this.h+120)*xf,n=+this.l,e=isNaN(this.s)?0:this.s*n*(1-n),r=Math.cos(t),i=Math.sin(t);return new zt(255*(n+e*(-.14861*r+1.78277*i)),255*(n+e*(Af*r+Cf*i)),255*(n+e*(zf*r)),this.opacity)}}));var qf,Df,Uf,Of,Ff,If,Yf=function t(n){function e(t,n){var e=r((t=Ct(t)).r,(n=Ct(n)).r),i=r(t.g,n.g),o=r(t.b,n.b),u=tn(t.opacity,n.opacity);return function(n){return t.r=e(n),t.g=i(n),t.b=o(n),t.opacity=u(n),t+""}}var r=Kt(n);return e.gamma=t,e}(1),Bf=nn(Wt),Hf=nn(Zt),jf=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Xf=new RegExp(jf.source,"g"),Vf=180/Math.PI,$f={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},Wf=ln(function(t){return"none"===t?$f:(qf||(qf=document.createElement("DIV"),Df=document.documentElement,Uf=document.defaultView),qf.style.transform=t,t=Uf.getComputedStyle(Df.appendChild(qf),null).getPropertyValue("transform"),Df.removeChild(qf),t=t.slice(7,-1).split(","),fn(+t[0],+t[1],+t[2],+t[3],+t[4],+t[5]))},"px, ","px)","deg)"),Zf=ln(function(t){return null==t?$f:(Of||(Of=document.createElementNS("http://www.w3.org/2000/svg","g")),Of.setAttribute("transform",t),(t=Of.transform.baseVal.consolidate())?(t=t.matrix,fn(t.a,t.b,t.c,t.d,t.e,t.f)):$f)},", ",")",")"),Gf=Math.SQRT2,Qf=2,Jf=4,Kf=1e-12,tl=dn(Jt),nl=dn(tn),el=vn(Jt),rl=vn(tn),il=gn(Jt),ol=gn(tn),ul=0,al=0,cl=0,sl=1e3,fl=0,ll=0,hl=0,pl="object"==typeof performance&&performance.now?performance:Date,dl="object"==typeof window&&window.requestAnimationFrame?window.requestAnimationFrame.bind(window):function(t){setTimeout(t,17)};mn.prototype=xn.prototype={constructor:mn,restart:function(t,n,e){if("function"!=typeof t)throw new TypeError("callback is not a function");e=(null==e?_n():+e)+(null==n?0:+n),this._next||If===this||(If?If._next=this:Ff=this,If=this),this._call=t,this._time=e,Tn()},stop:function(){this._call&&(this._call=null,this._time=1/0,Tn())}};var vl=N("start","end","interrupt"),gl=[],_l=0,yl=1,ml=2,xl=3,bl=4,wl=5,Ml=6,Tl=ft.prototype.constructor,Nl=0,kl=ft.prototype;Rn.prototype=Ln.prototype={constructor:Rn,select:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=Y(t));for(var r=this._groups,i=r.length,o=new Array(i),u=0;u<i;++u)for(var a,c,s=r[u],f=s.length,l=o[u]=new Array(f),h=0;h<f;++h)(a=s[h])&&(c=t.call(a,a.__data__,h,s))&&("__data__"in a&&(c.__data__=a.__data__),l[h]=c,kn(l[h],n,e,h,l,An(a,e)));return new Rn(o,this._parents,n,e)},selectAll:function(t){var n=this._name,e=this._id;"function"!=typeof t&&(t=H(t));for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=An(c,e),v=0,g=p.length;v<g;++v)(h=p[v])&&kn(h,n,e,v,p,d);o.push(p),u.push(c)}return new Rn(o,u,n,e)},filter:function(t){"function"!=typeof t&&(t=rf(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i<e;++i)for(var o,u=n[i],a=u.length,c=r[i]=[],s=0;s<a;++s)(o=u[s])&&t.call(o,o.__data__,s,u)&&c.push(o);return new Rn(r,this._parents,this._name,this._id)},merge:function(t){if(t._id!==this._id)throw new Error;for(var n=this._groups,e=t._groups,r=n.length,i=e.length,o=Math.min(r,i),u=new Array(r),a=0;a<o;++a)for(var c,s=n[a],f=e[a],l=s.length,h=u[a]=new Array(l),p=0;p<l;++p)(c=s[p]||f[p])&&(h[p]=c);for(;a<r;++a)u[a]=n[a];return new Rn(u,this._parents,this._name,this._id)},selection:function(){return new Tl(this._groups,this._parents)},transition:function(){for(var t=this._name,n=this._id,e=qn(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=An(u,n);kn(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new Rn(r,this._parents,t,e)},call:kl.call,nodes:kl.nodes,node:kl.node,size:kl.size,empty:kl.empty,each:kl.each,on:function(t,n){var e=this._id;return arguments.length<2?An(this.node(),e).on.on(t):this.each(function(t,n,e){var r,i,o=function(t){return(t+"").trim().split(/^|\s+/).every(function(t){var n=t.indexOf(".");return n>=0&&(t=t.slice(0,n)),!t||"start"===t})}(n)?Sn:En;return function(){var u=o(this,t),a=u.on;a!==r&&(i=(r=a).copy()).on(n,e),u.on=i}}(e,t,n))},attr:function(t,n){var e=E(t),r="transform"===e?Zf:Pn;return this.attrTween(t,"function"==typeof n?(e.local?function(t,n,e){var r,i,o;return function(){var u,a=e(this);if(null!=a)return(u=this.getAttributeNS(t.space,t.local))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttributeNS(t.space,t.local)}}:function(t,n,e){var r,i,o;return function(){var u,a=e(this);if(null!=a)return(u=this.getAttribute(t))===a?null:u===r&&a===i?o:o=n(r=u,i=a);this.removeAttribute(t)}})(e,r,zn(this,"attr."+t,n)):null==n?(e.local?function(t){return function(){this.removeAttributeNS(t.space,t.local)}}:function(t){return function(){this.removeAttribute(t)}})(e):(e.local?function(t,n,e){var r,i;return function(){var o=this.getAttributeNS(t.space,t.local);return o===e?null:o===r?i:i=n(r=o,e)}}:function(t,n,e){var r,i;return function(){var o=this.getAttribute(t);return o===e?null:o===r?i:i=n(r=o,e)}})(e,r,n+""))},attrTween:function(t,n){var e="attr."+t;if(arguments.length<2)return(e=this.tween(e))&&e._value;if(null==n)return this.tween(e,null);if("function"!=typeof n)throw new Error;var r=E(t);return this.tween(e,(r.local?function(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttributeNS(t.space,t.local,r(n))}}return e._value=n,e}:function(t,n){function e(){var e=this,r=n.apply(e,arguments);return r&&function(n){e.setAttribute(t,r(n))}}return e._value=n,e})(r,n))},style:function(t,n,e){var r="transform"==(t+="")?Wf:Pn;return null==n?this.styleTween(t,function(t,n){var e,r,i;return function(){var o=G(this,t),u=(this.style.removeProperty(t),G(this,t));return o===u?null:o===e&&u===r?i:i=n(e=o,r=u)}}(t,r)).on("end.style."+t,function(t){return function(){this.style.removeProperty(t)}}(t)):this.styleTween(t,"function"==typeof n?function(t,n,e){var r,i,o;return function(){var u=G(this,t),a=e(this);return null==a&&(this.style.removeProperty(t),a=G(this,t)),u===a?null:u===r&&a===i?o:o=n(r=u,i=a)}}(t,r,zn(this,"style."+t,n)):function(t,n,e){var r,i;return function(){var o=G(this,t);return o===e?null:o===r?i:i=n(r=o,e)}}(t,r,n+""),e)},styleTween:function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,function(t,n,e){function r(){var r=this,i=n.apply(r,arguments);return i&&function(n){r.style.setProperty(t,i(n),e)}}return r._value=n,r}(t,n,null==e?"":e))},text:function(t){return this.tween("text","function"==typeof t?function(t){return function(){var n=t(this);this.textContent=null==n?"":n}}(zn(this,"text",t)):function(t){return function(){this.textContent=t}}(null==t?"":t+""))},remove:function(){return this.on("end.remove",function(t){return function(){var n=this.parentNode;for(var e in this.__transition)if(+e!==t)return;n&&n.removeChild(this)}}(this._id))},tween:function(t,n){var e=this._id;if(t+="",arguments.length<2){for(var r,i=An(this.node(),e).tween,o=0,u=i.length;o<u;++o)if((r=i[o]).name===t)return r.value;return null}return this.each((null==n?function(t,n){var e,r;return function(){var i=En(this,t),o=i.tween;if(o!==e)for(var u=0,a=(r=e=o).length;u<a;++u)if(r[u].name===n){(r=r.slice()).splice(u,1);break}i.tween=r}}:function(t,n,e){var r,i;if("function"!=typeof e)throw new Error;return function(){var o=En(this,t),u=o.tween;if(u!==r){i=(r=u).slice();for(var a={name:n,value:e},c=0,s=i.length;c<s;++c)if(i[c].name===n){i[c]=a;break}c===s&&i.push(a)}o.tween=i}})(e,t,n))},delay:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?function(t,n){return function(){Sn(this,t).delay=+n.apply(this,arguments)}}:function(t,n){return n=+n,function(){Sn(this,t).delay=n}})(n,t)):An(this.node(),n).delay},duration:function(t){var n=this._id;return arguments.length?this.each(("function"==typeof t?function(t,n){return function(){En(this,t).duration=+n.apply(this,arguments)}}:function(t,n){return n=+n,function(){En(this,t).duration=n}})(n,t)):An(this.node(),n).duration},ease:function(t){var n=this._id;return arguments.length?this.each(function(t,n){if("function"!=typeof n)throw new Error;return function(){En(this,t).ease=n}}(n,t)):An(this.node(),n).ease}};var Sl=function t(n){function e(t){return Math.pow(t,n)}return n=+n,e.exponent=t,e}(3),El=function t(n){function e(t){return 1-Math.pow(1-t,n)}return n=+n,e.exponent=t,e}(3),Al=function t(n){function e(t){return((t*=2)<=1?Math.pow(t,n):2-Math.pow(2-t,n))/2}return n=+n,e.exponent=t,e}(3),Cl=Math.PI,zl=Cl/2,Pl=4/11,Rl=6/11,Ll=8/11,ql=.75,Dl=9/11,Ul=10/11,Ol=.9375,Fl=21/22,Il=63/64,Yl=1/Pl/Pl,Bl=function t(n){function e(t){return t*t*((n+1)*t-n)}return n=+n,e.overshoot=t,e}(1.70158),Hl=function t(n){function e(t){return--t*t*((n+1)*t+n)+1}return n=+n,e.overshoot=t,e}(1.70158),jl=function t(n){function e(t){return((t*=2)<1?t*t*((n+1)*t-n):(t-=2)*t*((n+1)*t+n)+2)/2}return n=+n,e.overshoot=t,e}(1.70158),Xl=2*Math.PI,Vl=function t(n,e){function r(t){return n*Math.pow(2,10*--t)*Math.sin((i-t)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=Xl);return r.amplitude=function(n){return t(n,e*Xl)},r.period=function(e){return t(n,e)},r}(1,.3),$l=function t(n,e){function r(t){return 1-n*Math.pow(2,-10*(t=+t))*Math.sin((t+i)/e)}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=Xl);return r.amplitude=function(n){return t(n,e*Xl)},r.period=function(e){return t(n,e)},r}(1,.3),Wl=function t(n,e){function r(t){return((t=2*t-1)<0?n*Math.pow(2,10*t)*Math.sin((i-t)/e):2-n*Math.pow(2,-10*t)*Math.sin((i+t)/e))/2}var i=Math.asin(1/(n=Math.max(1,n)))*(e/=Xl);return r.amplitude=function(n){return t(n,e*Xl)},r.period=function(e){return t(n,e)},r}(1,.3),Zl={time:null,delay:0,duration:250,ease:Un};ft.prototype.interrupt=function(t){return this.each(function(){Cn(this,t)})},ft.prototype.transition=function(t){var n,e;t instanceof Rn?(n=t._id,t=t._name):(n=qn(),(e=Zl).time=_n(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&kn(u,t,n,s,a,e||Bn(u,n));return new Rn(r,this._parents,t,n)};var Gl=[null],Ql={name:"drag"},Jl={name:"space"},Kl={name:"handle"},th={name:"center"},nh={name:"x",handles:["e","w"].map(Vn),input:function(t,n){return t&&[[t[0],n[0][1]],[t[1],n[1][1]]]},output:function(t){return t&&[t[0][0],t[1][0]]}},eh={name:"y",handles:["n","s"].map(Vn),input:function(t,n){return t&&[[n[0][0],t[0]],[n[1][0],t[1]]]},output:function(t){return t&&[t[0][1],t[1][1]]}},rh={name:"xy",handles:["n","e","s","w","nw","ne","se","sw"].map(Vn),input:function(t){return t},output:function(t){return t}},ih={overlay:"crosshair",selection:"move",n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},oh={e:"w",w:"e",nw:"ne",ne:"nw",se:"sw",sw:"se"},uh={n:"s",s:"n",nw:"sw",ne:"se",se:"ne",sw:"nw"},ah={overlay:1,selection:1,n:null,e:1,s:null,w:-1,nw:-1,ne:1,se:1,sw:-1},ch={overlay:1,selection:1,n:-1,e:null,s:1,w:null,nw:-1,ne:-1,se:1,sw:1},sh=Math.cos,fh=Math.sin,lh=Math.PI,hh=lh/2,ph=2*lh,dh=Math.max,vh=Array.prototype.slice,gh=Math.PI,_h=2*gh,yh=_h-1e-6;Kn.prototype=te.prototype={constructor:Kn,moveTo:function(t,n){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)},closePath:function(){null!==this._x1&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(t,n){this._+="L"+(this._x1=+t)+","+(this._y1=+n)},quadraticCurveTo:function(t,n,e,r){this._+="Q"+ +t+","+ +n+","+(this._x1=+e)+","+(this._y1=+r)},bezierCurveTo:function(t,n,e,r,i,o){this._+="C"+ +t+","+ +n+","+ +e+","+ +r+","+(this._x1=+i)+","+(this._y1=+o)},arcTo:function(t,n,e,r,i){t=+t,n=+n,e=+e,r=+r,i=+i;var o=this._x1,u=this._y1,a=e-t,c=r-n,s=o-t,f=u-n,l=s*s+f*f;if(i<0)throw new Error("negative radius: "+i);if(null===this._x1)this._+="M"+(this._x1=t)+","+(this._y1=n);else if(l>1e-6)if(Math.abs(f*a-c*s)>1e-6&&i){var h=e-o,p=r-u,d=a*a+c*c,v=h*h+p*p,g=Math.sqrt(d),_=Math.sqrt(l),y=i*Math.tan((gh-Math.acos((d+l-v)/(2*g*_)))/2),m=y/_,x=y/g;Math.abs(m-1)>1e-6&&(this._+="L"+(t+m*s)+","+(n+m*f)),this._+="A"+i+","+i+",0,0,"+ +(f*h>s*p)+","+(this._x1=t+x*a)+","+(this._y1=n+x*c)}else this._+="L"+(this._x1=t)+","+(this._y1=n);else;},arc:function(t,n,e,r,i,o){t=+t,n=+n;var u=(e=+e)*Math.cos(r),a=e*Math.sin(r),c=t+u,s=n+a,f=1^o,l=o?r-i:i-r;if(e<0)throw new Error("negative radius: "+e);null===this._x1?this._+="M"+c+","+s:(Math.abs(this._x1-c)>1e-6||Math.abs(this._y1-s)>1e-6)&&(this._+="L"+c+","+s),e&&(l<0&&(l=l%_h+_h),l>yh?this._+="A"+e+","+e+",0,1,"+f+","+(t-u)+","+(n-a)+"A"+e+","+e+",0,1,"+f+","+(this._x1=c)+","+(this._y1=s):l>1e-6&&(this._+="A"+e+","+e+",0,"+ +(l>=gh)+","+f+","+(this._x1=t+e*Math.cos(i))+","+(this._y1=n+e*Math.sin(i))))},rect:function(t,n,e,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+n)+"h"+ +e+"v"+ +r+"h"+-e+"Z"},toString:function(){return this._}};ue.prototype=ae.prototype={constructor:ue,has:function(t){return"$"+t in this},get:function(t){return this["$"+t]},set:function(t,n){return this["$"+t]=n,this},remove:function(t){var n="$"+t;return n in this&&delete this[n]},clear:function(){for(var t in this)"$"===t[0]&&delete this[t]},keys:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(n.slice(1));return t},values:function(){var t=[];for(var n in this)"$"===n[0]&&t.push(this[n]);return t},entries:function(){var t=[];for(var n in this)"$"===n[0]&&t.push({key:n.slice(1),value:this[n]});return t},size:function(){var t=0;for(var n in this)"$"===n[0]&&++t;return t},empty:function(){for(var t in this)if("$"===t[0])return!1;return!0},each:function(t){for(var n in this)"$"===n[0]&&t(this[n],n.slice(1),this)}};var mh=ae.prototype;he.prototype=pe.prototype={constructor:he,has:mh.has,add:function(t){return t+="",this["$"+t]=t,this},remove:mh.remove,clear:mh.clear,values:mh.keys,size:mh.size,empty:mh.empty,each:mh.each};var xh={},bh={},wh=34,Mh=10,Th=13,Nh=ve(","),kh=Nh.parse,Sh=Nh.parseRows,Eh=Nh.format,Ah=Nh.formatRows,Ch=ve("\t"),zh=Ch.parse,Ph=Ch.parseRows,Rh=Ch.format,Lh=Ch.formatRows,qh=we.prototype=Me.prototype;qh.copy=function(){var t,n,e=new Me(this._x,this._y,this._x0,this._y0,this._x1,this._y1),r=this._root;if(!r)return e;if(!r.length)return e._root=Te(r),e;for(t=[{source:r,target:e._root=new Array(4)}];r=t.pop();)for(var i=0;i<4;++i)(n=r.source[i])&&(n.length?t.push({source:n,target:r.target[i]=new Array(4)}):r.target[i]=Te(n));return e},qh.add=function(t){var n=+this._x.call(null,t),e=+this._y.call(null,t);return ye(this.cover(n,e),n,e,t)},qh.addAll=function(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-1/0,l=-1/0;for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)ye(this,u[e],a[e],t[e]);return this},qh.cover=function(t,n){if(isNaN(t=+t)||isNaN(n=+n))return this;var e=this._x0,r=this._y0,i=this._x1,o=this._y1;if(isNaN(e))i=(e=Math.floor(t))+1,o=(r=Math.floor(n))+1;else{if(!(e>t||t>i||r>n||n>o))return this;var u,a,c=i-e,s=this._root;switch(a=(n<(r+o)/2)<<1|t<(e+i)/2){case 0:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,o=r+c,t>i||n>o);break;case 1:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,o=r+c,e>t||n>o);break;case 2:do{u=new Array(4),u[a]=s,s=u}while(c*=2,i=e+c,r=o-c,t>i||r>n);break;case 3:do{u=new Array(4),u[a]=s,s=u}while(c*=2,e=i-c,r=o-c,e>t||r>n)}this._root&&this._root.length&&(this._root=s)}return this._x0=e,this._y0=r,this._x1=i,this._y1=o,this},qh.data=function(){var t=[];return this.visit(function(n){if(!n.length)do{t.push(n.data)}while(n=n.next)}),t},qh.extent=function(t){return arguments.length?this.cover(+t[0][0],+t[0][1]).cover(+t[1][0],+t[1][1]):isNaN(this._x0)?void 0:[[this._x0,this._y0],[this._x1,this._y1]]},qh.find=function(t,n,e){var r,i,o,u,a,c,s,f=this._x0,l=this._y0,h=this._x1,p=this._y1,d=[],v=this._root;for(v&&d.push(new me(v,f,l,h,p)),null==e?e=1/0:(f=t-e,l=n-e,h=t+e,p=n+e,e*=e);c=d.pop();)if(!(!(v=c.node)||(i=c.x0)>h||(o=c.y0)>p||(u=c.x1)<f||(a=c.y1)<l))if(v.length){var g=(i+u)/2,_=(o+a)/2;d.push(new me(v[3],g,_,u,a),new me(v[2],i,_,g,a),new me(v[1],g,o,u,_),new me(v[0],i,o,g,_)),(s=(n>=_)<<1|t>=g)&&(c=d[d.length-1],d[d.length-1]=d[d.length-1-s],d[d.length-1-s]=c)}else{var y=t-+this._x.call(null,v.data),m=n-+this._y.call(null,v.data),x=y*y+m*m;if(x<e){var b=Math.sqrt(e=x);f=t-b,l=n-b,h=t+b,p=n+b,r=v.data}}return r},qh.remove=function(t){if(isNaN(o=+this._x.call(null,t))||isNaN(u=+this._y.call(null,t)))return this;var n,e,r,i,o,u,a,c,s,f,l,h,p=this._root,d=this._x0,v=this._y0,g=this._x1,_=this._y1;if(!p)return this;if(p.length)for(;;){if((s=o>=(a=(d+g)/2))?d=a:g=a,(f=u>=(c=(v+_)/2))?v=c:_=c,n=p,!(p=p[l=f<<1|s]))return this;if(!p.length)break;(n[l+1&3]||n[l+2&3]||n[l+3&3])&&(e=n,h=l)}for(;p.data!==t;)if(r=p,!(p=p.next))return this;return(i=p.next)&&delete p.next,r?(i?r.next=i:delete r.next,this):n?(i?n[l]=i:delete n[l],(p=n[0]||n[1]||n[2]||n[3])&&p===(n[3]||n[2]||n[1]||n[0])&&!p.length&&(e?e[h]=p:this._root=p),this):(this._root=i,this)},qh.removeAll=function(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this},qh.root=function(){return this._root},qh.size=function(){var t=0;return this.visit(function(n){if(!n.length)do{++t}while(n=n.next)}),t},qh.visit=function(t){var n,e,r,i,o,u,a=[],c=this._root;for(c&&a.push(new me(c,this._x0,this._y0,this._x1,this._y1));n=a.pop();)if(!t(c=n.node,r=n.x0,i=n.y0,o=n.x1,u=n.y1)&&c.length){var s=(r+o)/2,f=(i+u)/2;(e=c[3])&&a.push(new me(e,s,f,o,u)),(e=c[2])&&a.push(new me(e,r,f,s,u)),(e=c[1])&&a.push(new me(e,s,i,o,f)),(e=c[0])&&a.push(new me(e,r,i,s,f))}return this},qh.visitAfter=function(t){var n,e=[],r=[];for(this._root&&e.push(new me(this._root,this._x0,this._y0,this._x1,this._y1));n=e.pop();){var i=n.node;if(i.length){var o,u=n.x0,a=n.y0,c=n.x1,s=n.y1,f=(u+c)/2,l=(a+s)/2;(o=i[0])&&e.push(new me(o,u,a,f,l)),(o=i[1])&&e.push(new me(o,f,a,c,l)),(o=i[2])&&e.push(new me(o,u,l,f,s)),(o=i[3])&&e.push(new me(o,f,l,c,s))}r.push(n)}for(;n=r.pop();)t(n.node,n.x0,n.y0,n.x1,n.y1);return this},qh.x=function(t){return arguments.length?(this._x=t,this):this._x},qh.y=function(t){return arguments.length?(this._y=t,this):this._y};var Dh,Uh=10,Oh=Math.PI*(3-Math.sqrt(5)),Fh={"":function(t,n){t:for(var e,r=(t=t.toPrecision(n)).length,i=1,o=-1;i<r;++i)switch(t[i]){case".":o=e=i;break;case"0":0===o&&(o=i),e=i;break;case"e":break t;default:o>0&&(o=0)}return o>0?t.slice(0,o)+t.slice(e+1):t},"%":function(t,n){return(100*t).toFixed(n)},b:function(t){return Math.round(t).toString(2)},c:function(t){return t+""},d:function(t){return Math.round(t).toString(10)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},g:function(t,n){return t.toPrecision(n)},o:function(t){return Math.round(t).toString(8)},p:function(t,n){return Re(100*t,n)},r:Re,s:function(t,n){var e=ze(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(Dh=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,u=r.length;return o===u?r:o>u?r+new Array(o-u+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+ze(t,Math.max(0,n+o-1))[0]},X:function(t){return Math.round(t).toString(16).toUpperCase()},x:function(t){return Math.round(t).toString(16)}},Ih=/^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;Le.prototype=qe.prototype,qe.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(null==this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(null==this.precision?"":"."+Math.max(0,0|this.precision))+this.type};var Yh,Bh=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];Oe({decimal:".",thousands:",",grouping:[3],currency:["$",""]}),He.prototype={constructor:He,reset:function(){this.s=this.t=0},add:function(t){je(xp,t,this.t),je(this,xp.s,this.s),this.s?this.t+=xp.t:this.s=xp.t},valueOf:function(){return this.s}};var Hh,jh,Xh,Vh,$h,Wh,Zh,Gh,Qh,Jh,Kh,tp,np,ep,rp,ip,op,up,ap,cp,sp,fp,lp,hp,pp,dp,vp,gp,_p,yp,mp,xp=new He,bp=1e-6,wp=1e-12,Mp=Math.PI,Tp=Mp/2,Np=Mp/4,kp=2*Mp,Sp=180/Mp,Ep=Mp/180,Ap=Math.abs,Cp=Math.atan,zp=Math.atan2,Pp=Math.cos,Rp=Math.ceil,Lp=Math.exp,qp=Math.log,Dp=Math.pow,Up=Math.sin,Op=Math.sign||function(t){return t>0?1:t<0?-1:0},Fp=Math.sqrt,Ip=Math.tan,Yp={Feature:function(t,n){Ze(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)Ze(e[r].geometry,n)}},Bp={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){Ge(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)Ge(e[r],n,0)},Polygon:function(t,n){Qe(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)Qe(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)Ze(e[r],n)}},Hp=Be(),jp=Be(),Xp={point:We,lineStart:We,lineEnd:We,polygonStart:function(){Hp.reset(),Xp.lineStart=Ke,Xp.lineEnd=tr},polygonEnd:function(){var t=+Hp;jp.add(t<0?kp+t:t),this.lineStart=this.lineEnd=this.point=We},sphere:function(){jp.add(kp)}},Vp=Be(),$p={point:fr,lineStart:hr,lineEnd:pr,polygonStart:function(){$p.point=dr,$p.lineStart=vr,$p.lineEnd=gr,Vp.reset(),Xp.polygonStart()},polygonEnd:function(){Xp.polygonEnd(),$p.point=fr,$p.lineStart=hr,$p.lineEnd=pr,Hp<0?(Wh=-(Gh=180),Zh=-(Qh=90)):Vp>bp?Qh=90:Vp<-bp&&(Zh=-90),rp[0]=Wh,rp[1]=Gh}},Wp={sphere:We,point:xr,lineStart:wr,lineEnd:Nr,polygonStart:function(){Wp.lineStart=kr,Wp.lineEnd=Sr},polygonEnd:function(){Wp.lineStart=wr,Wp.lineEnd=Nr}};Pr.invert=Pr;var Zp,Gp,Qp,Jp,Kp,td,nd,ed,rd,id,od,ud=Be(),ad=Vr(function(){return!0},function(t){var n,e=NaN,r=NaN,i=NaN;return{lineStart:function(){t.lineStart(),n=1},point:function(o,u){var a=o>0?Mp:-Mp,c=Ap(o-e);Ap(c-Mp)<bp?(t.point(e,r=(r+u)/2>0?Tp:-Tp),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),t.point(o,r),n=0):i!==a&&c>=Mp&&(Ap(e-i)<bp&&(e-=i*bp),Ap(o-a)<bp&&(o-=a*bp),r=function(t,n,e,r){var i,o,u=Up(t-e);return Ap(u)>bp?Cp((Up(n)*(o=Pp(r))*Up(e)-Up(r)*(i=Pp(n))*Up(t))/(i*o*u)):(n+r)/2}(e,r,o,u),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(a,r),n=0),t.point(e=o,r=u),i=a},lineEnd:function(){t.lineEnd(),e=r=NaN},clean:function(){return 2-n}}},function(t,n,e,r){var i;if(null==t)i=e*Tp,r.point(-Mp,i),r.point(0,i),r.point(Mp,i),r.point(Mp,0),r.point(Mp,-i),r.point(0,-i),r.point(-Mp,-i),r.point(-Mp,0),r.point(-Mp,i);else if(Ap(t[0]-n[0])>bp){var o=t[0]<n[0]?Mp:-Mp;i=e*o/2,r.point(-o,i),r.point(0,i),r.point(o,i)}else r.point(n[0],n[1])},[-Mp,-Tp]),cd=1e9,sd=-cd,fd=Be(),ld={sphere:We,point:We,lineStart:function(){ld.point=Jr,ld.lineEnd=Qr},lineEnd:We,polygonStart:We,polygonEnd:We},hd=[null,null],pd={type:"LineString",coordinates:hd},dd={Feature:function(t,n){return ei(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)if(ei(e[r].geometry,n))return!0;return!1}},vd={Sphere:function(){return!0},Point:function(t,n){return ri(t.coordinates,n)},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(ri(e[r],n))return!0;return!1},LineString:function(t,n){return ii(t.coordinates,n)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(ii(e[r],n))return!0;return!1},Polygon:function(t,n){return oi(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)if(oi(e[r],n))return!0;return!1},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)if(ei(e[r],n))return!0;return!1}},gd=Be(),_d=Be(),yd={point:We,lineStart:We,lineEnd:We,polygonStart:function(){yd.lineStart=hi,yd.lineEnd=vi},polygonEnd:function(){yd.lineStart=yd.lineEnd=yd.point=We,gd.add(Ap(_d)),_d.reset()},result:function(){var t=gd/2;return gd.reset(),t}},md=1/0,xd=md,bd=-md,wd=bd,Md={point:function(t,n){t<md&&(md=t),t>bd&&(bd=t),n<xd&&(xd=n),n>wd&&(wd=n)},lineStart:We,lineEnd:We,polygonStart:We,polygonEnd:We,result:function(){var t=[[md,xd],[bd,wd]];return bd=wd=-(xd=md=1/0),t}},Td=0,Nd=0,kd=0,Sd=0,Ed=0,Ad=0,Cd=0,zd=0,Pd=0,Rd={point:gi,lineStart:_i,lineEnd:xi,polygonStart:function(){Rd.lineStart=bi,Rd.lineEnd=wi},polygonEnd:function(){Rd.point=gi,Rd.lineStart=_i,Rd.lineEnd=xi},result:function(){var t=Pd?[Cd/Pd,zd/Pd]:Ad?[Sd/Ad,Ed/Ad]:kd?[Td/kd,Nd/kd]:[NaN,NaN];return Td=Nd=kd=Sd=Ed=Ad=Cd=zd=Pd=0,t}};Ni.prototype={_radius:4.5,pointRadius:function(t){return this._radius=t,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._context.closePath(),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._context.moveTo(t,n),this._point=1;break;case 1:this._context.lineTo(t,n);break;default:this._context.moveTo(t+this._radius,n),this._context.arc(t,n,this._radius,0,kp)}},result:We};var Ld,qd,Dd,Ud,Od,Fd=Be(),Id={point:We,lineStart:function(){Id.point=ki},lineEnd:function(){Ld&&Si(qd,Dd),Id.point=We},polygonStart:function(){Ld=!0},polygonEnd:function(){Ld=null},result:function(){var t=+Fd;return Fd.reset(),t}};Ei.prototype={_radius:4.5,_circle:Ai(4.5),pointRadius:function(t){return(t=+t)!==this._radius&&(this._radius=t,this._circle=null),this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){0===this._line&&this._string.push("Z"),this._point=NaN},point:function(t,n){switch(this._point){case 0:this._string.push("M",t,",",n),this._point=1;break;case 1:this._string.push("L",t,",",n);break;default:null==this._circle&&(this._circle=Ai(this._radius)),this._string.push("M",t,",",n,this._circle)}},result:function(){if(this._string.length){var t=this._string.join("");return this._string=[],t}return null}},zi.prototype={constructor:zi,point:function(t,n){this.stream.point(t,n)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};var Yd=16,Bd=Pp(30*Ep),Hd=Ci({point:function(t,n){this.stream.point(t*Ep,n*Ep)}}),jd=ji(function(t){return Fp(2/(1+t))});jd.invert=Xi(function(t){return 2*Ve(t/2)});var Xd=ji(function(t){return(t=Xe(t))&&t/Up(t)});Xd.invert=Xi(function(t){return t}),Vi.invert=function(t,n){return[t,2*Cp(Lp(n))-Tp]},Gi.invert=Gi,Ji.invert=Xi(Cp),to.invert=function(t,n){var e,r=n,i=25;do{var o=r*r,u=o*o;r-=e=(r*(1.007226+o*(.015085+u*(.028874*o-.044475-.005916*u)))-n)/(1.007226+o*(.045255+u*(.259866*o-.311325-.005916*11*u)))}while(Ap(e)>bp&&--i>0);return[t/(.8707+(o=r*r)*(o*(o*o*o*(.003971-.001529*o)-.013791)-.131979)),r]},no.invert=Xi(Ve),eo.invert=Xi(function(t){return 2*Cp(t)}),ro.invert=function(t,n){return[-n,2*Cp(Lp(t))-Tp]},ho.prototype=co.prototype={constructor:ho,count:function(){return this.eachAfter(ao)},each:function(t){var n,e,r,i,o=this,u=[o];do{for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r])}while(u.length);return this},eachAfter:function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},eachBefore:function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},sum:function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},sort:function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},path:function(t){for(var n=this,e=function(t,n){if(t===n)return t;var e=t.ancestors(),r=n.ancestors(),i=null;for(t=e.pop(),n=r.pop();t===n;)i=t,t=e.pop(),n=r.pop();return i}(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},ancestors:function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},descendants:function(){var t=[];return this.each(function(n){t.push(n)}),t},leaves:function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},links:function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n},copy:function(){return co(this).eachBefore(fo)}};var Vd=Array.prototype.slice,$d="$",Wd={depth:-1},Zd={};Yo.prototype=Object.create(ho.prototype);var Gd=(1+Math.sqrt(5))/2,Qd=function t(n){function e(t,e,r,i,o){Ho(n,t,e,r,i,o)}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Gd),Jd=function t(n){function e(t,e,r,i,o){if((u=t._squarify)&&u.ratio===n)for(var u,a,c,s,f,l=-1,h=u.length,p=t.value;++l<h;){for(c=(a=u[l]).children,s=a.value=0,f=c.length;s<f;++s)a.value+=c[s].value;a.dice?Ro(a,e,r,i,r+=(o-r)*a.value/p):Bo(a,e,r,e+=(i-e)*a.value/p,o),p-=a.value}else t._squarify=u=Ho(n,t,e,r,i,o),u.ratio=n}return e.ratio=function(n){return t((n=+n)>1?n:1)},e}(Gd),Kd=[].slice,tv={};$o.prototype=Qo.prototype={constructor:$o,defer:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("defer after await");if(null!=this._error)return this;var n=Kd.call(arguments,1);return n.push(t),++this._waiting,this._tasks.push(n),Wo(this),this},abort:function(){return null==this._error&&Zo(this,new Error("abort")),this},await:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=function(n,e){t.apply(null,[n].concat(e))},Go(this),this},awaitAll:function(t){if("function"!=typeof t)throw new Error("invalid callback");if(this._call)throw new Error("multiple await");return this._call=t,Go(this),this}};var nv=function t(n){function e(t,e){return t=null==t?0:+t,e=null==e?1:+e,1===arguments.length?(e=t,t=0):e-=t,function(){return n()*e+t}}return e.source=t,e}(Jo),ev=function t(n){function e(t,e){var r,i;return t=null==t?0:+t,e=null==e?1:+e,function(){var o;if(null!=r)o=r,r=null;else do{r=2*n()-1,o=2*n()-1,i=r*r+o*o}while(!i||i>1);return t+e*o*Math.sqrt(-2*Math.log(i)/i)}}return e.source=t,e}(Jo),rv=function t(n){function e(){var t=ev.source(n).apply(this,arguments);return function(){return Math.exp(t())}}return e.source=t,e}(Jo),iv=function t(n){function e(t){return function(){for(var e=0,r=0;r<t;++r)e+=n();return e}}return e.source=t,e}(Jo),ov=function t(n){function e(t){var e=iv.source(n)(t);return function(){return e()/t}}return e.source=t,e}(Jo),uv=function t(n){function e(t){return function(){return-Math.log(1-n())/t}}return e.source=t,e}(Jo),av=tu("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),cv=tu("application/json",function(t){return JSON.parse(t.responseText)}),sv=tu("text/plain",function(t){return t.responseText}),fv=tu("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),lv=nu("text/csv",kh),hv=nu("text/tab-separated-values",zh),pv=Array.prototype,dv=pv.map,vv=pv.slice,gv={name:"implicit"},_v=[0,1],yv=new Date,mv=new Date,xv=Eu(function(){},function(t,n){t.setTime(+t+n)},function(t,n){return n-t});xv.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Eu(function(n){n.setTime(Math.floor(n/t)*t)},function(n,e){n.setTime(+n+e*t)},function(n,e){return(e-n)/t}):xv:null};var bv=xv.range,wv=6e4,Mv=6048e5,Tv=Eu(function(t){t.setTime(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(+t+1e3*n)},function(t,n){return(n-t)/1e3},function(t){return t.getUTCSeconds()}),Nv=Tv.range,kv=Eu(function(t){t.setTime(Math.floor(t/wv)*wv)},function(t,n){t.setTime(+t+n*wv)},function(t,n){return(n-t)/wv},function(t){return t.getMinutes()}),Sv=kv.range,Ev=Eu(function(t){var n=t.getTimezoneOffset()*wv%36e5;n<0&&(n+=36e5),t.setTime(36e5*Math.floor((+t-n)/36e5)+n)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getHours()}),Av=Ev.range,Cv=Eu(function(t){t.setHours(0,0,0,0)},function(t,n){t.setDate(t.getDate()+n)},function(t,n){return(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*wv)/864e5},function(t){return t.getDate()-1}),zv=Cv.range,Pv=Au(0),Rv=Au(1),Lv=Au(2),qv=Au(3),Dv=Au(4),Uv=Au(5),Ov=Au(6),Fv=Pv.range,Iv=Rv.range,Yv=Lv.range,Bv=qv.range,Hv=Dv.range,jv=Uv.range,Xv=Ov.range,Vv=Eu(function(t){t.setDate(1),t.setHours(0,0,0,0)},function(t,n){t.setMonth(t.getMonth()+n)},function(t,n){return n.getMonth()-t.getMonth()+12*(n.getFullYear()-t.getFullYear())},function(t){return t.getMonth()}),$v=Vv.range,Wv=Eu(function(t){t.setMonth(0,1),t.setHours(0,0,0,0)},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t,n){return n.getFullYear()-t.getFullYear()},function(t){return t.getFullYear()});Wv.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Eu(function(n){n.setFullYear(Math.floor(n.getFullYear()/t)*t),n.setMonth(0,1),n.setHours(0,0,0,0)},function(n,e){n.setFullYear(n.getFullYear()+e*t)}):null};var Zv=Wv.range,Gv=Eu(function(t){t.setUTCSeconds(0,0)},function(t,n){t.setTime(+t+n*wv)},function(t,n){return(n-t)/wv},function(t){return t.getUTCMinutes()}),Qv=Gv.range,Jv=Eu(function(t){t.setUTCMinutes(0,0,0)},function(t,n){t.setTime(+t+36e5*n)},function(t,n){return(n-t)/36e5},function(t){return t.getUTCHours()}),Kv=Jv.range,tg=Eu(function(t){t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCDate(t.getUTCDate()+n)},function(t,n){return(n-t)/864e5},function(t){return t.getUTCDate()-1}),ng=tg.range,eg=Cu(0),rg=Cu(1),ig=Cu(2),og=Cu(3),ug=Cu(4),ag=Cu(5),cg=Cu(6),sg=eg.range,fg=rg.range,lg=ig.range,hg=og.range,pg=ug.range,dg=ag.range,vg=cg.range,gg=Eu(function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCMonth(t.getUTCMonth()+n)},function(t,n){return n.getUTCMonth()-t.getUTCMonth()+12*(n.getUTCFullYear()-t.getUTCFullYear())},function(t){return t.getUTCMonth()}),_g=gg.range,yg=Eu(function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},function(t,n){t.setUTCFullYear(t.getUTCFullYear()+n)},function(t,n){return n.getUTCFullYear()-t.getUTCFullYear()},function(t){return t.getUTCFullYear()});yg.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Eu(function(n){n.setUTCFullYear(Math.floor(n.getUTCFullYear()/t)*t),n.setUTCMonth(0,1),n.setUTCHours(0,0,0,0)},function(n,e){n.setUTCFullYear(n.getUTCFullYear()+e*t)}):null};var mg,xg=yg.range,bg={"-":"",_:" ",0:"0"},wg=/^\s*\d+/,Mg=/^%/,Tg=/[\\^$*+?|[\]().{}]/g;Ya({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});var Ng="%Y-%m-%dT%H:%M:%S.%LZ",kg=Date.prototype.toISOString?function(t){return t.toISOString()}:t.utcFormat(Ng),Sg=+new Date("2000-01-01T00:00:00.000Z")?function(t){var n=new Date(t);return isNaN(n)?null:n}:t.utcParse(Ng),Eg=1e3,Ag=60*Eg,Cg=60*Ag,zg=24*Cg,Pg=7*zg,Rg=30*zg,Lg=365*zg,qg=Xa("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"),Dg=Xa("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"),Ug=Xa("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"),Og=Xa("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"),Fg=ol(Xt(300,.5,0),Xt(-240,.5,1)),Ig=ol(Xt(-100,.75,.35),Xt(80,1.5,.8)),Yg=ol(Xt(260,.75,.35),Xt(80,1.5,.8)),Bg=Xt(),Hg=Va(Xa("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")),jg=Va(Xa("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")),Xg=Va(Xa("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")),Vg=Va(Xa("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")),$g=Math.abs,Wg=Math.atan2,Zg=Math.cos,Gg=Math.max,Qg=Math.min,Jg=Math.sin,Kg=Math.sqrt,t_=1e-12,n_=Math.PI,e_=n_/2,r_=2*n_;ec.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var i_=lc(rc);fc.prototype={areaStart:function(){this._curve.areaStart()},areaEnd:function(){this._curve.areaEnd()},lineStart:function(){this._curve.lineStart()},lineEnd:function(){this._curve.lineEnd()},point:function(t,n){this._curve.point(n*Math.sin(t),n*-Math.cos(t))}};var o_=Array.prototype.slice,u_={draw:function(t,n){var e=Math.sqrt(n/n_);t.moveTo(e,0),t.arc(0,0,e,0,r_)}},a_={draw:function(t,n){var e=Math.sqrt(n/5)/2;t.moveTo(-3*e,-e),t.lineTo(-e,-e),t.lineTo(-e,-3*e),t.lineTo(e,-3*e),t.lineTo(e,-e),t.lineTo(3*e,-e),t.lineTo(3*e,e),t.lineTo(e,e),t.lineTo(e,3*e),t.lineTo(-e,3*e),t.lineTo(-e,e),t.lineTo(-3*e,e),t.closePath()}},c_=Math.sqrt(1/3),s_=2*c_,f_={draw:function(t,n){var e=Math.sqrt(n/s_),r=e*c_;t.moveTo(0,-e),t.lineTo(r,0),t.lineTo(0,e),t.lineTo(-r,0),t.closePath()}},l_=Math.sin(n_/10)/Math.sin(7*n_/10),h_=Math.sin(r_/10)*l_,p_=-Math.cos(r_/10)*l_,d_={draw:function(t,n){var e=Math.sqrt(.8908130915292852*n),r=h_*e,i=p_*e;t.moveTo(0,-e),t.lineTo(r,i);for(var o=1;o<5;++o){var u=r_*o/5,a=Math.cos(u),c=Math.sin(u);t.lineTo(c*e,-a*e),t.lineTo(a*r-c*i,c*r+a*i)}t.closePath()}},v_={draw:function(t,n){var e=Math.sqrt(n),r=-e/2;t.rect(r,r,e,e)}},g_=Math.sqrt(3),__={draw:function(t,n){var e=-Math.sqrt(n/(3*g_));t.moveTo(0,2*e),t.lineTo(-g_*e,-e),t.lineTo(g_*e,-e),t.closePath()}},y_=Math.sqrt(3)/2,m_=1/Math.sqrt(12),x_=3*(m_/2+1),b_={draw:function(t,n){var e=Math.sqrt(n/x_),r=e/2,i=e*m_,o=r,u=e*m_+e,a=-o,c=u;t.moveTo(r,i),t.lineTo(o,u),t.lineTo(a,c),t.lineTo(-.5*r-y_*i,y_*r+-.5*i),t.lineTo(-.5*o-y_*u,y_*o+-.5*u),t.lineTo(-.5*a-y_*c,y_*a+-.5*c),t.lineTo(-.5*r+y_*i,-.5*i-y_*r),t.lineTo(-.5*o+y_*u,-.5*u-y_*o),t.lineTo(-.5*a+y_*c,-.5*c-y_*a),t.closePath()}},w_=[u_,a_,f_,v_,d_,__,b_];Tc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:Mc(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:Mc(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Nc.prototype={areaStart:wc,areaEnd:wc,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x2,this._y2),this._context.closePath();break;case 2:this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break;case 3:this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x2=t,this._y2=n;break;case 1:this._point=2,this._x3=t,this._y3=n;break;case 2:this._point=3,this._x4=t,this._y4=n,this._context.moveTo((this._x0+4*this._x1+t)/6,(this._y0+4*this._y1+n)/6);break;default:Mc(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},kc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var e=(this._x0+4*this._x1+t)/6,r=(this._y0+4*this._y1+n)/6;this._line?this._context.lineTo(e,r):this._context.moveTo(e,r);break;case 3:this._point=4;default:Mc(this,t,n)}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n}},Sc.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var t=this._x,n=this._y,e=t.length-1;if(e>0)for(var r,i=t[0],o=n[0],u=t[e]-i,a=n[e]-o,c=-1;++c<=e;)r=c/e,this._basis.point(this._beta*t[c]+(1-this._beta)*(i+r*u),this._beta*n[c]+(1-this._beta)*(o+r*a));this._x=this._y=null,this._basis.lineEnd()},point:function(t,n){this._x.push(+t),this._y.push(+n)}};var M_=function t(n){function e(t){return 1===n?new Tc(t):new Sc(t,n)}return e.beta=function(n){return t(+n)},e}(.85);Ac.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:Ec(this,this._x1,this._y1)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2,this._x1=t,this._y1=n;break;case 2:this._point=3;default:Ec(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var T_=function t(n){function e(t){return new Ac(t,n)}return e.tension=function(n){return t(+n)},e}(0);Cc.prototype={areaStart:wc,areaEnd:wc,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Ec(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var N_=function t(n){function e(t){return new Cc(t,n)}return e.tension=function(n){return t(+n)},e}(0);zc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Ec(this,t,n)}this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var k_=function t(n){function e(t){return new zc(t,n)}return e.tension=function(n){return t(+n)},e}(0);Rc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2)}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3;default:Pc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var S_=function t(n){function e(t){return n?new Rc(t,n):new Ac(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Lc.prototype={areaStart:wc,areaEnd:wc,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:this._context.moveTo(this._x3,this._y3),this._context.closePath();break;case 2:this._context.lineTo(this._x3,this._y3),this._context.closePath();break;case 3:this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5)}},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=t,this._y3=n;break;case 1:this._point=2,this._context.moveTo(this._x4=t,this._y4=n);break;case 2:this._point=3,this._x5=t,this._y5=n;break;default:Pc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var E_=function t(n){function e(t){return n?new Lc(t,n):new Cc(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);qc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||0!==this._line&&3===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){if(t=+t,n=+n,this._point){var e=this._x2-t,r=this._y2-n;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(e*e+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Pc(this,t,n)}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=t,this._y0=this._y1,this._y1=this._y2,this._y2=n}};var A_=function t(n){function e(t){return n?new qc(t,n):new zc(t,0)}return e.alpha=function(n){return t(+n)},e}(.5);Dc.prototype={areaStart:wc,areaEnd:wc,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(t,n){t=+t,n=+n,this._point?this._context.lineTo(t,n):(this._point=1,this._context.moveTo(t,n))}},Yc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:Ic(this,this._t0,Fc(this,this._t0))}(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){var e=NaN;if(t=+t,n=+n,t!==this._x1||n!==this._y1){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;break;case 2:this._point=3,Ic(this,Fc(this,e=Oc(this,t,n)),e);break;default:Ic(this,this._t0,e=Oc(this,t,n))}this._x0=this._x1,this._x1=t,this._y0=this._y1,this._y1=n,this._t0=e}}},(Bc.prototype=Object.create(Yc.prototype)).point=function(t,n){Yc.prototype.point.call(this,n,t)},Hc.prototype={moveTo:function(t,n){this._context.moveTo(n,t)},closePath:function(){this._context.closePath()},lineTo:function(t,n){this._context.lineTo(n,t)},bezierCurveTo:function(t,n,e,r,i,o){this._context.bezierCurveTo(n,t,r,e,o,i)}},jc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var t=this._x,n=this._y,e=t.length;if(e)if(this._line?this._context.lineTo(t[0],n[0]):this._context.moveTo(t[0],n[0]),2===e)this._context.lineTo(t[1],n[1]);else for(var r=Xc(t),i=Xc(n),o=0,u=1;u<e;++o,++u)this._context.bezierCurveTo(r[0][o],i[0][o],r[1][o],i[1][o],t[u],n[u]);(this._line||0!==this._line&&1===e)&&this._context.closePath(),this._line=1-this._line,this._x=this._y=null},point:function(t,n){this._x.push(+t),this._y.push(+n)}},Vc.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=this._y=NaN,this._point=0},lineEnd:function(){0<this._t&&this._t<1&&2===this._point&&this._context.lineTo(this._x,this._y),(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line>=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,n),this._context.lineTo(t,n);else{var e=this._x*(1-this._t)+t*this._t;this._context.lineTo(e,this._y),this._context.lineTo(e,n)}}this._x=t,this._y=n}},ns.prototype={constructor:ns,insert:function(t,n){var e,r,i;if(t){if(n.P=t,n.N=t.N,t.N&&(t.N.P=n),t.N=n,t.R){for(t=t.R;t.L;)t=t.L;t.L=n}else t.R=n;e=t}else this._?(t=os(this._),n.P=null,n.N=t,t.P=t.L=n,e=t):(n.P=n.N=null,this._=n,e=null);for(n.L=n.R=null,n.U=e,n.C=!0,t=n;e&&e.C;)e===(r=e.U).L?(i=r.R)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.R&&(rs(this,e),e=(t=e).U),e.C=!1,r.C=!0,is(this,r)):(i=r.L)&&i.C?(e.C=i.C=!1,r.C=!0,t=r):(t===e.L&&(is(this,e),e=(t=e).U),e.C=!1,r.C=!0,rs(this,r)),e=t.U;this._.C=!1},remove:function(t){t.N&&(t.N.P=t.P),t.P&&(t.P.N=t.N),t.N=t.P=null;var n,e,r,i=t.U,o=t.L,u=t.R;if(e=o?u?os(u):o:u,i?i.L===t?i.L=e:i.R=e:this._=e,o&&u?(r=e.C,e.C=t.C,e.L=o,o.U=e,e!==u?(i=e.U,e.U=t.U,t=e.R,i.L=t,e.R=u,u.U=e):(e.U=i,i=e,t=e.R)):(r=t.C,t=e),t&&(t.U=i),!r)if(t&&t.C)t.C=!1;else{do{if(t===this._)break;if(t===i.L){if((n=i.R).C&&(n.C=!1,i.C=!0,rs(this,i),n=i.R),n.L&&n.L.C||n.R&&n.R.C){n.R&&n.R.C||(n.L.C=!1,n.C=!0,is(this,n),n=i.R),n.C=i.C,i.C=n.R.C=!1,rs(this,i),t=this._;break}}else if((n=i.L).C&&(n.C=!1,i.C=!0,is(this,i),n=i.L),n.L&&n.L.C||n.R&&n.R.C){n.L&&n.L.C||(n.R.C=!1,n.C=!0,rs(this,n),n=i.L),n.C=i.C,i.C=n.L.C=!1,is(this,i),t=this._;break}n.C=!0,t=i,i=i.U}while(!t.C);t&&(t.C=!1)}}};var C_,z_,P_,R_,L_,q_=[],D_=[],U_=1e-6,O_=1e-12;Ms.prototype={constructor:Ms,polygons:function(){var t=this.edges;return this.cells.map(function(n){var e=n.halfedges.map(function(e){return hs(n,t[e])});return e.data=n.site.data,e})},triangles:function(){var t=[],n=this.edges;return this.cells.forEach(function(e,r){if(o=(i=e.halfedges).length)for(var i,o,u,a=e.site,c=-1,s=n[i[o-1]],f=s.left===a?s.right:s.left;++c<o;)u=f,f=(s=n[i[c]]).left===a?s.right:s.left,u&&f&&r<u.index&&r<f.index&&bs(a,u,f)<0&&t.push([a.data,u.data,f.data])}),t},links:function(){return this.edges.filter(function(t){return t.right}).map(function(t){return{source:t.left.data,target:t.right.data}})},find:function(t,n,e){for(var r,i,o=this,u=o._found||0,a=o.cells.length;!(i=o.cells[u]);)if(++u>=a)return null;var c=t-i.site[0],s=n-i.site[1],f=c*c+s*s;do{i=o.cells[r=u],u=null,i.halfedges.forEach(function(e){var r=o.edges[e],a=r.left;if(a!==i.site&&a||(a=r.right)){var c=t-a[0],s=n-a[1],l=c*c+s*s;l<f&&(f=l,u=a.index)}})}while(null!==u);return o._found=r,null==e||f<=e*e?i.site:null}},Ns.prototype={constructor:Ns,scale:function(t){return 1===t?this:new Ns(this.k*t,this.x,this.y)},translate:function(t,n){return 0===t&0===n?this:new Ns(this.k,this.x+this.k*t,this.y+this.k*n)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var F_=new Ns(1,0,0);ks.prototype=Ns.prototype,t.version="4.12.2",t.bisect=Ds,t.bisectRight=Ds,t.bisectLeft=Us,t.ascending=n,t.bisector=e,t.cross=function(t,n,e){var i,o,u,a,c=t.length,s=n.length,f=new Array(c*s);for(null==e&&(e=r),i=u=0;i<c;++i)for(a=t[i],o=0;o<s;++o,++u)f[u]=e(a,n[o]);return f},t.descending=function(t,n){return n<t?-1:n>t?1:n>=t?0:NaN},t.deviation=u,t.extent=a,t.histogram=function(){function t(t){var i,o,u=t.length,a=new Array(u);for(i=0;i<u;++i)a[i]=n(t[i],i,t);var c=e(a),s=c[0],l=c[1],h=r(a,s,l);Array.isArray(h)||(h=p(s,l,h),h=f(Math.ceil(s/h)*h,Math.floor(l/h)*h,h));for(var d=h.length;h[0]<=s;)h.shift(),--d;for(;h[d-1]>l;)h.pop(),--d;var v,g=new Array(d+1);for(i=0;i<=d;++i)(v=g[i]=[]).x0=i>0?h[i-1]:s,v.x1=i<d?h[i]:l;for(i=0;i<u;++i)s<=(o=a[i])&&o<=l&&g[Ds(h,o,0,d)].push(t[i]);return g}var n=s,e=a,r=d;return t.value=function(e){return arguments.length?(n="function"==typeof e?e:c(e),t):n},t.domain=function(n){return arguments.length?(e="function"==typeof n?n:c([n[0],n[1]]),t):e},t.thresholds=function(n){return arguments.length?(r="function"==typeof n?n:Array.isArray(n)?c(Fs.call(n)):c(n),t):r},t},t.thresholdFreedmanDiaconis=function(t,e,r){return t=Is.call(t,i).sort(n),Math.ceil((r-e)/(2*(v(t,.75)-v(t,.25))*Math.pow(t.length,-1/3)))},t.thresholdScott=function(t,n,e){return Math.ceil((e-n)/(3.5*u(t)*Math.pow(t.length,-1/3)))},t.thresholdSturges=d,t.max=function(t,n){var e,r,i=t.length,o=-1;if(null==n){for(;++o<i;)if(null!=(e=t[o])&&e>=e)for(r=e;++o<i;)null!=(e=t[o])&&e>r&&(r=e)}else for(;++o<i;)if(null!=(e=n(t[o],o,t))&&e>=e)for(r=e;++o<i;)null!=(e=n(t[o],o,t))&&e>r&&(r=e);return r},t.mean=function(t,n){var e,r=t.length,o=r,u=-1,a=0;if(null==n)for(;++u<r;)isNaN(e=i(t[u]))?--o:a+=e;else for(;++u<r;)isNaN(e=i(n(t[u],u,t)))?--o:a+=e;if(o)return a/o},t.median=function(t,e){var r,o=t.length,u=-1,a=[];if(null==e)for(;++u<o;)isNaN(r=i(t[u]))||a.push(r);else for(;++u<o;)isNaN(r=i(e(t[u],u,t)))||a.push(r);return v(a.sort(n),.5)},t.merge=g,t.min=_,t.pairs=function(t,n){null==n&&(n=r);for(var e=0,i=t.length-1,o=t[0],u=new Array(i<0?0:i);e<i;)u[e]=n(o,o=t[++e]);return u},t.permute=function(t,n){for(var e=n.length,r=new Array(e);e--;)r[e]=t[n[e]];return r},t.quantile=v,t.range=f,t.scan=function(t,e){if(r=t.length){var r,i,o=0,u=0,a=t[u];for(null==e&&(e=n);++o<r;)(e(i=t[o],a)<0||0!==e(a,a))&&(a=i,u=o);return 0===e(a,a)?u:void 0}},t.shuffle=function(t,n,e){for(var r,i,o=(null==e?t.length:e)-(n=null==n?0:+n);o;)i=Math.random()*o--|0,r=t[o+n],t[o+n]=t[i+n],t[i+n]=r;return t},t.sum=function(t,n){var e,r=t.length,i=-1,o=0;if(null==n)for(;++i<r;)(e=+t[i])&&(o+=e);else for(;++i<r;)(e=+n(t[i],i,t))&&(o+=e);return o},t.ticks=l,t.tickIncrement=h,t.tickStep=p,t.transpose=y,t.variance=o,t.zip=function(){return y(arguments)},t.axisTop=function(t){return T(Xs,t)},t.axisRight=function(t){return T(Vs,t)},t.axisBottom=function(t){return T($s,t)},t.axisLeft=function(t){return T(Ws,t)},t.brush=function(){return Qn(rh)},t.brushX=function(){return Qn(nh)},t.brushY=function(){return Qn(eh)},t.brushSelection=function(t){var n=t.__brush;return n?n.dim.output(n.selection):null},t.chord=function(){function t(t){var o,u,a,c,s,l,h=t.length,p=[],d=f(h),v=[],g=[],_=g.groups=new Array(h),y=new Array(h*h);for(o=0,s=-1;++s<h;){for(u=0,l=-1;++l<h;)u+=t[s][l];p.push(u),v.push(f(h)),o+=u}for(e&&d.sort(function(t,n){return e(p[t],p[n])}),r&&v.forEach(function(n,e){n.sort(function(n,i){return r(t[e][n],t[e][i])})}),c=(o=dh(0,ph-n*h)/o)?n:ph/h,u=0,s=-1;++s<h;){for(a=u,l=-1;++l<h;){var m=d[s],x=v[m][l],b=t[m][x],w=u,M=u+=b*o;y[x*h+m]={index:m,subindex:x,startAngle:w,endAngle:M,value:b}}_[m]={index:m,startAngle:a,endAngle:u,value:p[m]},u+=c}for(s=-1;++s<h;)for(l=s-1;++l<h;){var T=y[l*h+s],N=y[s*h+l];(T.value||N.value)&&g.push(T.value<N.value?{source:N,target:T}:{source:T,target:N})}return i?g.sort(i):g}var n=0,e=null,r=null,i=null;return t.padAngle=function(e){return arguments.length?(n=dh(0,e),t):n},t.sortGroups=function(n){return arguments.length?(e=n,t):e},t.sortSubgroups=function(n){return arguments.length?(r=n,t):r},t.sortChords=function(n){return arguments.length?(null==n?i=null:(i=function(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}(n))._=n,t):i&&i._},t},t.ribbon=function(){function t(){var t,a=vh.call(arguments),c=n.apply(this,a),s=e.apply(this,a),f=+r.apply(this,(a[0]=c,a)),l=i.apply(this,a)-hh,h=o.apply(this,a)-hh,p=f*sh(l),d=f*fh(l),v=+r.apply(this,(a[0]=s,a)),g=i.apply(this,a)-hh,_=o.apply(this,a)-hh;if(u||(u=t=te()),u.moveTo(p,d),u.arc(0,0,f,l,h),l===g&&h===_||(u.quadraticCurveTo(0,0,v*sh(g),v*fh(g)),u.arc(0,0,v,g,_)),u.quadraticCurveTo(0,0,p,d),u.closePath(),t)return u=null,t+""||null}var n=ne,e=ee,r=re,i=ie,o=oe,u=null;return t.radius=function(n){return arguments.length?(r="function"==typeof n?n:Jn(+n),t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:Jn(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:Jn(+n),t):o},t.source=function(e){return arguments.length?(n=e,t):n},t.target=function(n){return arguments.length?(e=n,t):e},t.context=function(n){return arguments.length?(u=null==n?null:n,t):u},t},t.nest=function(){function t(n,i,u,a){if(i>=o.length)return null!=e&&n.sort(e),null!=r?r(n):n;for(var c,s,f,l=-1,h=n.length,p=o[i++],d=ae(),v=u();++l<h;)(f=d.get(c=p(s=n[l])+""))?f.push(s):d.set(c,[s]);return d.each(function(n,e){a(v,e,t(n,i,u,a))}),v}function n(t,e){if(++e>o.length)return t;var i,a=u[e-1];return null!=r&&e>=o.length?i=t.entries():(i=[],t.each(function(t,r){i.push({key:r,values:n(t,e)})})),null!=a?i.sort(function(t,n){return a(t.key,n.key)}):i}var e,r,i,o=[],u=[];return i={object:function(n){return t(n,0,ce,se)},map:function(n){return t(n,0,fe,le)},entries:function(e){return n(t(e,0,fe,le),0)},key:function(t){return o.push(t),i},sortKeys:function(t){return u[o.length-1]=t,i},sortValues:function(t){return e=t,i},rollup:function(t){return r=t,i}}},t.set=pe,t.map=ae,t.keys=function(t){var n=[];for(var e in t)n.push(e);return n},t.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},t.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},t.color=kt,t.rgb=Ct,t.hsl=Rt,t.lab=Ut,t.hcl=Ht,t.cubehelix=Xt,t.dispatch=N,t.drag=function(){function n(t){t.on("mousedown.drag",e).filter(g).on("touchstart.drag",o).on("touchmove.drag",u).on("touchend.drag touchcancel.drag",a).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(){if(!h&&p.apply(this,arguments)){var n=c("mouse",d.apply(this,arguments),F,this,arguments);n&&(lt(t.event.view).on("mousemove.drag",r,!0).on("mouseup.drag",i,!0),vt(t.event.view),pt(),l=!1,s=t.event.clientX,f=t.event.clientY,n("start"))}}function r(){if(dt(),!l){var n=t.event.clientX-s,e=t.event.clientY-f;l=n*n+e*e>x}_.mouse("drag")}function i(){lt(t.event.view).on("mousemove.drag mouseup.drag",null),gt(t.event.view,l),dt(),_.mouse("end")}function o(){if(p.apply(this,arguments)){var n,e,r=t.event.changedTouches,i=d.apply(this,arguments),o=r.length;for(n=0;n<o;++n)(e=c(r[n].identifier,i,ht,this,arguments))&&(pt(),e("start"))}}function u(){var n,e,r=t.event.changedTouches,i=r.length;for(n=0;n<i;++n)(e=_[r[n].identifier])&&(dt(),e("drag"))}function a(){var n,e,r=t.event.changedTouches,i=r.length;for(h&&clearTimeout(h),h=setTimeout(function(){h=null},500),n=0;n<i;++n)(e=_[r[n].identifier])&&(pt(),e("end"))}function c(e,r,i,o,u){var a,c,s,f=i(r,e),l=y.copy();if(D(new yt(n,"beforestart",a,e,m,f[0],f[1],0,0,l),function(){return null!=(t.event.subject=a=v.apply(o,u))&&(c=a.x-f[0]||0,s=a.y-f[1]||0,!0)}))return function t(h){var p,d=f;switch(h){case"start":_[e]=t,p=m++;break;case"end":delete _[e],--m;case"drag":f=i(r,e),p=m}D(new yt(n,h,a,e,p,f[0]+c,f[1]+s,f[0]-d[0],f[1]-d[1],l),l.apply,l,[h,o,u])}}var s,f,l,h,p=mt,d=xt,v=bt,g=wt,_={},y=N("start","drag","end"),m=0,x=0;return n.filter=function(t){return arguments.length?(p="function"==typeof t?t:_t(!!t),n):p},n.container=function(t){return arguments.length?(d="function"==typeof t?t:_t(t),n):d},n.subject=function(t){return arguments.length?(v="function"==typeof t?t:_t(t),n):v},n.touchable=function(t){return arguments.length?(g="function"==typeof t?t:_t(!!t),n):g},n.on=function(){var t=y.on.apply(y,arguments);return t===y?n:t},n.clickDistance=function(t){return arguments.length?(x=(t=+t)*t,n):Math.sqrt(x)},n},t.dragDisable=vt,t.dragEnable=gt,t.dsvFormat=ve,t.csvParse=kh,t.csvParseRows=Sh,t.csvFormat=Eh,t.csvFormatRows=Ah,t.tsvParse=zh,t.tsvParseRows=Ph,t.tsvFormat=Rh,t.tsvFormatRows=Lh,t.easeLinear=function(t){return+t},t.easeQuad=Dn,t.easeQuadIn=function(t){return t*t},t.easeQuadOut=function(t){return t*(2-t)},t.easeQuadInOut=Dn,t.easeCubic=Un,t.easeCubicIn=function(t){return t*t*t},t.easeCubicOut=function(t){return--t*t*t+1},t.easeCubicInOut=Un,t.easePoly=Al,t.easePolyIn=Sl,t.easePolyOut=El,t.easePolyInOut=Al,t.easeSin=On,t.easeSinIn=function(t){return 1-Math.cos(t*zl)},t.easeSinOut=function(t){return Math.sin(t*zl)},t.easeSinInOut=On,t.easeExp=Fn,t.easeExpIn=function(t){return Math.pow(2,10*t-10)},t.easeExpOut=function(t){return 1-Math.pow(2,-10*t)},t.easeExpInOut=Fn,t.easeCircle=In,t.easeCircleIn=function(t){return 1-Math.sqrt(1-t*t)},t.easeCircleOut=function(t){return Math.sqrt(1- --t*t)},t.easeCircleInOut=In,t.easeBounce=Yn,t.easeBounceIn=function(t){return 1-Yn(1-t)},t.easeBounceOut=Yn,t.easeBounceInOut=function(t){return((t*=2)<=1?1-Yn(1-t):Yn(t-1)+1)/2},t.easeBack=jl,t.easeBackIn=Bl,t.easeBackOut=Hl,t.easeBackInOut=jl,t.easeElastic=$l,t.easeElasticIn=Vl,t.easeElasticOut=$l,t.easeElasticInOut=Wl,t.forceCenter=function(t,n){function e(){var e,i,o=r.length,u=0,a=0;for(e=0;e<o;++e)u+=(i=r[e]).x,a+=i.y;for(u=u/o-t,a=a/o-n,e=0;e<o;++e)(i=r[e]).x-=u,i.y-=a}var r;return null==t&&(t=0),null==n&&(n=0),e.initialize=function(t){r=t},e.x=function(n){return arguments.length?(t=+n,e):t},e.y=function(t){return arguments.length?(n=+t,e):n},e},t.forceCollide=function(t){function n(){for(var t,n,r,c,s,f,l,h=i.length,p=0;p<a;++p)for(n=we(i,Ne,ke).visitAfter(e),t=0;t<h;++t)r=i[t],f=o[r.index],l=f*f,c=r.x+r.vx,s=r.y+r.vy,n.visit(function(t,n,e,i,o){var a=t.data,h=t.r,p=f+h;if(!a)return n>c+p||i<c-p||e>s+p||o<s-p;if(a.index>r.index){var d=c-a.x-a.vx,v=s-a.y-a.vy,g=d*d+v*v;g<p*p&&(0===d&&(d=_e(),g+=d*d),0===v&&(v=_e(),g+=v*v),g=(p-(g=Math.sqrt(g)))/g*u,r.vx+=(d*=g)*(p=(h*=h)/(l+h)),r.vy+=(v*=g)*p,a.vx-=d*(p=1-p),a.vy-=v*p)}})}function e(t){if(t.data)return t.r=o[t.data.index];for(var n=t.r=0;n<4;++n)t[n]&&t[n].r>t.r&&(t.r=t[n].r)}function r(){if(i){var n,e,r=i.length;for(o=new Array(r),n=0;n<r;++n)e=i[n],o[e.index]=+t(e,n,i)}}var i,o,u=1,a=1;return"function"!=typeof t&&(t=ge(null==t?1:+t)),n.initialize=function(t){i=t,r()},n.iterations=function(t){return arguments.length?(a=+t,n):a},n.strength=function(t){return arguments.length?(u=+t,n):u},n.radius=function(e){return arguments.length?(t="function"==typeof e?e:ge(+e),r(),n):t},n},t.forceLink=function(t){function n(n){for(var e=0,r=t.length;e<p;++e)for(var i,a,c,f,l,h,d,v=0;v<r;++v)a=(i=t[v]).source,f=(c=i.target).x+c.vx-a.x-a.vx||_e(),l=c.y+c.vy-a.y-a.vy||_e(),f*=h=((h=Math.sqrt(f*f+l*l))-u[v])/h*n*o[v],l*=h,c.vx-=f*(d=s[v]),c.vy-=l*d,a.vx+=f*(d=1-d),a.vy+=l*d}function e(){if(a){var n,e,l=a.length,h=t.length,p=ae(a,f);for(n=0,c=new Array(l);n<h;++n)(e=t[n]).index=n,"object"!=typeof e.source&&(e.source=Ee(p,e.source)),"object"!=typeof e.target&&(e.target=Ee(p,e.target)),c[e.source.index]=(c[e.source.index]||0)+1,c[e.target.index]=(c[e.target.index]||0)+1;for(n=0,s=new Array(h);n<h;++n)e=t[n],s[n]=c[e.source.index]/(c[e.source.index]+c[e.target.index]);o=new Array(h),r(),u=new Array(h),i()}}function r(){if(a)for(var n=0,e=t.length;n<e;++n)o[n]=+l(t[n],n,t)}function i(){if(a)for(var n=0,e=t.length;n<e;++n)u[n]=+h(t[n],n,t)}var o,u,a,c,s,f=Se,l=function(t){return 1/Math.min(c[t.source.index],c[t.target.index])},h=ge(30),p=1;return null==t&&(t=[]),n.initialize=function(t){a=t,e()},n.links=function(r){return arguments.length?(t=r,e(),n):t},n.id=function(t){return arguments.length?(f=t,n):f},n.iterations=function(t){return arguments.length?(p=+t,n):p},n.strength=function(t){return arguments.length?(l="function"==typeof t?t:ge(+t),r(),n):l},n.distance=function(t){return arguments.length?(h="function"==typeof t?t:ge(+t),i(),n):h},n},t.forceManyBody=function(){function t(t){var n,a=i.length,c=we(i,Ae,Ce).visitAfter(e);for(u=t,n=0;n<a;++n)o=i[n],c.visit(r)}function n(){if(i){var t,n,e=i.length;for(a=new Array(e),t=0;t<e;++t)n=i[t],a[n.index]=+c(n,t,i)}}function e(t){var n,e,r,i,o,u=0,c=0;if(t.length){for(r=i=o=0;o<4;++o)(n=t[o])&&(e=Math.abs(n.value))&&(u+=n.value,c+=e,r+=e*n.x,i+=e*n.y);t.x=r/c,t.y=i/c}else{(n=t).x=n.data.x,n.y=n.data.y;do{u+=a[n.data.index]}while(n=n.next)}t.value=u}function r(t,n,e,r){if(!t.value)return!0;var i=t.x-o.x,c=t.y-o.y,h=r-n,p=i*i+c*c;if(h*h/l<p)return p<f&&(0===i&&(i=_e(),p+=i*i),0===c&&(c=_e(),p+=c*c),p<s&&(p=Math.sqrt(s*p)),o.vx+=i*t.value*u/p,o.vy+=c*t.value*u/p),!0;if(!(t.length||p>=f)){(t.data!==o||t.next)&&(0===i&&(i=_e(),p+=i*i),0===c&&(c=_e(),p+=c*c),p<s&&(p=Math.sqrt(s*p)));do{t.data!==o&&(h=a[t.data.index]*u/p,o.vx+=i*h,o.vy+=c*h)}while(t=t.next)}}var i,o,u,a,c=ge(-30),s=1,f=1/0,l=.81;return t.initialize=function(t){i=t,n()},t.strength=function(e){return arguments.length?(c="function"==typeof e?e:ge(+e),n(),t):c},t.distanceMin=function(n){return arguments.length?(s=n*n,t):Math.sqrt(s)},t.distanceMax=function(n){return arguments.length?(f=n*n,t):Math.sqrt(f)},t.theta=function(n){return arguments.length?(l=n*n,t):Math.sqrt(l)},t},t.forceRadial=function(t,n,e){function r(t){for(var r=0,i=o.length;r<i;++r){var c=o[r],s=c.x-n||1e-6,f=c.y-e||1e-6,l=Math.sqrt(s*s+f*f),h=(a[r]-l)*u[r]*t/l;c.vx+=s*h,c.vy+=f*h}}function i(){if(o){var n,e=o.length;for(u=new Array(e),a=new Array(e),n=0;n<e;++n)a[n]=+t(o[n],n,o),u[n]=isNaN(a[n])?0:+c(o[n],n,o)}}var o,u,a,c=ge(.1);return"function"!=typeof t&&(t=ge(+t)),null==n&&(n=0),null==e&&(e=0),r.initialize=function(t){o=t,i()},r.strength=function(t){return arguments.length?(c="function"==typeof t?t:ge(+t),i(),r):c},r.radius=function(n){return arguments.length?(t="function"==typeof n?n:ge(+n),i(),r):t},r.x=function(t){return arguments.length?(n=+t,r):n},r.y=function(t){return arguments.length?(e=+t,r):e},r},t.forceSimulation=function(t){function n(){e(),p.call("tick",o),u<a&&(h.stop(),p.call("end",o))}function e(){var n,e,r=t.length;for(u+=(s-u)*c,l.each(function(t){t(u)}),n=0;n<r;++n)null==(e=t[n]).fx?e.x+=e.vx*=f:(e.x=e.fx,e.vx=0),null==e.fy?e.y+=e.vy*=f:(e.y=e.fy,e.vy=0)}function r(){for(var n,e=0,r=t.length;e<r;++e){if(n=t[e],n.index=e,isNaN(n.x)||isNaN(n.y)){var i=Uh*Math.sqrt(e),o=e*Oh;n.x=i*Math.cos(o),n.y=i*Math.sin(o)}(isNaN(n.vx)||isNaN(n.vy))&&(n.vx=n.vy=0)}}function i(n){return n.initialize&&n.initialize(t),n}var o,u=1,a=.001,c=1-Math.pow(a,1/300),s=0,f=.6,l=ae(),h=xn(n),p=N("tick","end");return null==t&&(t=[]),r(),o={tick:e,restart:function(){return h.restart(n),o},stop:function(){return h.stop(),o},nodes:function(n){return arguments.length?(t=n,r(),l.each(i),o):t},alpha:function(t){return arguments.length?(u=+t,o):u},alphaMin:function(t){return arguments.length?(a=+t,o):a},alphaDecay:function(t){return arguments.length?(c=+t,o):+c},alphaTarget:function(t){return arguments.length?(s=+t,o):s},velocityDecay:function(t){return arguments.length?(f=1-t,o):1-f},force:function(t,n){return arguments.length>1?(null==n?l.remove(t):l.set(t,i(n)),o):l.get(t)},find:function(n,e,r){var i,o,u,a,c,s=0,f=t.length;for(null==r?r=1/0:r*=r,s=0;s<f;++s)(u=(i=n-(a=t[s]).x)*i+(o=e-a.y)*o)<r&&(c=a,r=u);return c},on:function(t,n){return arguments.length>1?(p.on(t,n),o):p.on(t)}}},t.forceX=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vx+=(o[e]-n.x)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ge(.1);return"function"!=typeof t&&(t=ge(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ge(+t),e(),n):u},n.x=function(r){return arguments.length?(t="function"==typeof r?r:ge(+r),e(),n):t},n},t.forceY=function(t){function n(t){for(var n,e=0,u=r.length;e<u;++e)(n=r[e]).vy+=(o[e]-n.y)*i[e]*t}function e(){if(r){var n,e=r.length;for(i=new Array(e),o=new Array(e),n=0;n<e;++n)i[n]=isNaN(o[n]=+t(r[n],n,r))?0:+u(r[n],n,r)}}var r,i,o,u=ge(.1);return"function"!=typeof t&&(t=ge(null==t?0:+t)),n.initialize=function(t){r=t,e()},n.strength=function(t){return arguments.length?(u="function"==typeof t?t:ge(+t),e(),n):u},n.y=function(r){return arguments.length?(t="function"==typeof r?r:ge(+r),e(),n):t},n},t.formatDefaultLocale=Oe,t.formatLocale=Ue,t.formatSpecifier=Le,t.precisionFixed=Fe,t.precisionPrefix=Ie,t.precisionRound=Ye,t.geoArea=function(t){return jp.reset(),Je(t,Xp),2*jp},t.geoBounds=function(t){var n,e,r,i,o,u,a;if(Qh=Gh=-(Wh=Zh=1/0),ep=[],Je(t,$p),e=ep.length){for(ep.sort(yr),n=1,o=[r=ep[0]];n<e;++n)mr(r,(i=ep[n])[0])||mr(r,i[1])?(_r(r[0],i[1])>_r(r[0],r[1])&&(r[1]=i[1]),_r(i[0],r[1])>_r(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-1/0,n=0,r=o[e=o.length-1];n<=e;r=i,++n)i=o[n],(a=_r(r[1],i[0]))>u&&(u=a,Wh=i[0],Gh=r[1])}return ep=rp=null,Wh===1/0||Zh===1/0?[[NaN,NaN],[NaN,NaN]]:[[Wh,Zh],[Gh,Qh]]},t.geoCentroid=function(t){ip=op=up=ap=cp=sp=fp=lp=hp=pp=dp=0,Je(t,Wp);var n=hp,e=pp,r=dp,i=n*n+e*e+r*r;return i<wp&&(n=sp,e=fp,r=lp,op<bp&&(n=up,e=ap,r=cp),(i=n*n+e*e+r*r)<wp)?[NaN,NaN]:[zp(e,n)*Sp,Ve(r/Fp(i))*Sp]},t.geoCircle=function(){function t(){var t=r.apply(this,arguments),a=i.apply(this,arguments)*Ep,c=o.apply(this,arguments)*Ep;return n=[],e=Rr(-t[0]*Ep,-t[1]*Ep,0).invert,Or(u,a,c,1),t={type:"Polygon",coordinates:[n]},n=e=null,t}var n,e,r=Cr([0,0]),i=Cr(90),o=Cr(6),u={point:function(t,r){n.push(t=e(t,r)),t[0]*=Sp,t[1]*=Sp}};return t.center=function(n){return arguments.length?(r="function"==typeof n?n:Cr([+n[0],+n[1]]),t):r},t.radius=function(n){return arguments.length?(i="function"==typeof n?n:Cr(+n),t):i},t.precision=function(n){return arguments.length?(o="function"==typeof n?n:Cr(+n),t):o},t},t.geoClipAntimeridian=ad,t.geoClipCircle=Zr,t.geoClipExtent=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=Gr(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][1],o=+a[1][0],u=+a[1][1],t=n=null,e):[[r,i],[o,u]]}}},t.geoClipRectangle=Gr,t.geoContains=function(t,n){return(t&&dd.hasOwnProperty(t.type)?dd[t.type]:ei)(t,n)},t.geoDistance=ni,t.geoGraticule=fi,t.geoGraticule10=function(){return fi()()},t.geoInterpolate=function(t,n){var e=t[0]*Ep,r=t[1]*Ep,i=n[0]*Ep,o=n[1]*Ep,u=Pp(r),a=Up(r),c=Pp(o),s=Up(o),f=u*Pp(e),l=u*Up(e),h=c*Pp(i),p=c*Up(i),d=2*Ve(Fp($e(o-r)+u*c*$e(i-e))),v=Up(d),g=d?function(t){var n=Up(t*=d)/v,e=Up(d-t)/v,r=e*f+n*h,i=e*l+n*p,o=e*a+n*s;return[zp(i,r)*Sp,zp(o,Fp(r*r+i*i))*Sp]}:function(){return[e*Sp,r*Sp]};return g.distance=d,g},t.geoLength=ti,t.geoPath=function(t,n){function e(t){return t&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),Je(t,r(i))),i.result()}var r,i,o=4.5;return e.area=function(t){return Je(t,r(yd)),yd.result()},e.measure=function(t){return Je(t,r(Id)),Id.result()},e.bounds=function(t){return Je(t,r(Md)),Md.result()},e.centroid=function(t){return Je(t,r(Rd)),Rd.result()},e.projection=function(n){return arguments.length?(r=null==n?(t=null,li):(t=n).stream,e):t},e.context=function(t){return arguments.length?(i=null==t?(n=null,new Ei):new Ni(n=t),"function"!=typeof o&&i.pointRadius(o),e):n},e.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),e):o},e.projection(t).context(n)},t.geoAlbers=Hi,t.geoAlbersUsa=function(){function t(t){var n=t[0],e=t[1];return a=null,i.point(n,e),a||(o.point(n,e),a)||(u.point(n,e),a)}function n(){return e=r=null,t}var e,r,i,o,u,a,c=Hi(),s=Bi().rotate([154,0]).center([-2,58.5]).parallels([55,65]),f=Bi().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(t,n){a=[t,n]}};return t.invert=function(t){var n=c.scale(),e=c.translate(),r=(t[0]-e[0])/n,i=(t[1]-e[1])/n;return(i>=.12&&i<.234&&r>=-.425&&r<-.214?s:i>=.166&&i<.234&&r>=-.214&&r<-.115?f:c).invert(t)},t.stream=function(t){return e&&r===t?e:e=function(t){var n=t.length;return{point:function(e,r){for(var i=-1;++i<n;)t[i].point(e,r)},sphere:function(){for(var e=-1;++e<n;)t[e].sphere()},lineStart:function(){for(var e=-1;++e<n;)t[e].lineStart()},lineEnd:function(){for(var e=-1;++e<n;)t[e].lineEnd()},polygonStart:function(){for(var e=-1;++e<n;)t[e].polygonStart()},polygonEnd:function(){for(var e=-1;++e<n;)t[e].polygonEnd()}}}([c.stream(r=t),s.stream(t),f.stream(t)])},t.precision=function(t){return arguments.length?(c.precision(t),s.precision(t),f.precision(t),n()):c.precision()},t.scale=function(n){return arguments.length?(c.scale(n),s.scale(.35*n),f.scale(n),t.translate(c.translate())):c.scale()},t.translate=function(t){if(!arguments.length)return c.translate();var e=c.scale(),r=+t[0],a=+t[1];return i=c.translate(t).clipExtent([[r-.455*e,a-.238*e],[r+.455*e,a+.238*e]]).stream(l),o=s.translate([r-.307*e,a+.201*e]).clipExtent([[r-.425*e+bp,a+.12*e+bp],[r-.214*e-bp,a+.234*e-bp]]).stream(l),u=f.translate([r-.205*e,a+.212*e]).clipExtent([[r-.214*e+bp,a+.166*e+bp],[r-.115*e-bp,a+.234*e-bp]]).stream(l),n()},t.fitExtent=function(n,e){return Ri(t,n,e)},t.fitSize=function(n,e){return Li(t,n,e)},t.fitWidth=function(n,e){return qi(t,n,e)},t.fitHeight=function(n,e){return Di(t,n,e)},t.scale(1070)},t.geoAzimuthalEqualArea=function(){return Oi(jd).scale(124.75).clipAngle(179.999)},t.geoAzimuthalEqualAreaRaw=jd,t.geoAzimuthalEquidistant=function(){return Oi(Xd).scale(79.4188).clipAngle(179.999)},t.geoAzimuthalEquidistantRaw=Xd,t.geoConicConformal=function(){return Ii(Zi).scale(109.5).parallels([30,30])},t.geoConicConformalRaw=Zi,t.geoConicEqualArea=Bi,t.geoConicEqualAreaRaw=Yi,t.geoConicEquidistant=function(){return Ii(Qi).scale(131.154).center([0,13.9389])},t.geoConicEquidistantRaw=Qi,t.geoEquirectangular=function(){return Oi(Gi).scale(152.63)},t.geoEquirectangularRaw=Gi,t.geoGnomonic=function(){return Oi(Ji).scale(144.049).clipAngle(60)},t.geoGnomonicRaw=Ji,t.geoIdentity=function(){function t(){return i=o=null,u}var n,e,r,i,o,u,a=1,c=0,s=0,f=1,l=1,h=li,p=null,d=li;return u={stream:function(t){return i&&o===t?i:i=h(d(o=t))},postclip:function(i){return arguments.length?(d=i,p=n=e=r=null,t()):d},clipExtent:function(i){return arguments.length?(d=null==i?(p=n=e=r=null,li):Gr(p=+i[0][0],n=+i[0][1],e=+i[1][0],r=+i[1][1]),t()):null==p?null:[[p,n],[e,r]]},scale:function(n){return arguments.length?(h=Ki((a=+n)*f,a*l,c,s),t()):a},translate:function(n){return arguments.length?(h=Ki(a*f,a*l,c=+n[0],s=+n[1]),t()):[c,s]},reflectX:function(n){return arguments.length?(h=Ki(a*(f=n?-1:1),a*l,c,s),t()):f<0},reflectY:function(n){return arguments.length?(h=Ki(a*f,a*(l=n?-1:1),c,s),t()):l<0},fitExtent:function(t,n){return Ri(u,t,n)},fitSize:function(t,n){return Li(u,t,n)},fitWidth:function(t,n){return qi(u,t,n)},fitHeight:function(t,n){return Di(u,t,n)}}},t.geoProjection=Oi,t.geoProjectionMutator=Fi,t.geoMercator=function(){return $i(Vi).scale(961/kp)},t.geoMercatorRaw=Vi,t.geoNaturalEarth1=function(){return Oi(to).scale(175.295)},t.geoNaturalEarth1Raw=to,t.geoOrthographic=function(){return Oi(no).scale(249.5).clipAngle(90+bp)},t.geoOrthographicRaw=no,t.geoStereographic=function(){return Oi(eo).scale(250).clipAngle(142)},t.geoStereographicRaw=eo,t.geoTransverseMercator=function(){var t=$i(ro),n=t.center,e=t.rotate;return t.center=function(t){return arguments.length?n([-t[1],t[0]]):(t=n(),[t[1],-t[0]])},t.rotate=function(t){return arguments.length?e([t[0],t[1],t.length>2?t[2]+90:90]):(t=e(),[t[0],t[1],t[2]-90])},e([0,0,90]).scale(159.155)},t.geoTransverseMercatorRaw=ro,t.geoRotation=Ur,t.geoStream=Je,t.geoTransform=function(t){return{stream:Ci(t)}},t.cluster=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=function(t){return t.reduce(oo,0)/t.length}(e),t.y=function(t){return 1+t.reduce(uo,0)}(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=function(t){for(var n;n=t.children;)t=n[0];return t}(t),c=function(t){for(var n;n=t.children;)t=n[n.length-1];return t}(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=io,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},t.hierarchy=co,t.pack=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Ao(n)).eachAfter(Co(i,.5)).eachBefore(zo(1)):t.eachBefore(Ao(Eo)).eachAfter(Co(ko,1)).eachAfter(Co(i,t.r/Math.min(e,r))).eachBefore(zo(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=ko;return t.radius=function(e){return arguments.length?(n=function(t){return null==t?null:No(t)}(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:So(+n),t):i},t},t.packSiblings=function(t){return To(t),t},t.packEnclose=po,t.partition=function(){function t(t){var o=t.height+1;return t.x0=t.y0=r,t.x1=n,t.y1=e/o,t.eachBefore(function(t,n){return function(e){e.children&&Ro(e,e.x0,t*(e.depth+1)/n,e.x1,t*(e.depth+2)/n);var i=e.x0,o=e.y0,u=e.x1-r,a=e.y1-r;u<i&&(i=u=(i+u)/2),a<o&&(o=a=(o+a)/2),e.x0=i,e.y0=o,e.x1=u,e.y1=a}}(e,o)),i&&t.eachBefore(Po),t}var n=1,e=1,r=0,i=!1;return t.round=function(n){return arguments.length?(i=!!n,t):i},t.size=function(r){return arguments.length?(n=+r[0],e=+r[1],t):[n,e]},t.padding=function(n){return arguments.length?(r=+n,t):r},t},t.stratify=function(){function t(t){var r,i,o,u,a,c,s,f=t.length,l=new Array(f),h={};for(i=0;i<f;++i)r=t[i],a=l[i]=new ho(r),null!=(c=n(r,i,t))&&(c+="")&&(h[s=$d+(a.id=c)]=s in h?Zd:a);for(i=0;i<f;++i)if(a=l[i],null!=(c=e(t[i],i,t))&&(c+="")){if(!(u=h[$d+c]))throw new Error("missing: "+c);if(u===Zd)throw new Error("ambiguous: "+c);u.children?u.children.push(a):u.children=[a],a.parent=u}else{if(o)throw new Error("multiple roots");o=a}if(!o)throw new Error("no root");if(o.parent=Wd,o.eachBefore(function(t){t.depth=t.parent.depth+1,--f}).eachBefore(lo),o.parent=null,f>0)throw new Error("cycle");return o}var n=Lo,e=qo;return t.id=function(e){return arguments.length?(n=No(e),t):n},t.parentId=function(n){return arguments.length?(e=No(n),t):e},t},t.tree=function(){function t(t){var c=function(t){for(var n,e,r,i,o,u=new Yo(t,0),a=[u];n=a.pop();)if(r=n._.children)for(n.children=new Array(o=r.length),i=o-1;i>=0;--i)a.push(e=n.children[i]=new Yo(r[i],i)),e.parent=n;return(u.parent=new Yo(null,0)).children=[u],u}(t);if(c.eachAfter(n),c.parent.m=-c.z,c.eachBefore(e),a)t.eachBefore(r);else{var s=t,f=t,l=t;t.eachBefore(function(t){t.x<s.x&&(s=t),t.x>f.x&&(f=t),t.depth>l.depth&&(l=t)});var h=s===f?1:i(s,f)/2,p=h-s.x,d=o/(f.x+h+p),v=u/(l.depth||1);t.eachBefore(function(t){t.x=(t.x+p)*d,t.y=t.depth*v})}return t}function n(t){var n=t.children,e=t.parent.children,r=t.i?e[t.i-1]:null;if(n){(function(t){for(var n,e=0,r=0,i=t.children,o=i.length;--o>=0;)(n=i[o]).z+=e,n.m+=e,e+=n.s+(r+=n.c)})(t);var o=(n[0].z+n[n.length-1].z)/2;r?(t.z=r.z+i(t._,r._),t.m=t.z-o):t.z=o}else r&&(t.z=r.z+i(t._,r._));t.parent.A=function(t,n,e){if(n){for(var r,o=t,u=t,a=n,c=o.parent.children[0],s=o.m,f=u.m,l=a.m,h=c.m;a=Oo(a),o=Uo(o),a&&o;)c=Uo(c),(u=Oo(u)).a=t,(r=a.z+l-o.z-s+i(a._,o._))>0&&(Fo(Io(a,t,e),t,r),s+=r,f+=r),l+=a.m,s+=o.m,h+=c.m,f+=u.m;a&&!Oo(u)&&(u.t=a,u.m+=l-f),o&&!Uo(c)&&(c.t=o,c.m+=s-h,e=t)}return e}(t,r,t.parent.A||e[0])}function e(t){t._.x=t.z+t.parent.m,t.m+=t.parent.m}function r(t){t.x*=o,t.y=t.depth*u}var i=Do,o=1,u=1,a=null;return t.separation=function(n){return arguments.length?(i=n,t):i},t.size=function(n){return arguments.length?(a=!1,o=+n[0],u=+n[1],t):a?null:[o,u]},t.nodeSize=function(n){return arguments.length?(a=!0,o=+n[0],u=+n[1],t):a?[o,u]:null},t},t.treemap=function(){function t(t){return t.x0=t.y0=0,t.x1=i,t.y1=o,t.eachBefore(n),u=[0],r&&t.eachBefore(Po),t}function n(t){var n=u[t.depth],r=t.x0+n,i=t.y0+n,o=t.x1-n,h=t.y1-n;o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),t.x0=r,t.y0=i,t.x1=o,t.y1=h,t.children&&(n=u[t.depth+1]=a(t)/2,r+=l(t)-n,i+=c(t)-n,o-=s(t)-n,h-=f(t)-n,o<r&&(r=o=(r+o)/2),h<i&&(i=h=(i+h)/2),e(t,r,i,o,h))}var e=Qd,r=!1,i=1,o=1,u=[0],a=ko,c=ko,s=ko,f=ko,l=ko;return t.round=function(n){return arguments.length?(r=!!n,t):r},t.size=function(n){return arguments.length?(i=+n[0],o=+n[1],t):[i,o]},t.tile=function(n){return arguments.length?(e=No(n),t):e},t.padding=function(n){return arguments.length?t.paddingInner(n).paddingOuter(n):t.paddingInner()},t.paddingInner=function(n){return arguments.length?(a="function"==typeof n?n:So(+n),t):a},t.paddingOuter=function(n){return arguments.length?t.paddingTop(n).paddingRight(n).paddingBottom(n).paddingLeft(n):t.paddingTop()},t.paddingTop=function(n){return arguments.length?(c="function"==typeof n?n:So(+n),t):c},t.paddingRight=function(n){return arguments.length?(s="function"==typeof n?n:So(+n),t):s},t.paddingBottom=function(n){return arguments.length?(f="function"==typeof n?n:So(+n),t):f},t.paddingLeft=function(n){return arguments.length?(l="function"==typeof n?n:So(+n),t):l},t},t.treemapBinary=function(t,n,e,r,i){function o(t,n,e,r,i,u,a){if(t>=n-1){var s=c[t];return s.x0=r,s.y0=i,s.x1=u,void(s.y1=a)}for(var l=f[t],h=e/2+l,p=t+1,d=n-1;p<d;){var v=p+d>>>1;f[v]<h?p=v+1:d=v}h-f[p-1]<f[p]-h&&t+1<p&&--p;var g=f[p]-l,_=e-g;if(u-r>a-i){var y=(r*_+u*g)/e;o(t,p,g,r,i,y,a),o(p,n,_,y,i,u,a)}else{var m=(i*_+a*g)/e;o(t,p,g,r,i,u,m),o(p,n,_,r,m,u,a)}}var u,a,c=t.children,s=c.length,f=new Array(s+1);for(f[0]=a=u=0;u<s;++u)f[u+1]=a+=c[u].value;o(0,s,t.value,n,e,r,i)},t.treemapDice=Ro,t.treemapSlice=Bo,t.treemapSliceDice=function(t,n,e,r,i){(1&t.depth?Bo:Ro)(t,n,e,r,i)},t.treemapSquarify=Qd,t.treemapResquarify=Jd,t.interpolate=cn,t.interpolateArray=en,t.interpolateBasis=Wt,t.interpolateBasisClosed=Zt,t.interpolateDate=rn,t.interpolateNumber=on,t.interpolateObject=un,t.interpolateRound=sn,t.interpolateString=an,t.interpolateTransformCss=Wf,t.interpolateTransformSvg=Zf,t.interpolateZoom=pn,t.interpolateRgb=Yf,t.interpolateRgbBasis=Bf,t.interpolateRgbBasisClosed=Hf,t.interpolateHsl=tl,t.interpolateHslLong=nl,t.interpolateLab=function(t,n){var e=tn((t=Ut(t)).l,(n=Ut(n)).l),r=tn(t.a,n.a),i=tn(t.b,n.b),o=tn(t.opacity,n.opacity);return function(n){return t.l=e(n),t.a=r(n),t.b=i(n),t.opacity=o(n),t+""}},t.interpolateHcl=el,t.interpolateHclLong=rl,t.interpolateCubehelix=il,t.interpolateCubehelixLong=ol,t.quantize=function(t,n){for(var e=new Array(n),r=0;r<n;++r)e[r]=t(r/(n-1));return e},t.path=te,t.polygonArea=function(t){for(var n,e=-1,r=t.length,i=t[r-1],o=0;++e<r;)n=i,i=t[e],o+=n[1]*i[0]-n[0]*i[1];return o/2},t.polygonCentroid=function(t){for(var n,e,r=-1,i=t.length,o=0,u=0,a=t[i-1],c=0;++r<i;)n=a,a=t[r],c+=e=n[0]*a[1]-a[0]*n[1],o+=(n[0]+a[0])*e,u+=(n[1]+a[1])*e;return c*=3,[o/c,u/c]},t.polygonHull=function(t){if((e=t.length)<3)return null;var n,e,r=new Array(e),i=new Array(e);for(n=0;n<e;++n)r[n]=[+t[n][0],+t[n][1],n];for(r.sort(Xo),n=0;n<e;++n)i[n]=[r[n][0],-r[n][1]];var o=Vo(r),u=Vo(i),a=u[0]===o[0],c=u[u.length-1]===o[o.length-1],s=[];for(n=o.length-1;n>=0;--n)s.push(t[r[o[n]][2]]);for(n=+a;n<u.length-c;++n)s.push(t[r[u[n]][2]]);return s},t.polygonContains=function(t,n){for(var e,r,i=t.length,o=t[i-1],u=n[0],a=n[1],c=o[0],s=o[1],f=!1,l=0;l<i;++l)e=(o=t[l])[0],(r=o[1])>a!=s>a&&u<(c-e)*(a-r)/(s-r)+e&&(f=!f),c=e,s=r;return f},t.polygonLength=function(t){for(var n,e,r=-1,i=t.length,o=t[i-1],u=o[0],a=o[1],c=0;++r<i;)n=u,e=a,n-=u=(o=t[r])[0],e-=a=o[1],c+=Math.sqrt(n*n+e*e);return c},t.quadtree=we,t.queue=Qo,t.randomUniform=nv,t.randomNormal=ev,t.randomLogNormal=rv,t.randomBates=ov,t.randomIrwinHall=iv,t.randomExponential=uv,t.request=Ko,t.html=av,t.json=cv,t.text=sv,t.xml=fv,t.csv=lv,t.tsv=hv,t.scaleBand=ru,t.scalePoint=function(){return iu(ru().paddingInner(1))},t.scaleIdentity=du,t.scaleLinear=pu,t.scaleLog=wu,t.scaleOrdinal=eu,t.scaleImplicit=gv,t.scalePow=Tu,t.scaleSqrt=function(){return Tu().exponent(.5)},t.scaleQuantile=Nu,t.scaleQuantize=ku,t.scaleThreshold=Su,t.scaleTime=function(){return ja(Wv,Vv,Pv,Cv,Ev,kv,Tv,xv,t.timeFormat).domain([new Date(2e3,0,1),new Date(2e3,0,2)])},t.scaleUtc=function(){return ja(yg,gg,eg,tg,Jv,Gv,Tv,xv,t.utcFormat).domain([Date.UTC(2e3,0,1),Date.UTC(2e3,0,2)])},t.schemeCategory10=qg,t.schemeCategory20b=Dg,t.schemeCategory20c=Ug,t.schemeCategory20=Og,t.interpolateCubehelixDefault=Fg,t.interpolateRainbow=function(t){(t<0||t>1)&&(t-=Math.floor(t));var n=Math.abs(t-.5);return Bg.h=360*t-100,Bg.s=1.5-1.5*n,Bg.l=.8-.9*n,Bg+""},t.interpolateWarm=Ig,t.interpolateCool=Yg,t.interpolateViridis=Hg,t.interpolateMagma=jg,t.interpolateInferno=Xg,t.interpolatePlasma=Vg,t.scaleSequential=$a,t.creator=A,t.local=C,t.matcher=rf,t.mouse=F,t.namespace=E,t.namespaces=Js,t.clientPoint=O,t.select=lt,t.selectAll=function(t){return"string"==typeof t?new st([document.querySelectorAll(t)],[document.documentElement]):new st([null==t?[]:t],af)},t.selection=ft,t.selector=Y,t.selectorAll=H,t.style=G,t.touch=ht,t.touches=function(t,n){null==n&&(n=U().touches);for(var e=0,r=n?n.length:0,i=new Array(r);e<r;++e)i[e]=O(t,n[e]);return i},t.window=Z,t.customEvent=D,t.arc=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-e_,p=u.apply(this,arguments)-e_,d=$g(p-h),v=p>h;if(c||(c=t=te()),l<f&&(s=l,l=f,f=s),l>t_)if(d>r_-t_)c.moveTo(l*Zg(h),l*Jg(h)),c.arc(0,0,l,h,p,!v),f>t_&&(c.moveTo(f*Zg(p),f*Jg(p)),c.arc(0,0,f,p,h,v));else{var g,_,y=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,N=T>t_&&(i?+i.apply(this,arguments):Kg(f*f+l*l)),k=Qg($g(l-f)/2,+r.apply(this,arguments)),S=k,E=k;if(N>t_){var A=Za(N/f*Jg(T)),C=Za(N/l*Jg(T));(w-=2*A)>t_?(A*=v?1:-1,x+=A,b-=A):(w=0,x=b=(h+p)/2),(M-=2*C)>t_?(C*=v?1:-1,y+=C,m-=C):(M=0,y=m=(h+p)/2)}var z=l*Zg(y),P=l*Jg(y),R=f*Zg(b),L=f*Jg(b);if(k>t_){var q=l*Zg(m),D=l*Jg(m),U=f*Zg(x),O=f*Jg(x);if(d<n_){var F=w>t_?function(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}(z,P,U,O,q,D,R,L):[R,L],I=z-F[0],Y=P-F[1],B=q-F[0],H=D-F[1],j=1/Jg(function(t){return t>1?0:t<-1?n_:Math.acos(t)}((I*B+Y*H)/(Kg(I*I+Y*Y)*Kg(B*B+H*H)))/2),X=Kg(F[0]*F[0]+F[1]*F[1]);S=Qg(k,(f-X)/(j-1)),E=Qg(k,(l-X)/(j+1))}}M>t_?E>t_?(g=nc(U,O,z,P,l,E,v),_=nc(q,D,R,L,l,E,v),c.moveTo(g.cx+g.x01,g.cy+g.y01),E<k?c.arc(g.cx,g.cy,E,Wg(g.y01,g.x01),Wg(_.y01,_.x01),!v):(c.arc(g.cx,g.cy,E,Wg(g.y01,g.x01),Wg(g.y11,g.x11),!v),c.arc(0,0,l,Wg(g.cy+g.y11,g.cx+g.x11),Wg(_.cy+_.y11,_.cx+_.x11),!v),c.arc(_.cx,_.cy,E,Wg(_.y11,_.x11),Wg(_.y01,_.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,y,m,!v)):c.moveTo(z,P),f>t_&&w>t_?S>t_?(g=nc(R,L,q,D,f,-S,v),_=nc(z,P,U,O,f,-S,v),c.lineTo(g.cx+g.x01,g.cy+g.y01),S<k?c.arc(g.cx,g.cy,S,Wg(g.y01,g.x01),Wg(_.y01,_.x01),!v):(c.arc(g.cx,g.cy,S,Wg(g.y01,g.x01),Wg(g.y11,g.x11),!v),c.arc(0,0,f,Wg(g.cy+g.y11,g.cx+g.x11),Wg(_.cy+_.y11,_.cx+_.x11),v),c.arc(_.cx,_.cy,S,Wg(_.y11,_.x11),Wg(_.y01,_.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(R,L)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=Ga,e=Qa,r=Wa(0),i=null,o=Ja,u=Ka,a=tc,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-n_/2;return[Zg(r)*t,Jg(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:Wa(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:Wa(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:Wa(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:Wa(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:Wa(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:Wa(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:Wa(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t},t.area=ac,t.line=uc,t.pie=function(){function t(t){var a,c,s,f,l,h=t.length,p=0,d=new Array(h),v=new Array(h),g=+i.apply(this,arguments),_=Math.min(r_,Math.max(-r_,o.apply(this,arguments)-g)),y=Math.min(Math.abs(_)/h,u.apply(this,arguments)),m=y*(_<0?-1:1);for(a=0;a<h;++a)(l=v[d[a]=a]=+n(t[a],a,t))>0&&(p+=l);for(null!=e?d.sort(function(t,n){return e(v[t],v[n])}):null!=r&&d.sort(function(n,e){return r(t[n],t[e])}),a=0,s=p?(_-h*m)/p:0;a<h;++a,g=f)c=d[a],f=g+((l=v[c])>0?l*s:0)+m,v[c]={data:t[c],index:a,value:l,startAngle:g,endAngle:f,padAngle:y};return v}var n=sc,e=cc,r=null,i=Wa(0),o=Wa(r_),u=Wa(0);return t.value=function(e){return arguments.length?(n="function"==typeof e?e:Wa(+e),t):n},t.sortValues=function(n){return arguments.length?(e=n,r=null,t):e},t.sort=function(n){return arguments.length?(r=n,e=null,t):r},t.startAngle=function(n){return arguments.length?(i="function"==typeof n?n:Wa(+n),t):i},t.endAngle=function(n){return arguments.length?(o="function"==typeof n?n:Wa(+n),t):o},t.padAngle=function(n){return arguments.length?(u="function"==typeof n?n:Wa(+n),t):u},t},t.areaRadial=dc,t.radialArea=dc,t.lineRadial=pc,t.radialLine=pc,t.pointRadial=vc,t.linkHorizontal=function(){return yc(mc)},t.linkVertical=function(){return yc(xc)},t.linkRadial=function(){var t=yc(bc);return t.angle=t.x,delete t.x,t.radius=t.y,delete t.y,t},t.symbol=function(){function t(){var t;if(r||(r=t=te()),n.apply(this,arguments).draw(r,+e.apply(this,arguments)),t)return r=null,t+""||null}var n=Wa(u_),e=Wa(64),r=null;return t.type=function(e){return arguments.length?(n="function"==typeof e?e:Wa(e),t):n},t.size=function(n){return arguments.length?(e="function"==typeof n?n:Wa(+n),t):e},t.context=function(n){return arguments.length?(r=null==n?null:n,t):r},t},t.symbols=w_,t.symbolCircle=u_,t.symbolCross=a_,t.symbolDiamond=f_,t.symbolSquare=v_,t.symbolStar=d_,t.symbolTriangle=__,t.symbolWye=b_,t.curveBasisClosed=function(t){return new Nc(t)},t.curveBasisOpen=function(t){return new kc(t)},t.curveBasis=function(t){return new Tc(t)},t.curveBundle=M_,t.curveCardinalClosed=N_,t.curveCardinalOpen=k_,t.curveCardinal=T_,t.curveCatmullRomClosed=E_,t.curveCatmullRomOpen=A_,t.curveCatmullRom=S_,t.curveLinearClosed=function(t){return new Dc(t)},t.curveLinear=rc,t.curveMonotoneX=function(t){return new Yc(t)},t.curveMonotoneY=function(t){return new Bc(t)},t.curveNatural=function(t){return new jc(t)},t.curveStep=function(t){return new Vc(t,.5)},t.curveStepAfter=function(t){return new Vc(t,1)},t.curveStepBefore=function(t){return new Vc(t,0)},t.stack=function(){function t(t){var o,u,a=n.apply(this,arguments),c=t.length,s=a.length,f=new Array(s);for(o=0;o<s;++o){for(var l,h=a[o],p=f[o]=new Array(c),d=0;d<c;++d)p[d]=l=[0,+i(t[d],h,d,t)],l.data=t[d];p.key=h}for(o=0,u=e(f);o<s;++o)f[u[o]].index=o;return r(f,u),f}var n=Wa([]),e=Wc,r=$c,i=Zc;return t.keys=function(e){return arguments.length?(n="function"==typeof e?e:Wa(o_.call(e)),t):n},t.value=function(n){return arguments.length?(i="function"==typeof n?n:Wa(+n),t):i},t.order=function(n){return arguments.length?(e=null==n?Wc:"function"==typeof n?n:Wa(o_.call(n)),t):e},t.offset=function(n){return arguments.length?(r=null==n?$c:n,t):r},t},t.stackOffsetExpand=function(t,n){if((r=t.length)>0){for(var e,r,i,o=0,u=t[0].length;o<u;++o){for(i=e=0;e<r;++e)i+=t[e][o][1]||0;if(i)for(e=0;e<r;++e)t[e][o][1]/=i}$c(t,n)}},t.stackOffsetDiverging=function(t,n){if((a=t.length)>1)for(var e,r,i,o,u,a,c=0,s=t[n[0]].length;c<s;++c)for(o=u=0,e=0;e<a;++e)(i=(r=t[n[e]][c])[1]-r[0])>=0?(r[0]=o,r[1]=o+=i):i<0?(r[1]=u,r[0]=u+=i):r[0]=o},t.stackOffsetNone=$c,t.stackOffsetSilhouette=function(t,n){if((e=t.length)>0){for(var e,r=0,i=t[n[0]],o=i.length;r<o;++r){for(var u=0,a=0;u<e;++u)a+=t[u][r][1]||0;i[r][1]+=i[r][0]=-a/2}$c(t,n)}},t.stackOffsetWiggle=function(t,n){if((i=t.length)>0&&(r=(e=t[n[0]]).length)>0){for(var e,r,i,o=0,u=1;u<r;++u){for(var a=0,c=0,s=0;a<i;++a){for(var f=t[n[a]],l=f[u][1]||0,h=(l-(f[u-1][1]||0))/2,p=0;p<a;++p){var d=t[n[p]];h+=(d[u][1]||0)-(d[u-1][1]||0)}c+=l,s+=h*l}e[u-1][1]+=e[u-1][0]=o,c&&(o-=s/c)}e[u-1][1]+=e[u-1][0]=o,$c(t,n)}},t.stackOrderAscending=Gc,t.stackOrderDescending=function(t){return Gc(t).reverse()},t.stackOrderInsideOut=function(t){var n,e,r=t.length,i=t.map(Qc),o=Wc(t).sort(function(t,n){return i[n]-i[t]}),u=0,a=0,c=[],s=[];for(n=0;n<r;++n)e=o[n],u<a?(u+=i[e],c.push(e)):(a+=i[e],s.push(e));return s.reverse().concat(c)},t.stackOrderNone=Wc,t.stackOrderReverse=function(t){return Wc(t).reverse()},t.timeInterval=Eu,t.timeMillisecond=xv,t.timeMilliseconds=bv,t.utcMillisecond=xv,t.utcMilliseconds=bv,t.timeSecond=Tv,t.timeSeconds=Nv,t.utcSecond=Tv,t.utcSeconds=Nv,t.timeMinute=kv,t.timeMinutes=Sv,t.timeHour=Ev,t.timeHours=Av,t.timeDay=Cv,t.timeDays=zv,t.timeWeek=Pv,t.timeWeeks=Fv,t.timeSunday=Pv,t.timeSundays=Fv,t.timeMonday=Rv,t.timeMondays=Iv,t.timeTuesday=Lv,t.timeTuesdays=Yv,t.timeWednesday=qv,t.timeWednesdays=Bv,t.timeThursday=Dv,t.timeThursdays=Hv,t.timeFriday=Uv,t.timeFridays=jv,t.timeSaturday=Ov,t.timeSaturdays=Xv,t.timeMonth=Vv,t.timeMonths=$v,t.timeYear=Wv,t.timeYears=Zv,t.utcMinute=Gv,t.utcMinutes=Qv,t.utcHour=Jv,t.utcHours=Kv,t.utcDay=tg,t.utcDays=ng,t.utcWeek=eg,t.utcWeeks=sg,t.utcSunday=eg,t.utcSundays=sg,t.utcMonday=rg,t.utcMondays=fg,t.utcTuesday=ig,t.utcTuesdays=lg,t.utcWednesday=og,t.utcWednesdays=hg,t.utcThursday=ug,t.utcThursdays=pg,t.utcFriday=ag,t.utcFridays=dg,t.utcSaturday=cg,t.utcSaturdays=vg,t.utcMonth=gg,t.utcMonths=_g,t.utcYear=yg,t.utcYears=xg,t.timeFormatDefaultLocale=Ya,t.timeFormatLocale=Lu,t.isoFormat=kg,t.isoParse=Sg,t.now=_n,t.timer=xn,t.timerFlush=bn,t.timeout=Nn,t.interval=function(t,n,e){var r=new mn,i=n;return null==n?(r.restart(t,n,e),r):(n=+n,e=null==e?_n():+e,r.restart(function o(u){u+=i,r.restart(o,i+=n,e),t(u)},n,e),r)},t.transition=Ln,t.active=function(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>yl&&e.name===n)return new Rn([[t]],Gl,n,+r)}return null},t.interrupt=Cn,t.voronoi=function(){function t(t){return new Ms(t.map(function(r,i){var o=[Math.round(n(r,i,t)/U_)*U_,Math.round(e(r,i,t)/U_)*U_];return o.index=i,o.data=r,o}),r)}var n=Kc,e=ts,r=null;return t.polygons=function(n){return t(n).polygons()},t.links=function(n){return t(n).links()},t.triangles=function(n){return t(n).triangles()},t.x=function(e){return arguments.length?(n="function"==typeof e?e:Jc(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:Jc(+n),t):e},t.extent=function(n){return arguments.length?(r=null==n?null:[[+n[0][0],+n[0][1]],[+n[1][0],+n[1][1]]],t):r&&[[r[0][0],r[0][1]],[r[1][0],r[1][1]]]},t.size=function(n){return arguments.length?(r=null==n?null:[[0,0],[+n[0],+n[1]]],t):r&&[r[1][0]-r[0][0],r[1][1]-r[0][1]]},t},t.zoom=function(){function n(t){t.property("__zoom",zs).on("wheel.zoom",c).on("mousedown.zoom",s).on("dblclick.zoom",f).filter(x).on("touchstart.zoom",l).on("touchmove.zoom",h).on("touchend.zoom touchcancel.zoom",p).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function e(t,n){return(n=Math.max(b[0],Math.min(b[1],n)))===t.k?t:new Ns(n,t.x,t.y)}function r(t,n,e){var r=n[0]-e[0]*t.k,i=n[1]-e[1]*t.k;return r===t.x&&i===t.y?t:new Ns(t.k,r,i)}function i(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function o(t,n,e){t.on("start.zoom",function(){u(this,arguments).start()}).on("interrupt.zoom end.zoom",function(){u(this,arguments).end()}).tween("zoom",function(){var t=arguments,r=u(this,t),o=_.apply(this,t),a=e||i(o),c=Math.max(o[1][0]-o[0][0],o[1][1]-o[0][1]),s=this.__zoom,f="function"==typeof n?n.apply(this,t):n,l=T(s.invert(a).concat(c/s.k),f.invert(a).concat(c/f.k));return function(t){if(1===t)t=f;else{var n=l(t),e=c/n[2];t=new Ns(e,a[0]-n[0]*e,a[1]-n[1]*e)}r.zoom(null,t)}})}function u(t,n){for(var e,r=0,i=k.length;r<i;++r)if((e=k[r]).that===t)return e;return new a(t,n)}function a(t,n){this.that=t,this.args=n,this.index=-1,this.active=0,this.extent=_.apply(t,n)}function c(){if(g.apply(this,arguments)){var t=u(this,arguments),n=this.__zoom,i=Math.max(b[0],Math.min(b[1],n.k*Math.pow(2,m.apply(this,arguments)))),o=F(this);if(t.wheel)t.mouse[0][0]===o[0]&&t.mouse[0][1]===o[1]||(t.mouse[1]=n.invert(t.mouse[0]=o)),clearTimeout(t.wheel);else{if(n.k===i)return;t.mouse=[o,n.invert(o)],Cn(this),t.start()}Es(),t.wheel=setTimeout(function(){t.wheel=null,t.end()},A),t.zoom("mouse",y(r(e(n,i),t.mouse[0],t.mouse[1]),t.extent,w))}}function s(){if(!v&&g.apply(this,arguments)){var n=u(this,arguments),e=lt(t.event.view).on("mousemove.zoom",function(){if(Es(),!n.moved){var e=t.event.clientX-o,i=t.event.clientY-a;n.moved=e*e+i*i>C}n.zoom("mouse",y(r(n.that.__zoom,n.mouse[0]=F(n.that),n.mouse[1]),n.extent,w))},!0).on("mouseup.zoom",function(){e.on("mousemove.zoom mouseup.zoom",null),gt(t.event.view,n.moved),Es(),n.end()},!0),i=F(this),o=t.event.clientX,a=t.event.clientY;vt(t.event.view),Ss(),n.mouse=[i,this.__zoom.invert(i)],Cn(this),n.start()}}function f(){if(g.apply(this,arguments)){var i=this.__zoom,u=F(this),a=i.invert(u),c=i.k*(t.event.shiftKey?.5:2),s=y(r(e(i,c),u,a),_.apply(this,arguments),w);Es(),M>0?lt(this).transition().duration(M).call(o,s,u):lt(this).call(n.transform,s)}}function l(){if(g.apply(this,arguments)){var n,e,r,i,o=u(this,arguments),a=t.event.changedTouches,c=a.length;for(Ss(),e=0;e<c;++e)i=[i=ht(this,a,(r=a[e]).identifier),this.__zoom.invert(i),r.identifier],o.touch0?o.touch1||(o.touch1=i):(o.touch0=i,n=!0);if(d&&(d=clearTimeout(d),!o.touch1))return o.end(),void((i=lt(this).on("dblclick.zoom"))&&i.apply(this,arguments));n&&(d=setTimeout(function(){d=null},E),Cn(this),o.start())}}function h(){var n,i,o,a,c=u(this,arguments),s=t.event.changedTouches,f=s.length;for(Es(),d&&(d=clearTimeout(d)),n=0;n<f;++n)o=ht(this,s,(i=s[n]).identifier),c.touch0&&c.touch0[2]===i.identifier?c.touch0[0]=o:c.touch1&&c.touch1[2]===i.identifier&&(c.touch1[0]=o);if(i=c.that.__zoom,c.touch1){var l=c.touch0[0],h=c.touch0[1],p=c.touch1[0],v=c.touch1[1],g=(g=p[0]-l[0])*g+(g=p[1]-l[1])*g,_=(_=v[0]-h[0])*_+(_=v[1]-h[1])*_;i=e(i,Math.sqrt(g/_)),o=[(l[0]+p[0])/2,(l[1]+p[1])/2],a=[(h[0]+v[0])/2,(h[1]+v[1])/2]}else{if(!c.touch0)return;o=c.touch0[0],a=c.touch0[1]}c.zoom("touch",y(r(i,o,a),c.extent,w))}function p(){var n,e,r=u(this,arguments),i=t.event.changedTouches,o=i.length;for(Ss(),v&&clearTimeout(v),v=setTimeout(function(){v=null},E),n=0;n<o;++n)e=i[n],r.touch0&&r.touch0[2]===e.identifier?delete r.touch0:r.touch1&&r.touch1[2]===e.identifier&&delete r.touch1;r.touch1&&!r.touch0&&(r.touch0=r.touch1,delete r.touch1),r.touch0?r.touch0[1]=this.__zoom.invert(r.touch0[0]):r.end()}var d,v,g=As,_=Cs,y=Ls,m=Ps,x=Rs,b=[0,1/0],w=[[-1/0,-1/0],[1/0,1/0]],M=250,T=pn,k=[],S=N("start","zoom","end"),E=500,A=150,C=0;return n.transform=function(t,n){var e=t.selection?t.selection():t;e.property("__zoom",zs),t!==e?o(t,n):e.interrupt().each(function(){u(this,arguments).start().zoom(null,"function"==typeof n?n.apply(this,arguments):n).end()})},n.scaleBy=function(t,e){n.scaleTo(t,function(){return this.__zoom.k*("function"==typeof e?e.apply(this,arguments):e)})},n.scaleTo=function(t,o){n.transform(t,function(){var t=_.apply(this,arguments),n=this.__zoom,u=i(t),a=n.invert(u),c="function"==typeof o?o.apply(this,arguments):o;return y(r(e(n,c),u,a),t,w)})},n.translateBy=function(t,e,r){n.transform(t,function(){return y(this.__zoom.translate("function"==typeof e?e.apply(this,arguments):e,"function"==typeof r?r.apply(this,arguments):r),_.apply(this,arguments),w)})},n.translateTo=function(t,e,r){n.transform(t,function(){var t=_.apply(this,arguments),n=this.__zoom,o=i(t);return y(F_.translate(o[0],o[1]).scale(n.k).translate("function"==typeof e?-e.apply(this,arguments):-e,"function"==typeof r?-r.apply(this,arguments):-r),t,w)})},a.prototype={start:function(){return 1==++this.active&&(this.index=k.push(this)-1,this.emit("start")),this},zoom:function(t,n){return this.mouse&&"mouse"!==t&&(this.mouse[1]=n.invert(this.mouse[0])),this.touch0&&"touch"!==t&&(this.touch0[1]=n.invert(this.touch0[0])),this.touch1&&"touch"!==t&&(this.touch1[1]=n.invert(this.touch1[0])),this.that.__zoom=n,this.emit("zoom"),this},end:function(){return 0==--this.active&&(k.splice(this.index,1),this.index=-1,this.emit("end")),this},emit:function(t){D(new function(t,n,e){this.target=t,this.type=n,this.transform=e}(n,t,this.that.__zoom),S.apply,S,[t,this.that,this.args])}},n.wheelDelta=function(t){return arguments.length?(m="function"==typeof t?t:Ts(+t),n):m},n.filter=function(t){return arguments.length?(g="function"==typeof t?t:Ts(!!t),n):g},n.touchable=function(t){return arguments.length?(x="function"==typeof t?t:Ts(!!t),n):x},n.extent=function(t){return arguments.length?(_="function"==typeof t?t:Ts([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),n):_},n.scaleExtent=function(t){return arguments.length?(b[0]=+t[0],b[1]=+t[1],n):[b[0],b[1]]},n.translateExtent=function(t){return arguments.length?(w[0][0]=+t[0][0],w[1][0]=+t[1][0],w[0][1]=+t[0][1],w[1][1]=+t[1][1],n):[[w[0][0],w[0][1]],[w[1][0],w[1][1]]]},n.constrain=function(t){return arguments.length?(y=t,n):y},n.duration=function(t){return arguments.length?(M=+t,n):M},n.interpolate=function(t){return arguments.length?(T=t,n):T},n.on=function(){var t=S.on.apply(S,arguments);return t===S?n:t},n.clickDistance=function(t){return arguments.length?(C=(t=+t)*t,n):Math.sqrt(C)},n},t.zoomTransform=ks,t.zoomIdentity=F_,Object.defineProperty(t,"__esModule",{value:!0})}); diff --git a/web/gui/lib/d3pie-0.2.1-netdata-3.js b/web/gui/lib/d3pie-0.2.1-netdata-3.js new file mode 100644 index 0000000..3b00b49 --- /dev/null +++ b/web/gui/lib/d3pie-0.2.1-netdata-3.js @@ -0,0 +1,2124 @@ +/*! + * d3pie + * @author Ben Keen + * @version 0.1.9 + * @date June 17th, 2015 + * @repo http://github.com/benkeen/d3pie + * SPDX-License-Identifier: MIT + */ + +// UMD pattern from https://github.com/umdjs/umd/blob/master/returnExports.js +(function(root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but only CommonJS-like environments that support module.exports, + // like Node + module.exports = factory(); + } else { + // browser globals (root is window) + root.d3pie = factory(root); + } +}(this, function() { + + var _scriptName = "d3pie"; + var _version = "0.2.1"; + + // used to uniquely generate IDs and classes, ensuring no conflict between multiple pies on the same page + var _uniqueIDCounter = 0; + + + // this section includes all helper libs on the d3pie object. They're populated via grunt-template. Note: to keep + // the syntax highlighting from getting all messed up, I commented out each line. That REQUIRES each of the files + // to have an empty first line. Crumby, yes, but acceptable. + //// --------- _default-settings.js -----------/** +/** + * Contains the out-the-box settings for the script. Any of these settings that aren't explicitly overridden for the + * d3pie instance will inherit from these. This is also included on the main website for use in the generation script. + */ +var defaultSettings = { + header: { + title: { + text: "", + color: "#333333", + fontSize: 18, + fontWeight: "bold", + font: "arial" + }, + subtitle: { + text: "", + color: "#666666", + fontSize: 14, + fontWeight: "bold", + font: "arial" + }, + location: "top-center", + titleSubtitlePadding: 8 + }, + footer: { + text: "", + color: "#666666", + fontSize: 14, + fontWeight: "bold", + font: "arial", + location: "left" + }, + size: { + canvasHeight: 500, + canvasWidth: 500, + pieInnerRadius: "0%", + pieOuterRadius: null + }, + data: { + sortOrder: "none", + ignoreSmallSegments: { + enabled: false, + valueType: "percentage", + value: null + }, + smallSegmentGrouping: { + enabled: false, + value: 1, + valueType: "percentage", + label: "Other", + color: "#cccccc" + }, + content: [] + }, + labels: { + outer: { + format: "label", + hideWhenLessThanPercentage: null, + pieDistance: 30 + }, + inner: { + format: "percentage", + hideWhenLessThanPercentage: null + }, + mainLabel: { + color: "#333333", + font: "arial", + fontWeight: "normal", + fontSize: 10 + }, + percentage: { + color: "#dddddd", + font: "arial", + fontWeight: "bold", + fontSize: 10, + decimalPlaces: 0 + }, + value: { + color: "#cccc44", + fontWeight: "bold", + font: "arial", + fontSize: 10 + }, + lines: { + enabled: true, + style: "curved", + color: "segment" + }, + truncation: { + enabled: false, + truncateLength: 30 + }, + formatter: null + }, + effects: { + load: { + effect: "none", // "default", commented in the code + speed: 1000 + }, + pullOutSegmentOnClick: { + effect: "none", // "bounce", commented in the code + speed: 300, + size: 10 + }, + highlightSegmentOnMouseover: false, + highlightLuminosity: -0.2 + }, + tooltips: { + enabled: false, + type: "placeholder", // caption|placeholder + string: "", + placeholderParser: null, + styles: { + fadeInSpeed: 250, + backgroundColor: "#000000", + backgroundOpacity: 0.5, + color: "#efefef", + borderRadius: 2, + font: "arial", + fontWeight: "bold", + fontSize: 10, + padding: 4 + } + }, + misc: { + colors: { + background: null, + segments: [ + "#2484c1", "#65a620", "#7b6888", "#a05d56", "#961a1a", "#d8d23a", "#e98125", "#d0743c", "#635222", "#6ada6a", + "#0c6197", "#7d9058", "#207f33", "#44b9b0", "#bca44a", "#e4a14b", "#a3acb2", "#8cc3e9", "#69a6f9", "#5b388f", + "#546e91", "#8bde95", "#d2ab58", "#273c71", "#98bf6e", "#4daa4b", "#98abc5", "#cc1010", "#31383b", "#006391", + "#c2643f", "#b0a474", "#a5a39c", "#a9c2bc", "#22af8c", "#7fcecf", "#987ac6", "#3d3b87", "#b77b1c", "#c9c2b6", + "#807ece", "#8db27c", "#be66a2", "#9ed3c6", "#00644b", "#005064", "#77979f", "#77e079", "#9c73ab", "#1f79a7" + ], + segmentStroke: "#ffffff" + }, + gradient: { + enabled: false, + percentage: 95, + color: "#000000" + }, + canvasPadding: { + top: 5, + right: 5, + bottom: 5, + left: 5 + }, + pieCenterOffset: { + x: 0, + y: 0 + }, + cssPrefix: null + }, + callbacks: { + onload: null, + onMouseoverSegment: null, + onMouseoutSegment: null, + onClickSegment: null + } +}; + + //// --------- validate.js ----------- +var validate = { + + // called whenever a new pie chart is created + initialCheck: function(pie) { + var cssPrefix = pie.cssPrefix; + var element = pie.element; + var options = pie.options; + + // confirm d3 is available [check minimum version] + if (!window.d3 || !window.d3.hasOwnProperty("version")) { + console.error("d3pie error: d3 is not available"); + return false; + } + + // confirm element is either a DOM element or a valid string for a DOM element + if (!(element instanceof HTMLElement || element instanceof SVGElement)) { + console.error("d3pie error: the first d3pie() param must be a valid DOM element (not jQuery) or a ID string."); + return false; + } + + // confirm the CSS prefix is valid. It has to start with a-Z and contain nothing but a-Z0-9_- + if (!(/[a-zA-Z][a-zA-Z0-9_-]*$/.test(cssPrefix))) { + console.error("d3pie error: invalid options.misc.cssPrefix"); + return false; + } + + // confirm some data has been supplied + if (!helpers.isArray(options.data.content)) { + console.error("d3pie error: invalid config structure: missing data.content property."); + return false; + } + if (options.data.content.length === 0) { + console.error("d3pie error: no data supplied."); + return false; + } + + // clear out any invalid data. Each data row needs a valid positive number and a label + var data = []; + for (var i=0; i<options.data.content.length; i++) { + if (typeof options.data.content[i].value !== "number" || isNaN(options.data.content[i].value)) { + console.log("not valid: ", options.data.content[i]); + continue; + } + if (options.data.content[i].value <= 0) { + console.log("not valid - should have positive value: ", options.data.content[i]); + continue; + } + data.push(options.data.content[i]); + } + pie.options.data.content = data; + + // labels.outer.hideWhenLessThanPercentage - 1-100 + // labels.inner.hideWhenLessThanPercentage - 1-100 + + return true; + } +}; + + //// --------- helpers.js ----------- +var helpers = { + + // creates the SVG element + addSVGSpace: function(pie) { + var element = pie.element; + var canvasWidth = pie.options.size.canvasWidth; + var canvasHeight = pie.options.size.canvasHeight; + var backgroundColor = pie.options.misc.colors.background; + + var svg = d3.select(element).append("svg:svg") + .attr("width", canvasWidth) + .attr("height", canvasHeight); + + if (backgroundColor !== "transparent") { + svg.style("background-color", function() { return backgroundColor; }); + } + + return svg; + }, + + shuffleArray: function(array) { + var currentIndex = array.length, tmpVal, randomIndex; + + while (0 !== currentIndex) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex -= 1; + + // and swap it with the current element + tmpVal = array[currentIndex]; + array[currentIndex] = array[randomIndex]; + array[randomIndex] = tmpVal; + } + return array; + }, + + processObj: function(obj, is, value) { + if (typeof is === 'string') { + return helpers.processObj(obj, is.split('.'), value); + } else if (is.length === 1 && value !== undefined) { + obj[is[0]] = value; + return obj[is[0]]; + } else if (is.length === 0) { + return obj; + } else { + return helpers.processObj(obj[is[0]], is.slice(1), value); + } + }, + + getDimensions: function(el) { + if(typeof el === 'string') + el = document.getElementById(el); + + var w = 0, h = 0; + if (el) { + var dimensions = el.getBBox(); + w = dimensions.width; + h = dimensions.height; + } + else { + console.log("error: getDimensions() " + id + " not found."); + } + + return { w: w, h: h }; + }, + + /** + * This is based on the SVG coordinate system, where top-left is 0,0 and bottom right is n-n. + * @param r1 + * @param r2 + * @returns {boolean} + */ + rectIntersect: function(r1, r2) { + var returnVal = ( + // r2.left > r1.right + (r2.x > (r1.x + r1.w)) || + + // r2.right < r1.left + ((r2.x + r2.w) < r1.x) || + + // r2.top < r1.bottom + ((r2.y + r2.h) < r1.y) || + + // r2.bottom > r1.top + (r2.y > (r1.y + r1.h)) + ); + + return !returnVal; + }, + + /** + * Returns a lighter/darker shade of a hex value, based on a luminance value passed. + * @param hex a hex color value such as “#abc” or “#123456″ (the hash is optional) + * @param lum the luminosity factor: -0.1 is 10% darker, 0.2 is 20% lighter, etc. + * @returns {string} + */ + getColorShade: function(hex, lum) { + + // validate hex string + hex = String(hex).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; + } + lum = lum || 0; + + // convert to decimal and change luminosity + var newHex = "#"; + for (var i=0; i<3; i++) { + var c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + newHex += ("00" + c).substr(c.length); + } + + return newHex; + }, + + /** + * Users can choose to specify segment colors in three ways (in order of precedence): + * 1. include a "color" attribute for each row in data.content + * 2. include a misc.colors.segments property which contains an array of hex codes + * 3. specify nothing at all and rely on this lib provide some reasonable defaults + * + * This function sees what's included and populates this.options.colors with whatever's required + * for this pie chart. + * @param data + */ + initSegmentColors: function(pie) { + var data = pie.options.data.content; + var colors = pie.options.misc.colors.segments; + + // TODO this needs a ton of error handling + + var finalColors = []; + for (var i=0; i<data.length; i++) { + if (data[i].hasOwnProperty("color")) { + finalColors.push(data[i].color); + } else { + finalColors.push(colors[i]); + } + } + + return finalColors; + }, + + applySmallSegmentGrouping: function(data, smallSegmentGrouping) { + var totalSize; + if (smallSegmentGrouping.valueType === "percentage") { + totalSize = math.getTotalPieSize(data); + } + + // loop through each data item + var newData = []; + var groupedData = []; + var totalGroupedData = 0; + for (var i=0; i<data.length; i++) { + if (smallSegmentGrouping.valueType === "percentage") { + var dataPercent = (data[i].value / totalSize) * 100; + if (dataPercent <= smallSegmentGrouping.value) { + groupedData.push(data[i]); + totalGroupedData += data[i].value; + continue; + } + data[i].isGrouped = false; + newData.push(data[i]); + } else { + if (data[i].value <= smallSegmentGrouping.value) { + groupedData.push(data[i]); + totalGroupedData += data[i].value; + continue; + } + data[i].isGrouped = false; + newData.push(data[i]); + } + } + + // we're done! See if there's any small segment groups to add + if (groupedData.length) { + newData.push({ + color: smallSegmentGrouping.color, + label: smallSegmentGrouping.label, + value: totalGroupedData, + isGrouped: true, + groupedData: groupedData + }); + } + + return newData; + }, + + // for debugging + showPoint: function(svg, x, y) { + svg.append("circle").attr("cx", x).attr("cy", y).attr("r", 2).style("fill", "black"); + }, + + isFunction: function(functionToCheck) { + var getType = {}; + return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; + }, + + isArray: function(o) { + return Object.prototype.toString.call(o) === '[object Array]'; + } +}; + + +// taken from jQuery +var extend = function() { + var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false, + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + class2type = { + "[object Boolean]": "boolean", + "[object Number]": "number", + "[object String]": "string", + "[object Function]": "function", + "[object Array]": "array", + "[object Date]": "date", + "[object RegExp]": "regexp", + "[object Object]": "object" + }, + + jQuery = { + isFunction: function (obj) { + return jQuery.type(obj) === "function"; + }, + isArray: Array.isArray || + function (obj) { + return jQuery.type(obj) === "array"; + }, + isWindow: function (obj) { + return obj !== null && obj === obj.window; + }, + isNumeric: function (obj) { + return !isNaN(parseFloat(obj)) && isFinite(obj); + }, + type: function (obj) { + return obj === null ? String(obj) : class2type[toString.call(obj)] || "object"; + }, + isPlainObject: function (obj) { + if (!obj || jQuery.type(obj) !== "object" || obj.nodeType) { + return false; + } + try { + if (obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) { + return false; + } + } catch (e) { + return false; + } + var key; + for (key in obj) {} + return key === undefined || hasOwn.call(obj, key); + } + }; + if (typeof target === "boolean") { + deep = target; + target = arguments[1] || {}; + i = 2; + } + if (typeof target !== "object" && !jQuery.isFunction(target)) { + target = {}; + } + if (length === i) { + target = this; + --i; + } + for (i; i < length; i++) { + if ((options = arguments[i]) !== null) { + for (name in options) { + src = target[name]; + copy = options[name]; + if (target === copy) { + continue; + } + if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) { + if (copyIsArray) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + // WARNING: RECURSION + target[name] = extend(deep, clone, copy); + } else if (copy !== undefined) { + target[name] = copy; + } + } + } + } + return target; +}; + //// --------- math.js ----------- +var math = { + + toRadians: function(degrees) { + return degrees * (Math.PI / 180); + }, + + toDegrees: function(radians) { + return radians * (180 / Math.PI); + }, + + computePieRadius: function(pie) { + var size = pie.options.size; + var canvasPadding = pie.options.misc.canvasPadding; + + // outer radius is either specified (e.g. through the generator), or omitted altogether + // and calculated based on the canvas dimensions. Right now the estimated version isn't great - it should + // be possible to calculate it to precisely generate the maximum sized pie, but it's fussy as heck. Something + // for the next release. + + // first, calculate the default _outerRadius + var w = size.canvasWidth - canvasPadding.left - canvasPadding.right; + var h = size.canvasHeight - canvasPadding.top - canvasPadding.bottom; + + // now factor in the footer, title & subtitle + if (pie.options.header.location !== "pie-center") { + h -= pie.textComponents.headerHeight; + } + + if (pie.textComponents.footer.exists) { + h -= pie.textComponents.footer.h; + } + + // for really teeny pies, h may be < 0. Adjust it back + h = (h < 0) ? 0 : h; + + var outerRadius = ((w < h) ? w : h) / 3; + var innerRadius, percent; + + // if the user specified something, use that instead + if (size.pieOuterRadius !== null) { + if (/%/.test(size.pieOuterRadius)) { + percent = parseInt(size.pieOuterRadius.replace(/[\D]/, ""), 10); + percent = (percent > 99) ? 99 : percent; + percent = (percent < 0) ? 0 : percent; + + var smallestDimension = (w < h) ? w : h; + + // now factor in the label line size + if (pie.options.labels.outer.format !== "none") { + var pieDistanceSpace = parseInt(pie.options.labels.outer.pieDistance, 10) * 2; + if (smallestDimension - pieDistanceSpace > 0) { + smallestDimension -= pieDistanceSpace; + } + } + + outerRadius = Math.floor((smallestDimension / 100) * percent) / 2; + } else { + outerRadius = parseInt(size.pieOuterRadius, 10); + } + } + + // inner radius + if (/%/.test(size.pieInnerRadius)) { + percent = parseInt(size.pieInnerRadius.replace(/[\D]/, ""), 10); + percent = (percent > 99) ? 99 : percent; + percent = (percent < 0) ? 0 : percent; + innerRadius = Math.floor((outerRadius / 100) * percent); + } else { + innerRadius = parseInt(size.pieInnerRadius, 10); + } + + pie.innerRadius = innerRadius; + pie.outerRadius = outerRadius; + }, + + getTotalPieSize: function(data) { + var totalSize = 0; + for (var i=0; i<data.length; i++) { + totalSize += data[i].value; + } + return totalSize; + }, + + sortPieData: function(pie) { + var data = pie.options.data.content; + var sortOrder = pie.options.data.sortOrder; + + switch (sortOrder) { + case "none": + // do nothing + break; + case "random": + data = helpers.shuffleArray(data); + break; + case "value-asc": + data.sort(function(a, b) { return (a.value < b.value) ? -1 : 1; }); + break; + case "value-desc": + data.sort(function(a, b) { return (a.value < b.value) ? 1 : -1; }); + break; + case "label-asc": + data.sort(function(a, b) { return (a.label.toLowerCase() > b.label.toLowerCase()) ? 1 : -1; }); + break; + case "label-desc": + data.sort(function(a, b) { return (a.label.toLowerCase() < b.label.toLowerCase()) ? 1 : -1; }); + break; + } + + return data; + }, + + // var pieCenter = math.getPieCenter(); + getPieTranslateCenter: function(pieCenter) { + return "translate(" + pieCenter.x + "," + pieCenter.y + ")"; + }, + + /** + * Used to determine where on the canvas the center of the pie chart should be. It takes into account the + * height and position of the title, subtitle and footer, and the various paddings. + * @private + */ + calculatePieCenter: function(pie) { + var pieCenterOffset = pie.options.misc.pieCenterOffset; + var hasTopTitle = (pie.textComponents.title.exists && pie.options.header.location !== "pie-center"); + var hasTopSubtitle = (pie.textComponents.subtitle.exists && pie.options.header.location !== "pie-center"); + + var headerOffset = pie.options.misc.canvasPadding.top; + if (hasTopTitle && hasTopSubtitle) { + headerOffset += pie.textComponents.title.h + pie.options.header.titleSubtitlePadding + pie.textComponents.subtitle.h; + } else if (hasTopTitle) { + headerOffset += pie.textComponents.title.h; + } else if (hasTopSubtitle) { + headerOffset += pie.textComponents.subtitle.h; + } + + var footerOffset = 0; + if (pie.textComponents.footer.exists) { + footerOffset = pie.textComponents.footer.h + pie.options.misc.canvasPadding.bottom; + } + + var x = ((pie.options.size.canvasWidth - pie.options.misc.canvasPadding.left - pie.options.misc.canvasPadding.right) / 2) + pie.options.misc.canvasPadding.left; + var y = ((pie.options.size.canvasHeight - footerOffset - headerOffset) / 2) + headerOffset; + + x += pieCenterOffset.x; + y += pieCenterOffset.y; + + pie.pieCenter = { x: x, y: y }; + }, + + + /** + * Rotates a point (x, y) around an axis (xm, ym) by degrees (a). + * @param x + * @param y + * @param xm + * @param ym + * @param a angle in degrees + * @returns {Array} + */ + rotate: function(x, y, xm, ym, a) { + + a = a * Math.PI / 180; // convert to radians + + var cos = Math.cos, + sin = Math.sin, + // subtract midpoints, so that midpoint is translated to origin and add it in the end again + xr = (x - xm) * cos(a) - (y - ym) * sin(a) + xm, + yr = (x - xm) * sin(a) + (y - ym) * cos(a) + ym; + + return { x: xr, y: yr }; + }, + + /** + * Translates a point x, y by distance d, and by angle a. + * @param x + * @param y + * @param dist + * @param a angle in degrees + */ + translate: function(x, y, d, a) { + var rads = math.toRadians(a); + return { + x: x + d * Math.sin(rads), + y: y - d * Math.cos(rads) + }; + }, + + // from: http://stackoverflow.com/questions/19792552/d3-put-arc-labels-in-a-pie-chart-if-there-is-enough-space + pointIsInArc: function(pt, ptData, d3Arc) { + // Center of the arc is assumed to be 0,0 + // (pt.x, pt.y) are assumed to be relative to the center + var r1 = d3Arc.innerRadius()(ptData), // Note: Using the innerRadius + r2 = d3Arc.outerRadius()(ptData), + theta1 = d3Arc.startAngle()(ptData), + theta2 = d3Arc.endAngle()(ptData); + + var dist = pt.x * pt.x + pt.y * pt.y, + angle = Math.atan2(pt.x, -pt.y); // Note: different coordinate system + + angle = (angle < 0) ? (angle + Math.PI * 2) : angle; + + return (r1 * r1 <= dist) && (dist <= r2 * r2) && + (theta1 <= angle) && (angle <= theta2); + } +}; + + //// --------- labels.js ----------- +var labels = { + + /** + * Adds the labels to the pie chart, but doesn't position them. There are two locations for the + * labels: inside (center) of the segments, or outside the segments on the edge. + * @param section "inner" or "outer" + * @param sectionDisplayType "percentage", "value", "label", "label-value1", etc. + * @param pie + */ + add: function(pie, section, sectionDisplayType) { + var include = labels.getIncludes(sectionDisplayType); + var settings = pie.options.labels; + + // group the label groups (label, percentage, value) into a single element for simpler positioning + var outerLabel = pie.svg.insert("g", "." + pie.cssPrefix + "labels-" + section) + .attr("class", pie.cssPrefix + "labels-" + section); + + var labelGroup = pie.__labels[section] = outerLabel.selectAll("." + pie.cssPrefix + "labelGroup-" + section) + .data(pie.options.data.content) + .enter() + .append("g") + .attr("id", function(d, i) { return pie.cssPrefix + "labelGroup" + i + "-" + section; }) + .attr("data-index", function(d, i) { return i; }) + .attr("class", pie.cssPrefix + "labelGroup-" + section) + .style("opacity", 0); + + var formatterContext = { section: section, sectionDisplayType: sectionDisplayType }; + + // 1. Add the main label + if (include.mainLabel) { + labelGroup.append("text") + .attr("id", function(d, i) { return pie.cssPrefix + "segmentMainLabel" + i + "-" + section; }) + .attr("class", pie.cssPrefix + "segmentMainLabel-" + section) + .text(function(d, i) { + var str = d.label; + + // if a custom formatter has been defined, pass it the raw label string - it can do whatever it wants with it. + // we only apply truncation if it's not defined + if (settings.formatter) { + formatterContext.index = i; + formatterContext.part = 'mainLabel'; + formatterContext.value = d.value; + formatterContext.label = str; + str = settings.formatter(formatterContext); + } else if (settings.truncation.enabled && d.label.length > settings.truncation.truncateLength) { + str = d.label.substring(0, settings.truncation.truncateLength) + "..."; + } + return str; + }) + .style("font-size", settings.mainLabel.fontSize + "px") + .style("font-family", settings.mainLabel.font) + .style("font-weight", settings.mainLabel.fontWeight) + .style("fill", function(d, i) { + return (settings.mainLabel.color === "segment") ? pie.options.colors[i] : settings.mainLabel.color; + }); + } + + // 2. Add the percentage label + if (include.percentage) { + labelGroup.append("text") + .attr("id", function(d, i) { return pie.cssPrefix + "segmentPercentage" + i + "-" + section; }) + .attr("class", pie.cssPrefix + "segmentPercentage-" + section) + .text(function(d, i) { + var percentage = d.percentage; + if (settings.formatter) { + formatterContext.index = i; + formatterContext.part = "percentage"; + formatterContext.value = d.value; + formatterContext.label = d.percentage; + percentage = settings.formatter(formatterContext); + } else { + percentage += "%"; + } + return percentage; + }) + .style("font-size", settings.percentage.fontSize + "px") + .style("font-family", settings.percentage.font) + .style("font-weight", settings.percentage.fontWeight) + .style("fill", settings.percentage.color); + } + + // 3. Add the value label + if (include.value) { + labelGroup.append("text") + .attr("id", function(d, i) { return pie.cssPrefix + "segmentValue" + i + "-" + section; }) + .attr("class", pie.cssPrefix + "segmentValue-" + section) + .text(function(d, i) { + formatterContext.index = i; + formatterContext.part = "value"; + formatterContext.value = d.value; + formatterContext.label = d.value; + return settings.formatter ? settings.formatter(formatterContext, d.value) : d.value; + }) + .style("font-size", settings.value.fontSize + "px") + .style("font-family", settings.value.font) + .style("font-weight", settings.value.fontWeight) + .style("fill", settings.value.color); + } + }, + + /** + * @param section "inner" / "outer" + */ + positionLabelElements: function(pie, section, sectionDisplayType) { + labels["dimensions-" + section] = []; + + // get the latest widths, heights + var labelGroups = pie.__labels[section]; + labelGroups.each(function(d, i) { + var mainLabel = d3.select(this).selectAll("." + pie.cssPrefix + "segmentMainLabel-" + section); + var percentage = d3.select(this).selectAll("." + pie.cssPrefix + "segmentPercentage-" + section); + var value = d3.select(this).selectAll("." + pie.cssPrefix + "segmentValue-" + section); + + labels["dimensions-" + section].push({ + mainLabel: (mainLabel.node() !== null) ? mainLabel.node().getBBox() : null, + percentage: (percentage.node() !== null) ? percentage.node().getBBox() : null, + value: (value.node() !== null) ? value.node().getBBox() : null + }); + }); + + var singleLinePad = 5; + var dims = labels["dimensions-" + section]; + switch (sectionDisplayType) { + case "label-value1": + pie.svg.selectAll("." + pie.cssPrefix + "segmentValue-" + section) + .attr("dx", function(d, i) { return dims[i].mainLabel.width + singleLinePad; }); + break; + case "label-value2": + pie.svg.selectAll("." + pie.cssPrefix + "segmentValue-" + section) + .attr("dy", function(d, i) { return dims[i].mainLabel.height; }); + break; + case "label-percentage1": + pie.svg.selectAll("." + pie.cssPrefix + "segmentPercentage-" + section) + .attr("dx", function(d, i) { return dims[i].mainLabel.width + singleLinePad; }); + break; + case "label-percentage2": + pie.svg.selectAll("." + pie.cssPrefix + "segmentPercentage-" + section) + .attr("dx", function(d, i) { return (dims[i].mainLabel.width / 2) - (dims[i].percentage.width / 2); }) + .attr("dy", function(d, i) { return dims[i].mainLabel.height; }); + break; + } + }, + + computeLabelLinePositions: function(pie) { + pie.lineCoordGroups = []; + pie.__labels.outer + .each(function(d, i) { return labels.computeLinePosition(pie, i); }); + }, + + computeLinePosition: function(pie, i) { + var angle = segments.getSegmentAngle(i, pie.options.data.content, pie.totalSize, { midpoint: true }); + var originCoords = math.rotate(pie.pieCenter.x, pie.pieCenter.y - pie.outerRadius, pie.pieCenter.x, pie.pieCenter.y, angle); + var heightOffset = pie.outerLabelGroupData[i].h / 5; // TODO check + var labelXMargin = 6; // the x-distance of the label from the end of the line [TODO configurable] + + var quarter = Math.floor(angle / 90); + var midPoint = 4; + var x2, y2, x3, y3; + + // this resolves an issue when the + if (quarter === 2 && angle === 180) { + quarter = 1; + } + + switch (quarter) { + case 0: + x2 = pie.outerLabelGroupData[i].x - labelXMargin - ((pie.outerLabelGroupData[i].x - labelXMargin - originCoords.x) / 2); + y2 = pie.outerLabelGroupData[i].y + ((originCoords.y - pie.outerLabelGroupData[i].y) / midPoint); + x3 = pie.outerLabelGroupData[i].x - labelXMargin; + y3 = pie.outerLabelGroupData[i].y - heightOffset; + break; + case 1: + x2 = originCoords.x + (pie.outerLabelGroupData[i].x - originCoords.x) / midPoint; + y2 = originCoords.y + (pie.outerLabelGroupData[i].y - originCoords.y) / midPoint; + x3 = pie.outerLabelGroupData[i].x - labelXMargin; + y3 = pie.outerLabelGroupData[i].y - heightOffset; + break; + case 2: + var startOfLabelX = pie.outerLabelGroupData[i].x + pie.outerLabelGroupData[i].w + labelXMargin; + x2 = originCoords.x - (originCoords.x - startOfLabelX) / midPoint; + y2 = originCoords.y + (pie.outerLabelGroupData[i].y - originCoords.y) / midPoint; + x3 = pie.outerLabelGroupData[i].x + pie.outerLabelGroupData[i].w + labelXMargin; + y3 = pie.outerLabelGroupData[i].y - heightOffset; + break; + case 3: + var startOfLabel = pie.outerLabelGroupData[i].x + pie.outerLabelGroupData[i].w + labelXMargin; + x2 = startOfLabel + ((originCoords.x - startOfLabel) / midPoint); + y2 = pie.outerLabelGroupData[i].y + (originCoords.y - pie.outerLabelGroupData[i].y) / midPoint; + x3 = pie.outerLabelGroupData[i].x + pie.outerLabelGroupData[i].w + labelXMargin; + y3 = pie.outerLabelGroupData[i].y - heightOffset; + break; + } + + /* + * x1 / y1: the x/y coords of the start of the line, at the mid point of the segments arc on the pie circumference + * x2 / y2: if "curved" line style is being used, this is the midpoint of the line. Other + * x3 / y3: the end of the line; closest point to the label + */ + if (pie.options.labels.lines.style === "straight") { + pie.lineCoordGroups[i] = [ + { x: originCoords.x, y: originCoords.y }, + { x: x3, y: y3 } + ]; + } else { + pie.lineCoordGroups[i] = [ + { x: originCoords.x, y: originCoords.y }, + { x: x2, y: y2 }, + { x: x3, y: y3 } + ]; + } + }, + + addLabelLines: function(pie) { + var lineGroups = pie.svg.insert("g", "." + pie.cssPrefix + "pieChart") // meaning, BEFORE .pieChart + .attr("class", pie.cssPrefix + "lineGroups") + .style("opacity", 1); + + var lineGroup = lineGroups.selectAll("." + pie.cssPrefix + "lineGroup") + .data(pie.lineCoordGroups) + .enter() + .append("g") + .attr("class", pie.cssPrefix + "lineGroup"); + + var lineFunction = d3.line() + .curve(d3.curveBasis) + .x(function(d) { return d.x; }) + .y(function(d) { return d.y; }); + + lineGroup.append("path") + .attr("d", lineFunction) + .attr("stroke", function(d, i) { + return (pie.options.labels.lines.color === "segment") ? pie.options.colors[i] : pie.options.labels.lines.color; + }) + .attr("stroke-width", 1) + .attr("fill", "none") + .style("opacity", function(d, i) { + var percentage = pie.options.labels.outer.hideWhenLessThanPercentage; + var isHidden = (percentage !== null && d.percentage < percentage) || pie.options.data.content[i].label === ""; + return isHidden ? 0 : 1; + }); + }, + + positionLabelGroups: function(pie, section) { + if (pie.options.labels[section].format === "none") + return; + + pie.__labels[section] + .style("opacity", function(d, i) { + var percentage = pie.options.labels[section].hideWhenLessThanPercentage; + return (percentage !== null && d.percentage < percentage) ? 0 : 1; + }) + .attr("transform", function(d, i) { + var x, y; + if (section === "outer") { + x = pie.outerLabelGroupData[i].x; + y = pie.outerLabelGroupData[i].y; + } else { + var pieCenterCopy = extend(true, {}, pie.pieCenter); + + // now recompute the "center" based on the current _innerRadius + if (pie.innerRadius > 0) { + var angle = segments.getSegmentAngle(i, pie.options.data.content, pie.totalSize, { midpoint: true }); + var newCoords = math.translate(pie.pieCenter.x, pie.pieCenter.y, pie.innerRadius, angle); + pieCenterCopy.x = newCoords.x; + pieCenterCopy.y = newCoords.y; + } + + var dims = helpers.getDimensions(pie.cssPrefix + "labelGroup" + i + "-inner"); + var xOffset = dims.w / 2; + var yOffset = dims.h / 4; // confusing! Why 4? should be 2, but it doesn't look right + + x = pieCenterCopy.x + (pie.lineCoordGroups[i][0].x - pieCenterCopy.x) / 1.8; + y = pieCenterCopy.y + (pie.lineCoordGroups[i][0].y - pieCenterCopy.y) / 1.8; + + x = x - xOffset; + y = y + yOffset; + } + + return "translate(" + x + "," + y + ")"; + }); + }, + + + getIncludes: function(val) { + var addMainLabel = false; + var addValue = false; + var addPercentage = false; + + switch (val) { + case "label": + addMainLabel = true; + break; + case "value": + addValue = true; + break; + case "percentage": + addPercentage = true; + break; + case "label-value1": + case "label-value2": + addMainLabel = true; + addValue = true; + break; + case "label-percentage1": + case "label-percentage2": + addMainLabel = true; + addPercentage = true; + break; + } + return { + mainLabel: addMainLabel, + value: addValue, + percentage: addPercentage + }; + }, + + + /** + * This does the heavy-lifting to compute the actual coordinates for the outer label groups. It does two things: + * 1. Make a first pass and position them in the ideal positions, based on the pie sizes + * 2. Do some basic collision avoidance. + */ + computeOuterLabelCoords: function(pie) { + + // 1. figure out the ideal positions for the outer labels + pie.__labels.outer + .each(function(d, i) { + return labels.getIdealOuterLabelPositions(pie, i); + }); + + // 2. now adjust those positions to try to accommodate conflicts + labels.resolveOuterLabelCollisions(pie); + }, + + /** + * This attempts to resolve label positioning collisions. + */ + resolveOuterLabelCollisions: function(pie) { + if (pie.options.labels.outer.format === "none") { + return; + } + + var size = pie.options.data.content.length; + labels.checkConflict(pie, 0, "clockwise", size); + labels.checkConflict(pie, size-1, "anticlockwise", size); + }, + + checkConflict: function(pie, currIndex, direction, size) { + var i, curr; + + if (size <= 1) { + return; + } + + var currIndexHemisphere = pie.outerLabelGroupData[currIndex].hs; + if (direction === "clockwise" && currIndexHemisphere !== "right") { + return; + } + if (direction === "anticlockwise" && currIndexHemisphere !== "left") { + return; + } + var nextIndex = (direction === "clockwise") ? currIndex+1 : currIndex-1; + + // this is the current label group being looked at. We KNOW it's positioned properly (the first item + // is always correct) + var currLabelGroup = pie.outerLabelGroupData[currIndex]; + + // this one we don't know about. That's the one we're going to look at and move if necessary + var examinedLabelGroup = pie.outerLabelGroupData[nextIndex]; + + var info = { + labelHeights: pie.outerLabelGroupData[0].h, + center: pie.pieCenter, + lineLength: (pie.outerRadius + pie.options.labels.outer.pieDistance), + heightChange: pie.outerLabelGroupData[0].h + 1 // 1 = padding + }; + + // loop through *ALL* label groups examined so far to check for conflicts. This is because when they're + // very tightly fitted, a later label group may still appear high up on the page + if (direction === "clockwise") { + i = 0; + for (; i<=currIndex; i++) { + curr = pie.outerLabelGroupData[i]; + + // if there's a conflict with this label group, shift the label to be AFTER the last known + // one that's been properly placed + if (!labels.isLabelHidden(pie, i) && helpers.rectIntersect(curr, examinedLabelGroup)) { + labels.adjustLabelPos(pie, nextIndex, currLabelGroup, info); + break; + } + } + } else { + i = size - 1; + for (; i >= currIndex; i--) { + curr = pie.outerLabelGroupData[i]; + + // if there's a conflict with this label group, shift the label to be AFTER the last known + // one that's been properly placed + if (!labels.isLabelHidden(pie, i) && helpers.rectIntersect(curr, examinedLabelGroup)) { + labels.adjustLabelPos(pie, nextIndex, currLabelGroup, info); + break; + } + } + } + labels.checkConflict(pie, nextIndex, direction, size); + }, + + isLabelHidden: function(pie, index) { + var percentage = pie.options.labels.outer.hideWhenLessThanPercentage; + return (percentage !== null && d.percentage < percentage) || pie.options.data.content[index].label === ""; + }, + + // does a little math to shift a label into a new position based on the last properly placed one + adjustLabelPos: function(pie, nextIndex, lastCorrectlyPositionedLabel, info) { + var xDiff, yDiff, newXPos, newYPos; + newYPos = lastCorrectlyPositionedLabel.y + info.heightChange; + yDiff = info.center.y - newYPos; + + if (Math.abs(info.lineLength) > Math.abs(yDiff)) { + xDiff = Math.sqrt((info.lineLength * info.lineLength) - (yDiff * yDiff)); + } else { + xDiff = Math.sqrt((yDiff * yDiff) - (info.lineLength * info.lineLength)); + } + + if (lastCorrectlyPositionedLabel.hs === "right") { + newXPos = info.center.x + xDiff; + } else { + newXPos = info.center.x - xDiff - pie.outerLabelGroupData[nextIndex].w; + } + + pie.outerLabelGroupData[nextIndex].x = newXPos; + pie.outerLabelGroupData[nextIndex].y = newYPos; + }, + + /** + * @param i 0-N where N is the dataset size - 1. + */ + getIdealOuterLabelPositions: function(pie, i) { + var labelGroupNode = pie.svg.select("#" + pie.cssPrefix + "labelGroup" + i + "-outer").node(); + if (!labelGroupNode) return; + + var labelGroupDims = labelGroupNode.getBBox(); + var angle = segments.getSegmentAngle(i, pie.options.data.content, pie.totalSize, { midpoint: true }); + + var originalX = pie.pieCenter.x; + var originalY = pie.pieCenter.y - (pie.outerRadius + pie.options.labels.outer.pieDistance); + var newCoords = math.rotate(originalX, originalY, pie.pieCenter.x, pie.pieCenter.y, angle); + + // if the label is on the left half of the pie, adjust the values + var hemisphere = "right"; // hemisphere + if (angle > 180) { + newCoords.x -= (labelGroupDims.width + 8); + hemisphere = "left"; + } else { + newCoords.x += 8; + } + + pie.outerLabelGroupData[i] = { + x: newCoords.x, + y: newCoords.y, + w: labelGroupDims.width, + h: labelGroupDims.height, + hs: hemisphere + }; + } +}; + + //// --------- segments.js ----------- +var segments = { + + effectMap: { + "none": d3.easeLinear, + "bounce": d3.easeBounce, + "linear": d3.easeLinear, + "sin": d3.easeSin, + "elastic": d3.easeElastic, + "back": d3.easeBack, + "quad": d3.easeQuad, + "circle": d3.easeCircle, + "exp": d3.easeExp + }, + + /** + * Creates the pie chart segments and displays them according to the desired load effect. + * @private + */ + create: function(pie) { + var pieCenter = pie.pieCenter; + var colors = pie.options.colors; + var loadEffects = pie.options.effects.load; + var segmentStroke = pie.options.misc.colors.segmentStroke; + + // we insert the pie chart BEFORE the title, to ensure the title overlaps the pie + var pieChartElement = pie.svg.insert("g", "#" + pie.cssPrefix + "title") + .attr("transform", function() { return math.getPieTranslateCenter(pieCenter); }) + .attr("class", pie.cssPrefix + "pieChart"); + + var arc = d3.arc() + .innerRadius(pie.innerRadius) + .outerRadius(pie.outerRadius) + .startAngle(0) + .endAngle(function(d) { + return (d.value / pie.totalSize) * 2 * Math.PI; + }); + + var g = pieChartElement.selectAll("." + pie.cssPrefix + "arc") + .data(pie.options.data.content) + .enter() + .append("g") + .attr("class", pie.cssPrefix + "arc"); + + // if we're not fading in the pie, just set the load speed to 0 + //var loadSpeed = loadEffects.speed; + //if (loadEffects.effect === "none") { + // loadSpeed = 0; + //} + + g.append("path") + .attr("id", function(d, i) { return pie.cssPrefix + "segment" + i; }) + .attr("fill", function(d, i) { + var color = colors[i]; + if (pie.options.misc.gradient.enabled) { + color = "url(#" + pie.cssPrefix + "grad" + i + ")"; + } + return color; + }) + .style("stroke", segmentStroke) + .style("stroke-width", 1) + //.transition() + //.ease(d3.easeCubicInOut) + //.duration(loadSpeed) + .attr("data-index", function(d, i) { return i; }) + .attr("d", arc); +/* + .attrTween("d", function(b) { + var i = d3.interpolate({ value: 0 }, b); + return function(t) { + var ret = pie.arc(i(t)); + console.log(ret); + return ret; + }; + }); +*/ + pie.svg.selectAll("g." + pie.cssPrefix + "arc") + .attr("transform", + function(d, i) { + var angle = 0; + if (i > 0) { + angle = segments.getSegmentAngle(i-1, pie.options.data.content, pie.totalSize); + } + return "rotate(" + angle + ")"; + } + ); + pie.arc = arc; + }, + + addGradients: function(pie) { + var grads = pie.svg.append("defs") + .selectAll("radialGradient") + .data(pie.options.data.content) + .enter().append("radialGradient") + .attr("gradientUnits", "userSpaceOnUse") + .attr("cx", 0) + .attr("cy", 0) + .attr("r", "120%") + .attr("id", function(d, i) { return pie.cssPrefix + "grad" + i; }); + + grads.append("stop").attr("offset", "0%").style("stop-color", function(d, i) { return pie.options.colors[i]; }); + grads.append("stop").attr("offset", pie.options.misc.gradient.percentage + "%").style("stop-color", pie.options.misc.gradient.color); + }, + + addSegmentEventHandlers: function(pie) { + var arc = pie.svg.selectAll("." + pie.cssPrefix + "arc"); + arc = arc.merge(pie.__labels.inner.merge(pie.__labels.outer)); + + arc.on("click", function() { + var currentEl = d3.select(this); + var segment; + + // mouseover works on both the segments AND the segment labels, hence the following + if (currentEl.attr("class") === pie.cssPrefix + "arc") { + segment = currentEl.select("path"); + } else { + var index = currentEl.attr("data-index"); + segment = d3.select("#" + pie.cssPrefix + "segment" + index); + } + + var isExpanded = segment.attr("class") === pie.cssPrefix + "expanded"; + segments.onSegmentEvent(pie, pie.options.callbacks.onClickSegment, segment, isExpanded); + if (pie.options.effects.pullOutSegmentOnClick.effect !== "none") { + if (isExpanded) { + segments.closeSegment(pie, segment.node()); + } else { + segments.openSegment(pie, segment.node()); + } + } + }); + + arc.on("mouseover", function() { + var currentEl = d3.select(this); + var segment, index; + + if (currentEl.attr("class") === pie.cssPrefix + "arc") { + segment = currentEl.select("path"); + } else { + index = currentEl.attr("data-index"); + segment = d3.select("#" + pie.cssPrefix + "segment" + index); + } + + if (pie.options.effects.highlightSegmentOnMouseover) { + index = segment.attr("data-index"); + var segColor = pie.options.colors[index]; + segment.style("fill", helpers.getColorShade(segColor, pie.options.effects.highlightLuminosity)); + } + + if (pie.options.tooltips.enabled) { + index = segment.attr("data-index"); + tt.showTooltip(pie, index); + } + + var isExpanded = segment.attr("class") === pie.cssPrefix + "expanded"; + segments.onSegmentEvent(pie, pie.options.callbacks.onMouseoverSegment, segment, isExpanded); + }); + + arc.on("mousemove", function() { + tt.moveTooltip(pie); + }); + + arc.on("mouseout", function() { + var currentEl = d3.select(this); + var segment, index; + + if (currentEl.attr("class") === pie.cssPrefix + "arc") { + segment = currentEl.select("path"); + } else { + index = currentEl.attr("data-index"); + segment = d3.select("#" + pie.cssPrefix + "segment" + index); + } + + if (pie.options.effects.highlightSegmentOnMouseover) { + index = segment.attr("data-index"); + var color = pie.options.colors[index]; + if (pie.options.misc.gradient.enabled) { + color = "url(#" + pie.cssPrefix + "grad" + index + ")"; + } + segment.style("fill", color); + } + + if (pie.options.tooltips.enabled) { + index = segment.attr("data-index"); + tt.hideTooltip(pie, index); + } + + var isExpanded = segment.attr("class") === pie.cssPrefix + "expanded"; + segments.onSegmentEvent(pie, pie.options.callbacks.onMouseoutSegment, segment, isExpanded); + }); + }, + + // helper function used to call the click, mouseover, mouseout segment callback functions + onSegmentEvent: function(pie, func, segment, isExpanded) { + if (!helpers.isFunction(func)) { + return; + } + var index = parseInt(segment.attr("data-index"), 10); + func({ + segment: segment.node(), + index: index, + expanded: isExpanded, + data: pie.options.data.content[index] + }); + }, + + openSegment: function(pie, segment) { + if (pie.isOpeningSegment) { + return; + } + pie.isOpeningSegment = true; + + segments.maybeCloseOpenSegment(pie); + + d3.select(segment) + .transition() + .ease(segments.effectMap[pie.options.effects.pullOutSegmentOnClick.effect]) + .duration(pie.options.effects.pullOutSegmentOnClick.speed) + .attr("transform", function(d, i) { + var c = pie.arc.centroid(d), + x = c[0], + y = c[1], + h = Math.sqrt(x*x + y*y), + pullOutSize = parseInt(pie.options.effects.pullOutSegmentOnClick.size, 10); + + return "translate(" + ((x/h) * pullOutSize) + ',' + ((y/h) * pullOutSize) + ")"; + }) + .on("end", function(d, i) { + pie.currentlyOpenSegment = segment; + pie.isOpeningSegment = false; + d3.select(segment).attr("class", pie.cssPrefix + "expanded"); + }); + }, + + maybeCloseOpenSegment: function(pie) { + if (typeof pie !== 'undefined' && pie.svg.selectAll("." + pie.cssPrefix + "expanded").size() > 0) { + segments.closeSegment(pie, pie.svg.select("." + pie.cssPrefix + "expanded").node()); + } + }, + + closeSegment: function(pie, segment) { + d3.select(segment) + .transition() + .duration(400) + .attr("transform", "translate(0,0)") + .on("end", function(d, i) { + d3.select(segment).attr("class", ""); + pie.currentlyOpenSegment = null; + }); + }, + + getCentroid: function(el) { + var bbox = el.getBBox(); + return { + x: bbox.x + bbox.width / 2, + y: bbox.y + bbox.height / 2 + }; + }, + + /** + * General helper function to return a segment's angle, in various different ways. + * @param index + * @param opts optional object for fine-tuning exactly what you want. + */ + getSegmentAngle: function(index, data, totalSize, opts) { + var options = extend({ + // if true, this returns the full angle from the origin. Otherwise it returns the single segment angle + compounded: true, + + // optionally returns the midpoint of the angle instead of the full angle + midpoint: false + }, opts); + + var currValue = data[index].value; + var fullValue; + if (options.compounded) { + fullValue = 0; + + // get all values up to and including the specified index + for (var i=0; i<=index; i++) { + fullValue += data[i].value; + } + } + + if (typeof fullValue === 'undefined') { + fullValue = currValue; + } + + // now convert the full value to an angle + var angle = (fullValue / totalSize) * 360; + + // lastly, if we want the midpoint, factor that sucker in + if (options.midpoint) { + var currAngle = (currValue / totalSize) * 360; + angle -= (currAngle / 2); + } + + return angle; + } + +}; + + //// --------- text.js ----------- +var text = { + offscreenCoord: -10000, + + addTitle: function(pie) { + pie.__title = pie.svg.selectAll("." + pie.cssPrefix + "title") + .data([pie.options.header.title]) + .enter() + .append("text") + .text(function(d) { return d.text; }) + .attr("id", pie.cssPrefix + "title") + .attr("class", pie.cssPrefix + "title") + .attr("x", text.offscreenCoord) + .attr("y", text.offscreenCoord) + .attr("text-anchor", function() { + var location; + if (pie.options.header.location === "top-center" || pie.options.header.location === "pie-center") { + location = "middle"; + } else { + location = "left"; + } + return location; + }) + .attr("fill", function(d) { return d.color; }) + .style("font-size", function(d) { return d.fontSize + "px"; }) + .style("font-weight", function(d) { return d.fontWeight; }) + .style("font-family", function(d) { return d.font; }); + }, + + positionTitle: function(pie) { + var textComponents = pie.textComponents; + var headerLocation = pie.options.header.location; + var canvasPadding = pie.options.misc.canvasPadding; + var canvasWidth = pie.options.size.canvasWidth; + var titleSubtitlePadding = pie.options.header.titleSubtitlePadding; + + var x; + if (headerLocation === "top-left") { + x = canvasPadding.left; + } else { + x = ((canvasWidth - canvasPadding.right) / 2) + canvasPadding.left; + } + + // add whatever offset has been added by user + x += pie.options.misc.pieCenterOffset.x; + + var y = canvasPadding.top + textComponents.title.h; + + if (headerLocation === "pie-center") { + y = pie.pieCenter.y; + + // still not fully correct + if (textComponents.subtitle.exists) { + var totalTitleHeight = textComponents.title.h + titleSubtitlePadding + textComponents.subtitle.h; + y = y - (totalTitleHeight / 2) + textComponents.title.h; + } else { + y += (textComponents.title.h / 4); + } + } + + pie.__title + .attr("x", x) + .attr("y", y); + }, + + addSubtitle: function(pie) { + var headerLocation = pie.options.header.location; + + pie.__subtitle = pie.svg.selectAll("." + pie.cssPrefix + "subtitle") + .data([pie.options.header.subtitle]) + .enter() + .append("text") + .text(function(d) { return d.text; }) + .attr("x", text.offscreenCoord) + .attr("y", text.offscreenCoord) + .attr("id", pie.cssPrefix + "subtitle") + .attr("class", pie.cssPrefix + "subtitle") + .attr("text-anchor", function() { + var location; + if (headerLocation === "top-center" || headerLocation === "pie-center") { + location = "middle"; + } else { + location = "left"; + } + return location; + }) + .attr("fill", function(d) { return d.color; }) + .style("font-size", function(d) { return d.fontSize + "px"; }) + .style("font-weight", function(d) { return d.fontWeight; }) + .style("font-family", function(d) { return d.font; }); + }, + + positionSubtitle: function(pie) { + var canvasPadding = pie.options.misc.canvasPadding; + var canvasWidth = pie.options.size.canvasWidth; + + var x; + if (pie.options.header.location === "top-left") { + x = canvasPadding.left; + } else { + x = ((canvasWidth - canvasPadding.right) / 2) + canvasPadding.left; + } + + // add whatever offset has been added by user + x += pie.options.misc.pieCenterOffset.x; + + var y = text.getHeaderHeight(pie); + + pie.__subtitle + .attr("x", x) + .attr("y", y); + }, + + addFooter: function(pie) { + pie.__footer = pie.svg.selectAll("." + pie.cssPrefix + "footer") + .data([pie.options.footer]) + .enter() + .append("text") + .text(function(d) { return d.text; }) + .attr("x", text.offscreenCoord) + .attr("y", text.offscreenCoord) + .attr("id", pie.cssPrefix + "footer") + .attr("class", pie.cssPrefix + "footer") + .attr("text-anchor", function() { + var location = "left"; + if (pie.options.footer.location === "bottom-center") { + location = "middle"; + } else if (pie.options.footer.location === "bottom-right") { + location = "left"; // on purpose. We have to change the x-coord to make it properly right-aligned + } + return location; + }) + .attr("fill", function(d) { return d.color; }) + .style("font-size", function(d) { return d.fontSize + "px"; }) + .style("font-weight", function(d) { return d.fontWeight; }) + .style("font-family", function(d) { return d.font; }); + }, + + positionFooter: function(pie) { + var footerLocation = pie.options.footer.location; + var footerWidth = pie.textComponents.footer.w; + var canvasWidth = pie.options.size.canvasWidth; + var canvasHeight = pie.options.size.canvasHeight; + var canvasPadding = pie.options.misc.canvasPadding; + + var x; + if (footerLocation === "bottom-left") { + x = canvasPadding.left; + } else if (footerLocation === "bottom-right") { + x = canvasWidth - footerWidth - canvasPadding.right; + } else { + x = canvasWidth / 2; // TODO - shouldn't this also take into account padding? + } + + pie.__footer + .attr("x", x) + .attr("y", canvasHeight - canvasPadding.bottom); + }, + + getHeaderHeight: function(pie) { + var h; + if (pie.textComponents.title.exists) { + + // if the subtitle isn't defined, it'll be set to 0 + var totalTitleHeight = pie.textComponents.title.h + pie.options.header.titleSubtitlePadding + pie.textComponents.subtitle.h; + if (pie.options.header.location === "pie-center") { + h = pie.pieCenter.y - (totalTitleHeight / 2) + totalTitleHeight; + } else { + h = totalTitleHeight + pie.options.misc.canvasPadding.top; + } + } else { + if (pie.options.header.location === "pie-center") { + var footerPlusPadding = pie.options.misc.canvasPadding.bottom + pie.textComponents.footer.h; + h = ((pie.options.size.canvasHeight - footerPlusPadding) / 2) + pie.options.misc.canvasPadding.top + (pie.textComponents.subtitle.h / 2); + } else { + h = pie.options.misc.canvasPadding.top + pie.textComponents.subtitle.h; + } + } + return h; + } +}; + + //// --------- validate.js ----------- +var tt = { + addTooltips: function(pie) { + + // group the label groups (label, percentage, value) into a single element for simpler positioning + var tooltips = pie.svg.insert("g") + .attr("class", pie.cssPrefix + "tooltips"); + + tooltips.selectAll("." + pie.cssPrefix + "tooltip") + .data(pie.options.data.content) + .enter() + .append("g") + .attr("class", pie.cssPrefix + "tooltip") + .attr("id", function(d, i) { return pie.cssPrefix + "tooltip" + i; }) + .style("opacity", 0) + .append("rect") + .attr("rx", pie.options.tooltips.styles.borderRadius) + .attr("ry", pie.options.tooltips.styles.borderRadius) + .attr("x", -pie.options.tooltips.styles.padding) + .attr("opacity", pie.options.tooltips.styles.backgroundOpacity) + .style("fill", pie.options.tooltips.styles.backgroundColor); + + tooltips.selectAll("." + pie.cssPrefix + "tooltip") + .data(pie.options.data.content) + .append("text") + .attr("fill", function(d) { return pie.options.tooltips.styles.color; }) + .style("font-size", function(d) { return pie.options.tooltips.styles.fontSize; }) + .style("font-weight", function(d) { return pie.options.tooltips.styles.fontWeight; }) + .style("font-family", function(d) { return pie.options.tooltips.styles.font; }) + .text(function(d, i) { + var caption = pie.options.tooltips.string; + if (pie.options.tooltips.type === "caption") { + caption = d.caption; + } + return tt.replacePlaceholders(pie, caption, i, { + label: d.label, + value: d.value, + percentage: d.percentage + }); + }); + + tooltips.selectAll("." + pie.cssPrefix + "tooltip rect") + .attr("width", function (d, i) { + var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + i); + return dims.w + (2 * pie.options.tooltips.styles.padding); + }) + .attr("height", function (d, i) { + var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + i); + return dims.h + (2 * pie.options.tooltips.styles.padding); + }) + .attr("y", function (d, i) { + var dims = helpers.getDimensions(pie.cssPrefix + "tooltip" + i); + return -(dims.h / 2) + 1; + }); + }, + + showTooltip: function(pie, index) { + var fadeInSpeed = pie.options.tooltips.styles.fadeInSpeed; + if (tt.currentTooltip === index) { + fadeInSpeed = 1; + } + + tt.currentTooltip = index; + d3.select("#" + pie.cssPrefix + "tooltip" + index) + .transition() + .duration(fadeInSpeed) + .style("opacity", function() { return 1; }); + + tt.moveTooltip(pie); + }, + + moveTooltip: function(pie) { + d3.selectAll("#" + pie.cssPrefix + "tooltip" + tt.currentTooltip) + .attr("transform", function(d) { + var mouseCoords = d3.mouse(this.parentNode); + var x = mouseCoords[0] + pie.options.tooltips.styles.padding + 2; + var y = mouseCoords[1] - (2 * pie.options.tooltips.styles.padding) - 2; + return "translate(" + x + "," + y + ")"; + }); + }, + + hideTooltip: function(pie, index) { + d3.select("#" + pie.cssPrefix + "tooltip" + index) + .style("opacity", function() { return 0; }); + + // move the tooltip offscreen. This ensures that when the user next mouseovers the segment the hidden + // element won't interfere + d3.select("#" + pie.cssPrefix + "tooltip" + tt.currentTooltip) + .attr("transform", function(d, i) { + // klutzy, but it accounts for tooltip padding which could push it onscreen + var x = pie.options.size.canvasWidth + 1000; + var y = pie.options.size.canvasHeight + 1000; + return "translate(" + x + "," + y + ")"; + }); + }, + + replacePlaceholders: function(pie, str, index, replacements) { + + // if the user has defined a placeholderParser function, call it before doing the replacements + if (helpers.isFunction(pie.options.tooltips.placeholderParser)) { + pie.options.tooltips.placeholderParser(index, replacements); + } + + var replacer = function() { + return function(match) { + var placeholder = arguments[1]; + if (replacements.hasOwnProperty(placeholder)) { + return replacements[arguments[1]]; + } else { + return arguments[0]; + } + }; + }; + return str.replace(/\{(\w+)\}/g, replacer(replacements)); + } +}; + + + // -------------------------------------------------------------------------------------------- + + // our constructor + var d3pie = function(element, options) { + + // element can be an ID or DOM element + this.element = element; + if (typeof element === "string") { + var el = element.replace(/^#/, ""); // replace any jQuery-like ID hash char + this.element = document.getElementById(el); + } + + var opts = {}; + extend(true, opts, defaultSettings, options); + this.options = opts; + + // if the user specified a custom CSS element prefix (ID, class), use it + if (this.options.misc.cssPrefix !== null) { + this.cssPrefix = this.options.misc.cssPrefix; + } else { + this.cssPrefix = "p" + _uniqueIDCounter + "_"; + _uniqueIDCounter++; + } + + + // now run some validation on the user-defined info + if (!validate.initialCheck(this)) { + return; + } + + // add a data-role to the DOM node to let anyone know that it contains a d3pie instance, and the d3pie version + d3.select(this.element).attr(_scriptName, _version); + + // things that are done once + _setupData.call(this); + _init.call(this); + }; + + d3pie.prototype.recreate = function() { + // now run some validation on the user-defined info + if (!validate.initialCheck(this)) { + return; + } + + _setupData.call(this); + _init.call(this); + }; + + d3pie.prototype.redraw = function() { + this.element.innerHTML = ""; + _init.call(this); + }; + + d3pie.prototype.destroy = function() { + this.element.innerHTML = ""; // clear out the SVG + d3.select(this.element).attr(_scriptName, null); // remove the data attr + }; + + /** + * Returns all pertinent info about the current open info. Returns null if nothing's open, or if one is, an object of + * the following form: + * { + * element: DOM NODE, + * index: N, + * data: {} + * } + */ + d3pie.prototype.getOpenSegment = function() { + var segment = this.currentlyOpenSegment; + if (segment !== null && typeof segment !== "undefined") { + var index = parseInt(d3.select(segment).attr("data-index"), 10); + return { + element: segment, + index: index, + data: this.options.data.content[index] + }; + } else { + return null; + } + }; + + d3pie.prototype.openSegment = function(index) { + index = parseInt(index, 10); + if (index < 0 || index > this.options.data.content.length-1) { + return; + } + segments.openSegment(this, d3.select("#" + this.cssPrefix + "segment" + index).node()); + }; + + d3pie.prototype.closeSegment = function() { + segments.maybeCloseOpenSegment(this); + }; + + // this let's the user dynamically update aspects of the pie chart without causing a complete redraw. It + // intelligently re-renders only the part of the pie that the user specifies. Some things cause a repaint, others + // just redraw the single element + d3pie.prototype.updateProp = function(propKey, value) { + switch (propKey) { + case "header.title.text": + var oldVal = helpers.processObj(this.options, propKey); + helpers.processObj(this.options, propKey, value); + d3.select("#" + this.cssPrefix + "title").html(value); + if ((oldVal === "" && value !== "") || (oldVal !== "" && value === "")) { + this.redraw(); + } + break; + + case "header.subtitle.text": + var oldValue = helpers.processObj(this.options, propKey); + helpers.processObj(this.options, propKey, value); + d3.select("#" + this.cssPrefix + "subtitle").html(value); + if ((oldValue === "" && value !== "") || (oldValue !== "" && value === "")) { + this.redraw(); + } + break; + + case "callbacks.onload": + case "callbacks.onMouseoverSegment": + case "callbacks.onMouseoutSegment": + case "callbacks.onClickSegment": + case "effects.pullOutSegmentOnClick.effect": + case "effects.pullOutSegmentOnClick.speed": + case "effects.pullOutSegmentOnClick.size": + case "effects.highlightSegmentOnMouseover": + case "effects.highlightLuminosity": + helpers.processObj(this.options, propKey, value); + break; + + // everything else, attempt to update it & do a repaint + default: + helpers.processObj(this.options, propKey, value); + + this.destroy(); + this.recreate(); + break; + } + }; + + + // ------------------------------------------------------------------------------------------------ + + var _setupData = function () { + this.options.data.content = math.sortPieData(this); + if (this.options.data.smallSegmentGrouping.enabled) { + this.options.data.content = helpers.applySmallSegmentGrouping(this.options.data.content, this.options.data.smallSegmentGrouping); + } + + + this.options.colors = helpers.initSegmentColors(this); + this.totalSize = math.getTotalPieSize(this.options.data.content); + + var dp = this.options.labels.percentage.decimalPlaces; + + // add in percentage data to content + for (var i=0; i<this.options.data.content.length; i++) { + this.options.data.content[i].percentage = _getPercentage(this.options.data.content[i].value, this.totalSize, dp); + } + + // adjust the final item to ensure the percentage always adds up to precisely 100%. This is necessary + var totalPercentage = 0; + for (var j=0; j<this.options.data.content.length; j++) { + if (j === this.options.data.content.length - 1) { + this.options.data.content[j].percentage = (100 - totalPercentage).toFixed(dp); + } + totalPercentage += parseFloat(this.options.data.content[j].percentage); + } + }; + + var _init = function() { + + // prep-work + this.svg = helpers.addSVGSpace(this); + + // store info about the main text components as part of the d3pie object instance + this.textComponents = { + headerHeight: 0, + title: { + exists: this.options.header.title.text !== "", + h: 0, + w: 0 + }, + subtitle: { + exists: this.options.header.subtitle.text !== "", + h: 0, + w: 0 + }, + footer: { + exists: this.options.footer.text !== "", + h: 0, + w: 0 + } + }; + + this.outerLabelGroupData = []; + + // add the key text components offscreen (title, subtitle, footer). We need to know their widths/heights for later computation + if (this.textComponents.title.exists) text.addTitle(this); + if (this.textComponents.subtitle.exists) text.addSubtitle(this); + text.addFooter(this); + + // console.log(this); + + // the footer never moves. Put it in place now + var self = this; + text.positionFooter(self); + var d3 = helpers.getDimensions(self.__footer.node()); + self.textComponents.footer.h = d3.h; + self.textComponents.footer.w = d3.w; + + if (self.textComponents.title.exists) { + var d1 = helpers.getDimensions(self.__title.node()); + self.textComponents.title.h = d1.h; + self.textComponents.title.w = d1.w; + } + + if (self.textComponents.subtitle.exists) { + var d2 = helpers.getDimensions(self.__subtitle.node()); + self.textComponents.subtitle.h = d2.h; + self.textComponents.subtitle.w = d2.w; + } + + // now compute the full header height + if (self.textComponents.title.exists || self.textComponents.subtitle.exists) { + var headerHeight = 0; + if (self.textComponents.title.exists) { + headerHeight += self.textComponents.title.h; + if (self.textComponents.subtitle.exists) { + headerHeight += self.options.header.titleSubtitlePadding; + } + } + if (self.textComponents.subtitle.exists) { + headerHeight += self.textComponents.subtitle.h; + } + self.textComponents.headerHeight = headerHeight; + } + + // at this point, all main text component dimensions have been calculated + math.computePieRadius(self); + + // this value is used all over the place for placing things and calculating locations. We figure it out ONCE + // and store it as part of the object + math.calculatePieCenter(self); + + // position the title and subtitle + text.positionTitle(self); + text.positionSubtitle(self); + + // now create the pie chart segments, and gradients if the user desired + if (self.options.misc.gradient.enabled) { + segments.addGradients(self); + } + segments.create(self); // also creates this.arc + + self.__labels = {}; + labels.add(self, "inner", self.options.labels.inner.format); + labels.add(self, "outer", self.options.labels.outer.format); + + // position the label elements relatively within their individual group (label, percentage, value) + labels.positionLabelElements(self, "inner", self.options.labels.inner.format); + labels.positionLabelElements(self, "outer", self.options.labels.outer.format); + labels.computeOuterLabelCoords(self); + + // this is (and should be) dumb. It just places the outer groups at their calculated, collision-free positions + labels.positionLabelGroups(self, "outer"); + + // we use the label line positions for many other calculations, so ALWAYS compute them + labels.computeLabelLinePositions(self); + + // only add them if they're actually enabled + if (self.options.labels.lines.enabled && self.options.labels.outer.format !== "none") { + labels.addLabelLines(self); + } + + labels.positionLabelGroups(self, "inner"); + + if (helpers.isFunction(self.options.callbacks.onload)) { + try { + self.options.callbacks.onload(); + } catch (e) { } + } + + // add and position the tooltips + if (self.options.tooltips.enabled) { + tt.addTooltips(self); + } + + segments.addSegmentEventHandlers(self); + }; + + var _getPercentage = function(value, total, decimalPlaces) { + var relativeAmount = value / total; + if (decimalPlaces <= 0) { + return Math.round(relativeAmount * 100); + } else { + return (relativeAmount * 100).toFixed(decimalPlaces); + } + }; + + return d3pie; +})); diff --git a/web/gui/lib/dygraph-c91c859.min.js b/web/gui/lib/dygraph-c91c859.min.js new file mode 100644 index 0000000..1713fee --- /dev/null +++ b/web/gui/lib/dygraph-c91c859.min.js @@ -0,0 +1,7 @@ +/*! @license Copyright 2017 Dan Vanderkam (danvdk@gmail.com) MIT-licensed (http://opensource.org/licenses/MIT) */ +// SPDX-License-Identifier: MIT +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Dygraph=t()}}(function(){return function t(e,a,i){function n(o,s){if(!a[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var h=new Error("Cannot find module '"+o+"'");throw h.code="MODULE_NOT_FOUND",h}var u=a[o]={exports:{}};e[o][0].call(u.exports,function(t){var a=e[o][1][t];return n(a||t)},u,u.exports,t,e,a,i)}return a[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)n(i[o]);return n}({1:[function(t,e,a){function i(){throw new Error("setTimeout has not been defined")}function n(){throw new Error("clearTimeout has not been defined")}function r(t){if(d===setTimeout)return setTimeout(t,0);if((d===i||!d)&&setTimeout)return d=setTimeout,setTimeout(t,0);try{return d(t,0)}catch(e){try{return d.call(null,t,0)}catch(e){return d.call(this,t,0)}}}function o(t){if(c===clearTimeout)return clearTimeout(t);if((c===n||!c)&&clearTimeout)return c=clearTimeout,clearTimeout(t);try{return c(t)}catch(e){try{return c.call(null,t)}catch(e){return c.call(this,t)}}}function s(){v&&g&&(v=!1,g.length?f=g.concat(f):_=-1,f.length&&l())}function l(){if(!v){var t=r(s);v=!0;for(var e=f.length;e;){for(g=f,f=[];++_<e;)g&&g[_].run();_=-1,e=f.length}g=null,v=!1,o(t)}}function h(t,e){this.fun=t,this.array=e}function u(){}var d,c,p=e.exports={};!function(){try{d="function"==typeof setTimeout?setTimeout:i}catch(t){d=i}try{c="function"==typeof clearTimeout?clearTimeout:n}catch(t){c=n}}();var g,f=[],v=!1,_=-1;p.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var a=1;a<arguments.length;a++)e[a-1]=arguments[a];f.push(new h(t,e)),1!==f.length||v||r(l)},h.prototype.run=function(){this.fun.apply(null,this.array)},p.title="browser",p.browser=!0,p.env={},p.argv=[],p.version="",p.versions={},p.on=u,p.addListener=u,p.once=u,p.off=u,p.removeListener=u,p.removeAllListeners=u,p.emit=u,p.prependListener=u,p.prependOnceListener=u,p.listeners=function(t){return[]},p.binding=function(t){throw new Error("process.binding is not supported")},p.cwd=function(){return"/"},p.chdir=function(t){throw new Error("process.chdir is not supported")},p.umask=function(){return 0}},{}],2:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o=[],s=a.get("logscale"),l=0;l<t.length;l++)i=t[l][0],r=t[l][e],s&&null!==r&&(r[0]<=0||r[1]<=0||r[2]<=0)&&(r=null),null!==r?(n=r[1],null===n||isNaN(n)?o.push([i,n,[n,n]]):o.push([i,n,[r[0],r[2]]])):o.push([i,null,[null,null]]);return o},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u=[];for(n=0,o=0,r=0,s=0,l=0;l<t.length;l++){if(i=t[l][1],h=t[l][2],u[l]=t[l],null===i||isNaN(i)||(n+=h[0],o+=i,r+=h[1],s+=1),l-e>=0){var d=t[l-e];null===d[1]||isNaN(d[1])||(n-=d[2][0],o-=d[1],r-=d[2][1],s-=1)}u[l]=s?[t[l][0],1*o/s,[1*n/s,1*r/s]]:[t[l][0],null,[null,null]]}return u},a.default=r,e.exports=a.default},{"./bars":5}],3:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("logscale"),u=0;u<t.length;u++)i=t[u][0],o=t[u][e],h&&null!==o&&(o[0]<=0||o[0]-l*o[1]<=0)&&(o=null),null!==o?(n=o[0],null===n||isNaN(n)?s.push([i,n,[n,n,n]]):(r=l*o[1],s.push([i,n,[n-r,n+r,o[1]]]))):s.push([i,null,[null,null,null]]);return s},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l,h,u,d,c=[],p=a.get("sigma");for(i=0;i<t.length;i++){for(s=0,u=0,l=0,n=Math.max(0,i-e+1);n<i+1;n++)null===(r=t[n][1])||isNaN(r)||(l++,s+=r,u+=Math.pow(t[n][2][2],2));l?(h=Math.sqrt(u)/l,d=s/l,c[i]=[t[i][0],d,[d-p*h,d+p*h]]):(o=1==e?t[i][1]:null,c[i]=[t[i][0],o,[o,o]])}return c},a.default=r,e.exports=a.default},{"./bars":5}],4:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./bars"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h,u,d=[],c=a.get("sigma"),p=a.get("logscale"),g=0;g<t.length;g++)i=t[g][0],r=t[g][e],p&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?d.push([i,o,[o,o,o,s]]):(l=s?o/s:0,h=s?c*Math.sqrt(l*(1-l)/s):1,u=100*h,n=100*l,d.push([i,n,[n-u,n+u,o,s]]))):d.push([i,null,[null,null,null,null]]);return d},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s=[],l=a.get("sigma"),h=a.get("wilsonInterval"),u=0,d=0;for(r=0;r<t.length;r++){u+=t[r][2][2],d+=t[r][2][3],r-e>=0&&(u-=t[r-e][2][2],d-=t[r-e][2][3]);var c=t[r][0],p=d?u/d:0;if(h)if(d){var g=p<0?0:p,f=d,v=l*Math.sqrt(g*(1-g)/f+l*l/(4*f*f)),_=1+l*l/d;i=(g+l*l/(2*d)-v)/_,n=(g+l*l/(2*d)+v)/_,s[r]=[c,100*g,[100*i,100*n]]}else s[r]=[c,0,[0,0]];else o=d?l*Math.sqrt(p*(1-p)/d):1,s[r]=[c,100*p,[100*(p-o),100*(p+o)]]}return s},a.default=r,e.exports=a.default},{"./bars":5}],5:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=i(n),o=t("../dygraph-layout"),s=i(o),l=function(){r.default.call(this)};l.prototype=new r.default,l.prototype.extractSeries=function(t,e,a){},l.prototype.rollingAverage=function(t,e,a){},l.prototype.onPointsCreated_=function(t,e){for(var a=0;a<t.length;++a){var i=t[a],n=e[a];n.y_top=NaN,n.y_bottom=NaN,n.yval_minus=r.default.parseFloat(i[2][0]),n.yval_plus=r.default.parseFloat(i[2][1])}},l.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=t.length-1,s=0;s<=o;s++)if(null!==(i=t[s][1])&&!isNaN(i)){var l=t[s][2][0],h=t[s][2][1];l>i&&(l=i),h<i&&(h=i),(null===r||h>r)&&(r=h),(null===n||l<n)&&(n=l)}return[n,r]},l.prototype.onLineEvaluated=function(t,e,a){for(var i,n=0;n<t.length;n++)i=t[n],i.y_top=s.default.calcYNormal_(e,i.yval_minus,a),i.y_bottom=s.default.calcYNormal_(e,i.yval_plus,a)},a.default=l,e.exports=a.default},{"../dygraph-layout":13,"./datahandler":6}],6:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){},n=i;n.X=0,n.Y=1,n.EXTRAS=2,n.prototype.extractSeries=function(t,e,a){},n.prototype.seriesToPoints=function(t,e,a){for(var i=[],r=0;r<t.length;++r){var o=t[r],s=o[1],l=null===s?null:n.parseFloat(s),h={x:NaN,y:NaN,xval:n.parseFloat(o[0]),yval:l,name:e,idx:r+a,canvasx:NaN,canvasy:NaN};i.push(h)}return this.onPointsCreated_(t,i),i},n.prototype.onPointsCreated_=function(t,e){},n.prototype.rollingAverage=function(t,e,a){},n.prototype.getExtremeYValues=function(t,e,a){},n.prototype.onLineEvaluated=function(t,e,a){},n.parseFloat=function(t){return null===t?NaN:t},a.default=i,e.exports=a.default},{}],7:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./datahandler"),r=(i(n),t("./default")),o=i(r),s=function(){};s.prototype=new o.default,s.prototype.extractSeries=function(t,e,a){for(var i,n,r,o,s,l,h=[],u=a.get("logscale"),d=0;d<t.length;d++)i=t[d][0],r=t[d][e],u&&null!==r&&(r[0]<=0||r[1]<=0)&&(r=null),null!==r?(o=r[0],s=r[1],null===o||isNaN(o)?h.push([i,o,[o,s]]):(l=s?o/s:0,n=100*l,h.push([i,n,[o,s]]))):h.push([i,null,[null,null]]);return h},s.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n=[],r=0,o=0;for(i=0;i<t.length;i++){r+=t[i][2][0],o+=t[i][2][1],i-e>=0&&(r-=t[i-e][2][0],o-=t[i-e][2][1]);var s=t[i][0],l=o?r/o:0;n[i]=[s,100*l]}return n},a.default=s,e.exports=a.default},{"./datahandler":6,"./default":8}],8:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./datahandler"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(){};r.prototype=new n.default,r.prototype.extractSeries=function(t,e,a){for(var i=[],n=a.get("logscale"),r=0;r<t.length;r++){var o=t[r][0],s=t[r][e];n&&s<=0&&(s=null),i.push([o,s])}return i},r.prototype.rollingAverage=function(t,e,a){e=Math.min(e,t.length);var i,n,r,o,s,l=[];if(1==e)return t;for(i=0;i<t.length;i++){for(o=0,s=0,n=Math.max(0,i-e+1);n<i+1;n++)null===(r=t[n][1])||isNaN(r)||(s++,o+=t[n][1]);l[i]=s?[t[i][0],o/s]:[t[i][0],null]}return l},r.prototype.getExtremeYValues=function(t,e,a){for(var i,n=null,r=null,o=t.length-1,s=0;s<=o;s++)null===(i=t[s][1])||isNaN(i)||((null===r||i>r)&&(r=i),(null===n||i<n)&&(n=i));return[n,r]},a.default=r,e.exports=a.default},{"./datahandler":6}],9:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=t("./dygraph"),o=function(t){return t&&t.__esModule?t:{default:t}}(r),s=function(t,e,a,i){if(this.dygraph_=t,this.layout=i,this.element=e,this.elementContext=a,this.height=t.height_,this.width=t.width_,!n.isCanvasSupported(this.element))throw"Canvas is not supported.";this.area=i.getPlotArea();var r=this.dygraph_.canvas_ctx_;r.beginPath(),r.rect(this.area.x,this.area.y,this.area.w,this.area.h),r.clip(),r=this.dygraph_.hidden_ctx_,r.beginPath(),r.rect(this.area.x,this.area.y,this.area.w,this.area.h),r.clip()};s.prototype.clear=function(){this.elementContext.clearRect(0,0,this.width,this.height)},s.prototype.render=function(){this._updatePoints(),this._renderLineChart()},s._getIteratorPredicate=function(t){return t?s._predicateThatSkipsEmptyPoints:null},s._predicateThatSkipsEmptyPoints=function(t,e){return null!==t[e].yval},s._drawStyledLine=function(t,e,a,i,r,o,l){var h=t.dygraph,u=h.getBooleanOption("stepPlot",t.setName);n.isArrayLike(i)||(i=null);var d=h.getBooleanOption("drawGapEdgePoints",t.setName),c=t.points,p=t.setName,g=n.createIterator(c,0,c.length,s._getIteratorPredicate(h.getBooleanOption("connectSeparatedPoints",p))),f=i&&i.length>=2,v=t.drawingContext;v.save(),f&&v.setLineDash&&v.setLineDash(i);var _=s._drawSeries(t,g,a,l,r,d,u,e);s._drawPointsOnLine(t,_,o,e,l),f&&v.setLineDash&&v.setLineDash([]),v.restore()},s._drawSeries=function(t,e,a,i,n,r,o,s){var l,h,u=null,d=null,c=null,p=[],g=!0,f=t.drawingContext;f.beginPath(),f.strokeStyle=s,f.lineWidth=a;for(var v=e.array_,_=e.end_,y=e.predicate_,x=e.start_;x<_;x++){if(h=v[x],y){for(;x<_&&!y(v,x);)x++;if(x==_)break;h=v[x]}if(null===h.canvasy||h.canvasy!=h.canvasy)o&&null!==u&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),u=d=null;else{if(l=!1,r||null===u){e.nextIdx_=x,e.next(),c=e.hasNext?e.peek.canvasy:null;var m=null===c||c!=c;l=null===u&&m,r&&(!g&&null===u||e.hasNext&&m)&&(l=!0)}null!==u?a&&(o&&(f.moveTo(u,d),f.lineTo(h.canvasx,d)),f.lineTo(h.canvasx,h.canvasy)):f.moveTo(h.canvasx,h.canvasy),(n||l)&&p.push([h.canvasx,h.canvasy,h.idx]),u=h.canvasx,d=h.canvasy}g=!1}return f.stroke(),p},s._drawPointsOnLine=function(t,e,a,i,n){for(var r=t.drawingContext,o=0;o<e.length;o++){var s=e[o];r.save(),a.call(t.dygraph,t.dygraph,t.setName,r,s[0],s[1],i,n,s[2]),r.restore()}},s.prototype._updatePoints=function(){for(var t=this.layout.points,e=t.length;e--;)for(var a=t[e],i=a.length;i--;){var n=a[i];n.canvasx=this.area.w*n.x+this.area.x,n.canvasy=this.area.h*n.y+this.area.y}},s.prototype._renderLineChart=function(t,e){var a,i,r=e||this.elementContext,o=this.layout.points,s=this.layout.setNames;this.colors=this.dygraph_.colorsMap_;var l=this.dygraph_.getOption("plotter"),h=l;n.isArrayLike(h)||(h=[h]);var u={};for(a=0;a<s.length;a++){i=s[a];var d=this.dygraph_.getOption("plotter",i);d!=l&&(u[i]=d)}for(a=0;a<h.length;a++)for(var c=h[a],p=a==h.length-1,g=0;g<o.length;g++)if(i=s[g],!t||i==t){var f=o[g],v=c;if(i in u){if(!p)continue;v=u[i]}var _=this.colors[i],y=this.dygraph_.getOption("strokeWidth",i);r.save(),r.strokeStyle=_,r.lineWidth=y,v({points:f,setName:i,drawingContext:r,color:_,strokeWidth:y,dygraph:this.dygraph_,axis:this.dygraph_.axisPropertiesForSeries(i),plotArea:this.area,seriesIndex:g,seriesCount:o.length,singleSeriesName:t,allSeriesPoints:o}),r.restore()}},s._Plotters={linePlotter:function(t){s._linePlotter(t)},fillPlotter:function(t){s._fillPlotter(t)},errorPlotter:function(t){s._errorPlotter(t)}},s._linePlotter=function(t){var e=t.dygraph,a=t.setName,i=t.strokeWidth,r=e.getNumericOption("strokeBorderWidth",a),o=e.getOption("drawPointCallback",a)||n.Circles.DEFAULT,l=e.getOption("strokePattern",a),h=e.getBooleanOption("drawPoints",a),u=e.getNumericOption("pointSize",a);r&&i&&s._drawStyledLine(t,e.getOption("strokeBorderColor",a),i+2*r,l,h,o,u),s._drawStyledLine(t,t.color,i,l,h,o,u)},s._errorPlotter=function(t){var e=t.dygraph,a=t.setName;if(e.getBooleanOption("errorBars")||e.getBooleanOption("customBars")){e.getBooleanOption("fillGraph",a)&&console.warn("Can't use fillGraph option with error bars");var i,r=t.drawingContext,o=t.color,l=e.getNumericOption("fillAlpha",a),h=e.getBooleanOption("stepPlot",a),u=t.points,d=n.createIterator(u,0,u.length,s._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",a))),c=NaN,p=NaN,g=[-1,-1],f=n.toRGB_(o),v="rgba("+f.r+","+f.g+","+f.b+","+l+")";r.fillStyle=v,r.beginPath();for(var _=function(t){return null===t||void 0===t||isNaN(t)};d.hasNext;){var y=d.next();!h&&_(y.y)||h&&!isNaN(p)&&_(p)?c=NaN:(i=[y.y_bottom,y.y_top],h&&(p=y.y),isNaN(i[0])&&(i[0]=y.y),isNaN(i[1])&&(i[1]=y.y),i[0]=t.plotArea.h*i[0]+t.plotArea.y,i[1]=t.plotArea.h*i[1]+t.plotArea.y,isNaN(c)||(h?(r.moveTo(c,g[0]),r.lineTo(y.canvasx,g[0]),r.lineTo(y.canvasx,g[1])):(r.moveTo(c,g[0]),r.lineTo(y.canvasx,i[0]),r.lineTo(y.canvasx,i[1])),r.lineTo(c,g[1]),r.closePath()),g=i,c=y.canvasx)}r.fill()}},s._fastCanvasProxy=function(t){var e=[],a=null,i=null,n=0,r=function(t){if(!(e.length<=1)){for(var a=e.length-1;a>0;a--){var i=e[a];if(2==i[0]){var n=e[a-1];n[1]==i[1]&&n[2]==i[2]&&e.splice(a,1)}}for(var a=0;a<e.length-1;){var i=e[a];2==i[0]&&2==e[a+1][0]?e.splice(a,1):a++}if(e.length>2&&!t){var r=0;2==e[0][0]&&r++;for(var o=null,s=null,a=r;a<e.length;a++){var i=e[a];if(1==i[0])if(null===o&&null===s)o=a,s=a;else{var l=i[2];l<e[o][2]?o=a:l>e[s][2]&&(s=a)}}var h=e[o],u=e[s];e.splice(r,e.length-r),o<s?(e.push(h),e.push(u)):o>s?(e.push(u),e.push(h)):e.push(h)}}},o=function(a){r(a);for(var o=0,s=e.length;o<s;o++){var l=e[o];1==l[0]?t.lineTo(l[1],l[2]):2==l[0]&&t.moveTo(l[1],l[2])}e.length&&(i=e[e.length-1][1]),n+=e.length,e=[]},s=function(t,n,r){var s=Math.round(n);if(null===a||s!=a){var l=a-i>1,h=s-a>1;o(l||h),a=s}e.push([t,n,r])};return{moveTo:function(t,e){s(2,t,e)},lineTo:function(t,e){s(1,t,e)},stroke:function(){o(!0),t.stroke()},fill:function(){o(!0),t.fill()},beginPath:function(){o(!0),t.beginPath()},closePath:function(){o(!0),t.closePath()},_count:function(){return n}}},s._fillPlotter=function(t){if(!t.singleSeriesName&&0===t.seriesIndex){for(var e=t.dygraph,a=e.getLabels().slice(1),i=a.length;i>=0;i--)e.visibility()[i]||a.splice(i,1);if(function(){for(var t=0;t<a.length;t++)if(e.getBooleanOption("fillGraph",a[t]))return!0;return!1}())for(var r,l,h=t.plotArea,u=t.allSeriesPoints,d=u.length,c=e.getBooleanOption("stackedGraph"),p=e.getColors(),g={},f=function(t,e,a,i){if(t.lineTo(e,a),c)for(var n=i.length-1;n>=0;n--){var r=i[n];t.lineTo(r[0],r[1])}},v=d-1;v>=0;v--){var _=t.drawingContext,y=a[v];if(e.getBooleanOption("fillGraph",y)){var x=e.getNumericOption("fillAlpha",y),m=e.getBooleanOption("stepPlot",y),b=p[v],w=e.axisPropertiesForSeries(y),A=1+w.minyval*w.yscale;A<0?A=0:A>1&&(A=1),A=h.h*A+h.y;var O,D=u[v],E=n.createIterator(D,0,D.length,s._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints",y))),L=NaN,T=[-1,-1],S=n.toRGB_(b),P="rgba("+S.r+","+S.g+","+S.b+","+x+")";_.fillStyle=P,_.beginPath();var C,M=!0;(D.length>2*e.width_||o.default.FORCE_FAST_PROXY)&&(_=s._fastCanvasProxy(_));for(var N,F=[];E.hasNext;)if(N=E.next(),n.isOK(N.y)||m){if(c){if(!M&&C==N.xval)continue;M=!1,C=N.xval,r=g[N.canvasx];var k;k=void 0===r?A:l?r[0]:r,O=[N.canvasy,k],m?-1===T[0]?g[N.canvasx]=[N.canvasy,A]:g[N.canvasx]=[N.canvasy,T[0]]:g[N.canvasx]=N.canvasy}else O=isNaN(N.canvasy)&&m?[h.y+h.h,A]:[N.canvasy,A];isNaN(L)?(_.moveTo(N.canvasx,O[1]),_.lineTo(N.canvasx,O[0])):(m?(_.lineTo(N.canvasx,T[0]),_.lineTo(N.canvasx,O[0])):_.lineTo(N.canvasx,O[0]),c&&(F.push([L,T[1]]),l&&r?F.push([N.canvasx,r[1]]):F.push([N.canvasx,O[1]]))),T=O,L=N.canvasx}else f(_,L,T[1],F),F=[],L=NaN,null===N.y_stacked||isNaN(N.y_stacked)||(g[N.canvasx]=h.h*N.y_stacked+h.y);l=m,O&&N&&(f(_,N.canvasx,O[1],F),F=[]),_.fill()}}}},a.default=s,e.exports=a.default},{"./dygraph":18,"./dygraph-utils":17}],10:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-tickers"),o=n(r),s=t("./dygraph-interaction-model"),l=i(s),h=t("./dygraph-canvas"),u=i(h),d=t("./dygraph-utils"),c=n(d),p={highlightCircleSize:3,highlightSeriesOpts:null,highlightSeriesBackgroundAlpha:.5,highlightSeriesBackgroundColor:"rgb(255, 255, 255)",labelsSeparateLines:!1,labelsShowZeroValues:!0,labelsKMB:!1,labelsKMG2:!1,showLabelsOnHighlight:!0,digitsAfterDecimal:2,maxNumberWidth:6,sigFigs:null,strokeWidth:1,strokeBorderWidth:0,strokeBorderColor:"white",axisTickSize:3,axisLabelFontSize:14,rightGap:5,showRoller:!1,xValueParser:void 0,delimiter:",",sigma:2,errorBars:!1,fractions:!1,wilsonInterval:!0,customBars:!1,fillGraph:!1,fillAlpha:.15,connectSeparatedPoints:!1,stackedGraph:!1,stackedGraphNaNFill:"all",hideOverlayOnMouseOut:!0,legend:"onmouseover",stepPlot:!1,xRangePad:0,yRangePad:null,drawAxesAtZero:!1,titleHeight:28,xLabelHeight:18,yLabelWidth:18,axisLineColor:"black",axisLineWidth:.3,gridLineWidth:.3,axisLabelWidth:50,gridLineColor:"rgb(128,128,128)",interactionModel:l.default.defaultModel,animatedZooms:!1,showRangeSelector:!1,rangeSelectorHeight:40,rangeSelectorPlotStrokeColor:"#808FAB",rangeSelectorPlotFillGradientColor:"white",rangeSelectorPlotFillColor:"#A7B1C4",rangeSelectorBackgroundStrokeColor:"gray",rangeSelectorBackgroundLineWidth:1,rangeSelectorPlotLineWidth:1.5,rangeSelectorForegroundStrokeColor:"black",rangeSelectorForegroundLineWidth:1,rangeSelectorAlpha:.6,showInRangeSelector:null,plotter:[u.default._fillPlotter,u.default._errorPlotter,u.default._linePlotter],plugins:[],axes:{x:{pixelsPerLabel:70,axisLabelWidth:60,axisLabelFormatter:c.dateAxisLabelFormatter,valueFormatter:c.dateValueFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.dateTicker},y:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawGrid:!0,drawAxis:!0,independentTicks:!0,ticker:o.numericTicks},y2:{axisLabelWidth:50,pixelsPerLabel:30,valueFormatter:c.numberValueFormatter,axisLabelFormatter:c.numberAxisLabelFormatter,drawAxis:!0,drawGrid:!1,independentTicks:!1,ticker:o.numericTicks}}};a.default=p,e.exports=a.default},{"./dygraph-canvas":9,"./dygraph-interaction-model":12,"./dygraph-tickers":16,"./dygraph-utils":17}],11:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph"),n=function(t){return t&&t.__esModule?t:{default:t}}(i),r=function(t){this.container=t};r.prototype.draw=function(t,e){this.container.innerHTML="",void 0!==this.date_graph&&this.date_graph.destroy(),this.date_graph=new n.default(this.container,t,e)},r.prototype.setSelection=function(t){var e=!1;t.length&&(e=t[0].row),this.date_graph.setSelection(e)},r.prototype.getSelection=function(){var t=[],e=this.date_graph.getSelection();if(e<0)return t;for(var a=this.date_graph.layout_.points,i=0;i<a.length;++i)t.push({row:e,column:i+1});return t},a.default=r,e.exports=a.default},{"./dygraph":18}],12:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r={};r.maybeTreatMouseOpAsClick=function(t,e,a){a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=Math.abs(a.dragEndX-a.dragStartX),o=Math.abs(a.dragEndY-a.dragStartY);i<2&&o<2&&void 0!==e.lastx_&&-1!=e.lastx_&&r.treatMouseOpAsClick(e,t,a),a.regionWidth=i,a.regionHeight=o},r.startPan=function(t,e,a){var i,r;a.isPanning=!0;var o=e.xAxisRange();if(e.getOptionForAxis("logscale","x")?(a.initialLeftmostDate=n.log10(o[0]),a.dateRange=n.log10(o[1])-n.log10(o[0])):(a.initialLeftmostDate=o[0],a.dateRange=o[1]-o[0]),a.xUnitsPerPixel=a.dateRange/(e.plotter_.area.w-1),e.getNumericOption("panEdgeFraction")){var s=e.width_*e.getNumericOption("panEdgeFraction"),l=e.xAxisExtremes(),h=e.toDomXCoord(l[0])-s,u=e.toDomXCoord(l[1])+s,d=e.toDataXCoord(h),c=e.toDataXCoord(u);a.boundedDates=[d,c];var p=[],g=e.height_*e.getNumericOption("panEdgeFraction");for(i=0;i<e.axes_.length;i++){r=e.axes_[i];var f=r.extremeRange,v=e.toDomYCoord(f[0],i)+g,_=e.toDomYCoord(f[1],i)-g,y=e.toDataYCoord(v,i),x=e.toDataYCoord(_,i);p[i]=[y,x]}a.boundedValues=p}for(a.is2DPan=!1,a.axes=[],i=0;i<e.axes_.length;i++){r=e.axes_[i];var m={},b=e.yAxisRange(i);e.attributes_.getForAxis("logscale",i)?(m.initialTopValue=n.log10(b[1]),m.dragValueRange=n.log10(b[1])-n.log10(b[0])):(m.initialTopValue=b[1],m.dragValueRange=b[1]-b[0]),m.unitsPerPixel=m.dragValueRange/(e.plotter_.area.h-1),a.axes.push(m),r.valueRange&&(a.is2DPan=!0)}},r.movePan=function(t,e,a){a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=a.initialLeftmostDate-(a.dragEndX-a.dragStartX)*a.xUnitsPerPixel;a.boundedDates&&(i=Math.max(i,a.boundedDates[0]));var r=i+a.dateRange;if(a.boundedDates&&r>a.boundedDates[1]&&(i-=r-a.boundedDates[1],r=i+a.dateRange),e.getOptionForAxis("logscale","x")?e.dateWindow_=[Math.pow(n.LOG_SCALE,i),Math.pow(n.LOG_SCALE,r)]:e.dateWindow_=[i,r],a.is2DPan)for(var o=a.dragEndY-a.dragStartY,s=0;s<e.axes_.length;s++){var l=e.axes_[s],h=a.axes[s],u=o*h.unitsPerPixel,d=a.boundedValues?a.boundedValues[s]:null,c=h.initialTopValue+u;d&&(c=Math.min(c,d[1]));var p=c-h.dragValueRange;d&&p<d[0]&&(c-=p-d[0],p=c-h.dragValueRange),e.attributes_.getForAxis("logscale",s)?l.valueRange=[Math.pow(n.LOG_SCALE,p),Math.pow(n.LOG_SCALE,c)]:l.valueRange=[p,c]}e.drawGraph_(!1)},r.endPan=r.maybeTreatMouseOpAsClick,r.startZoom=function(t,e,a){a.isZooming=!0,a.zoomMoved=!1},r.moveZoom=function(t,e,a){a.zoomMoved=!0,a.dragEndX=n.dragGetX_(t,a),a.dragEndY=n.dragGetY_(t,a);var i=Math.abs(a.dragStartX-a.dragEndX),r=Math.abs(a.dragStartY-a.dragEndY);a.dragDirection=i<r/2?n.VERTICAL:n.HORIZONTAL,e.drawZoomRect_(a.dragDirection,a.dragStartX,a.dragEndX,a.dragStartY,a.dragEndY,a.prevDragDirection,a.prevEndX,a.prevEndY),a.prevEndX=a.dragEndX,a.prevEndY=a.dragEndY,a.prevDragDirection=a.dragDirection},r.treatMouseOpAsClick=function(t,e,a){for(var i=t.getFunctionOption("clickCallback"),n=t.getFunctionOption("pointClickCallback"),r=null,o=-1,s=Number.MAX_VALUE,l=0;l<t.selPoints_.length;l++){var h=t.selPoints_[l],u=Math.pow(h.canvasx-a.dragEndX,2)+Math.pow(h.canvasy-a.dragEndY,2);!isNaN(u)&&(-1==o||u<s)&&(s=u,o=l)}var d=t.getNumericOption("highlightCircleSize")+2;if(s<=d*d&&(r=t.selPoints_[o]),r){var c={cancelable:!0,point:r,canvasx:a.dragEndX,canvasy:a.dragEndY};if(t.cascadeEvents_("pointClick",c))return;n&&n.call(t,e,r)}var c={cancelable:!0,xval:t.lastx_,pts:t.selPoints_,canvasx:a.dragEndX,canvasy:a.dragEndY};t.cascadeEvents_("click",c)||i&&i.call(t,e,t.lastx_,t.selPoints_)},r.endZoom=function(t,e,a){e.clearZoomRect_(),a.isZooming=!1,r.maybeTreatMouseOpAsClick(t,e,a);var i=e.getArea();if(a.regionWidth>=10&&a.dragDirection==n.HORIZONTAL){var o=Math.min(a.dragStartX,a.dragEndX),s=Math.max(a.dragStartX,a.dragEndX);o=Math.max(o,i.x),s=Math.min(s,i.x+i.w),o<s&&e.doZoomX_(o,s),a.cancelNextDblclick=!0}else if(a.regionHeight>=10&&a.dragDirection==n.VERTICAL){var l=Math.min(a.dragStartY,a.dragEndY),h=Math.max(a.dragStartY,a.dragEndY);l=Math.max(l,i.y),h=Math.min(h,i.y+i.h),l<h&&e.doZoomY_(l,h),a.cancelNextDblclick=!0}a.dragStartX=null,a.dragStartY=null},r.startTouch=function(t,e,a){t.preventDefault(),t.touches.length>1&&(a.startTimeForDoubleTapMs=null);for(var i=[],n=0;n<t.touches.length;n++){var r=t.touches[n];i.push({pageX:r.pageX,pageY:r.pageY,dataX:e.toDataXCoord(r.pageX),dataY:e.toDataYCoord(r.pageY)})}if(a.initialTouches=i,1==i.length)a.initialPinchCenter=i[0],a.touchDirections={x:!0,y:!0};else if(i.length>=2){a.initialPinchCenter={pageX:.5*(i[0].pageX+i[1].pageX),pageY:.5*(i[0].pageY+i[1].pageY),dataX:.5*(i[0].dataX+i[1].dataX),dataY:.5*(i[0].dataY+i[1].dataY)};var o=180/Math.PI*Math.atan2(a.initialPinchCenter.pageY-i[0].pageY,i[0].pageX-a.initialPinchCenter.pageX);o=Math.abs(o),o>90&&(o=90-o),a.touchDirections={x:o<67.5,y:o>22.5}}a.initialRange={x:e.xAxisRange(),y:e.yAxisRange()}},r.moveTouch=function(t,e,a){a.startTimeForDoubleTapMs=null;var i,n=[];for(i=0;i<t.touches.length;i++){var r=t.touches[i];n.push({pageX:r.pageX,pageY:r.pageY})}var o,s=a.initialTouches,l=a.initialPinchCenter;o=1==n.length?n[0]:{pageX:.5*(n[0].pageX+n[1].pageX),pageY:.5*(n[0].pageY+n[1].pageY)};var h={pageX:o.pageX-l.pageX,pageY:o.pageY-l.pageY},u=a.initialRange.x[1]-a.initialRange.x[0],d=a.initialRange.y[0]-a.initialRange.y[1];h.dataX=h.pageX/e.plotter_.area.w*u,h.dataY=h.pageY/e.plotter_.area.h*d;var c,p;if(1==n.length)c=1,p=1;else if(n.length>=2){var g=s[1].pageX-l.pageX;c=(n[1].pageX-o.pageX)/g;var f=s[1].pageY-l.pageY;p=(n[1].pageY-o.pageY)/f}c=Math.min(8,Math.max(.125,c)),p=Math.min(8,Math.max(.125,p));var v=!1;if(a.touchDirections.x&&(e.dateWindow_=[l.dataX-h.dataX+(a.initialRange.x[0]-l.dataX)/c,l.dataX-h.dataX+(a.initialRange.x[1]-l.dataX)/c],v=!0),a.touchDirections.y)for(i=0;i<1;i++){var _=e.axes_[i],y=e.attributes_.getForAxis("logscale",i);y||(_.valueRange=[l.dataY-h.dataY+(a.initialRange.y[0]-l.dataY)/p,l.dataY-h.dataY+(a.initialRange.y[1]-l.dataY)/p],v=!0)}if(e.drawGraph_(!1),v&&n.length>1&&e.getFunctionOption("zoomCallback")){var x=e.xAxisRange();e.getFunctionOption("zoomCallback").call(e,x[0],x[1],e.yAxisRanges())}},r.endTouch=function(t,e,a){if(0!==t.touches.length)r.startTouch(t,e,a);else if(1==t.changedTouches.length){var i=(new Date).getTime(),n=t.changedTouches[0];a.startTimeForDoubleTapMs&&i-a.startTimeForDoubleTapMs<500&&a.doubleTapX&&Math.abs(a.doubleTapX-n.screenX)<50&&a.doubleTapY&&Math.abs(a.doubleTapY-n.screenY)<50?e.resetZoom():(a.startTimeForDoubleTapMs=i,a.doubleTapX=n.screenX,a.doubleTapY=n.screenY)}};var o=function(t,e,a){return t<e?e-t:t>a?t-a:0},s=function(t,e){var a=n.findPos(e.canvas_),i={left:a.x,right:a.x+e.canvas_.offsetWidth,top:a.y,bottom:a.y+e.canvas_.offsetHeight},r={x:n.pageX(t),y:n.pageY(t)},s=o(r.x,i.left,i.right),l=o(r.y,i.top,i.bottom);return Math.max(s,l)};r.defaultModel={mousedown:function(t,e,a){if(!t.button||2!=t.button){a.initializeMouseDown(t,e,a),t.altKey||t.shiftKey?r.startPan(t,e,a):r.startZoom(t,e,a);var i=function(t){if(a.isZooming){s(t,e)<100?r.moveZoom(t,e,a):null!==a.dragEndX&&(a.dragEndX=null,a.dragEndY=null,e.clearZoomRect_())}else a.isPanning&&r.movePan(t,e,a)},o=function t(o){a.isZooming?null!==a.dragEndX?r.endZoom(o,e,a):r.maybeTreatMouseOpAsClick(o,e,a):a.isPanning&&r.endPan(o,e,a),n.removeEvent(document,"mousemove",i),n.removeEvent(document,"mouseup",t),a.destroy()};e.addAndTrackEvent(document,"mousemove",i),e.addAndTrackEvent(document,"mouseup",o)}},willDestroyContextMyself:!0,touchstart:function(t,e,a){r.startTouch(t,e,a)},touchmove:function(t,e,a){r.moveTouch(t,e,a)},touchend:function(t,e,a){r.endTouch(t,e,a)},dblclick:function(t,e,a){if(a.cancelNextDblclick)return void(a.cancelNextDblclick=!1);var i={canvasx:a.dragEndX,canvasy:a.dragEndY,cancelable:!0};e.cascadeEvents_("dblclick",i)||t.altKey||t.shiftKey||e.resetZoom()}},r.nonInteractiveModel_={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a)},mouseup:r.maybeTreatMouseOpAsClick},r.dragIsPanInteractionModel={mousedown:function(t,e,a){a.initializeMouseDown(t,e,a),r.startPan(t,e,a)},mousemove:function(t,e,a){a.isPanning&&r.movePan(t,e,a)},mouseup:function(t,e,a){a.isPanning&&r.endPan(t,e,a)}},a.default=r,e.exports=a.default},{"./dygraph-utils":17}],13:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(t){this.dygraph_=t,this.points=[],this.setNames=[],this.annotations=[],this.yAxes_=null,this.xTicks_=null,this.yTicks_=null};r.prototype.addDataset=function(t,e){this.points.push(e),this.setNames.push(t)},r.prototype.getPlotArea=function(){return this.area_},r.prototype.computePlotArea=function(){var t={x:0,y:0};t.w=this.dygraph_.width_-t.x-this.dygraph_.getOption("rightGap"),t.h=this.dygraph_.height_;var e={chart_div:this.dygraph_.graphDiv,reserveSpaceLeft:function(e){var a={x:t.x,y:t.y,w:e,h:t.h};return t.x+=e,t.w-=e,a},reserveSpaceRight:function(e){var a={x:t.x+t.w-e,y:t.y,w:e,h:t.h};return t.w-=e,a},reserveSpaceTop:function(e){var a={x:t.x,y:t.y,w:t.w,h:e};return t.y+=e,t.h-=e,a},reserveSpaceBottom:function(e){var a={x:t.x,y:t.y+t.h-e,w:t.w,h:e};return t.h-=e,a},chartRect:function(){return{x:t.x,y:t.y,w:t.w,h:t.h}}};this.dygraph_.cascadeEvents_("layout",e),this.area_=t},r.prototype.setAnnotations=function(t){this.annotations=[];for(var e=this.dygraph_.getOption("xValueParser")||function(t){return t},a=0;a<t.length;a++){var i={};if(!t[a].xval&&void 0===t[a].x)return void console.error("Annotations must have an 'x' property");if(t[a].icon&&(!t[a].hasOwnProperty("width")||!t[a].hasOwnProperty("height")))return void console.error("Must set width and height when setting annotation.icon property");n.update(i,t[a]),i.xval||(i.xval=e(i.x)),this.annotations.push(i)}},r.prototype.setXTicks=function(t){this.xTicks_=t},r.prototype.setYAxes=function(t){this.yAxes_=t},r.prototype.evaluate=function(){this._xAxis={},this._evaluateLimits(),this._evaluateLineCharts(),this._evaluateLineTicks(),this._evaluateAnnotations()},r.prototype._evaluateLimits=function(){var t=this.dygraph_.xAxisRange();this._xAxis.minval=t[0],this._xAxis.maxval=t[1];var e=t[1]-t[0];this._xAxis.scale=0!==e?1/e:1,this.dygraph_.getOptionForAxis("logscale","x")&&(this._xAxis.xlogrange=n.log10(this._xAxis.maxval)-n.log10(this._xAxis.minval),this._xAxis.xlogscale=0!==this._xAxis.xlogrange?1/this._xAxis.xlogrange:1);for(var a=0;a<this.yAxes_.length;a++){var i=this.yAxes_[a];i.minyval=i.computedValueRange[0],i.maxyval=i.computedValueRange[1],i.yrange=i.maxyval-i.minyval,i.yscale=0!==i.yrange?1/i.yrange:1,this.dygraph_.getOption("logscale")&&(i.ylogrange=n.log10(i.maxyval)-n.log10(i.minyval),i.ylogscale=0!==i.ylogrange?1/i.ylogrange:1,isFinite(i.ylogrange)&&!isNaN(i.ylogrange)||console.error("axis "+a+" of graph at "+i.g+" can't be displayed in log scale for range ["+i.minyval+" - "+i.maxyval+"]"))}},r.calcXNormal_=function(t,e,a){return a?(n.log10(t)-n.log10(e.minval))*e.xlogscale:(t-e.minval)*e.scale},r.calcYNormal_=function(t,e,a){if(a){var i=1-(n.log10(e)-n.log10(t.minyval))*t.ylogscale;return isFinite(i)?i:NaN}return 1-(e-t.minyval)*t.yscale},r.prototype._evaluateLineCharts=function(){for(var t=this.dygraph_.getOption("stackedGraph"),e=this.dygraph_.getOptionForAxis("logscale","x"),a=0;a<this.points.length;a++){for(var i=this.points[a],n=this.setNames[a],o=this.dygraph_.getOption("connectSeparatedPoints",n),s=this.dygraph_.axisPropertiesForSeries(n),l=this.dygraph_.attributes_.getForSeries("logscale",n),h=0;h<i.length;h++){var u=i[h];u.x=r.calcXNormal_(u.xval,this._xAxis,e);var d=u.yval;t&&(u.y_stacked=r.calcYNormal_(s,u.yval_stacked,l), +null===d||isNaN(d)||(d=u.yval_stacked)),null===d&&(d=NaN,o||(u.yval=NaN)),u.y=r.calcYNormal_(s,d,l)}this.dygraph_.dataHandler_.onLineEvaluated(i,s,l)}},r.prototype._evaluateLineTicks=function(){var t,e,a,i,n,r;for(this.xticks=[],t=0;t<this.xTicks_.length;t++)e=this.xTicks_[t],a=e.label,r=!("label_v"in e),n=r?e.v:e.label_v,(i=this.dygraph_.toPercentXCoord(n))>=0&&i<1&&this.xticks.push({pos:i,label:a,has_tick:r});for(this.yticks=[],t=0;t<this.yAxes_.length;t++)for(var o=this.yAxes_[t],s=0;s<o.ticks.length;s++)e=o.ticks[s],a=e.label,r=!("label_v"in e),n=r?e.v:e.label_v,(i=this.dygraph_.toPercentYCoord(n,t))>0&&i<=1&&this.yticks.push({axis:t,pos:i,label:a,has_tick:r})},r.prototype._evaluateAnnotations=function(){var t,e={};for(t=0;t<this.annotations.length;t++){var a=this.annotations[t];e[a.xval+","+a.series]=a}if(this.annotated_points=[],this.annotations&&this.annotations.length)for(var i=0;i<this.points.length;i++){var n=this.points[i];for(t=0;t<n.length;t++){var r=n[t],o=r.xval+","+r.name;o in e&&(r.annotation=e[o],this.annotated_points.push(r))}}},r.prototype.removeAllDatasets=function(){delete this.points,delete this.setNames,delete this.setPointsLengths,delete this.setPointsOffsets,this.points=[],this.setNames=[],this.setPointsLengths=[],this.setPointsOffsets=[]},a.default=r,e.exports=a.default},{"./dygraph-utils":17}],14:[function(t,e,a){(function(t){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=null;if(void 0!==t);a.default=i,e.exports=a.default}).call(this,t("_process"))},{_process:1}],15:[function(t,e,a){(function(i){"use strict";function n(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var r=t("./dygraph-utils"),o=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(r),s=t("./dygraph-default-attrs"),l=n(s),h=t("./dygraph-options-reference"),u=(n(h),function(t){this.dygraph_=t,this.yAxes_=[],this.xAxis_={},this.series_={},this.global_=this.dygraph_.attrs_,this.user_=this.dygraph_.user_attrs_||{},this.labels_=[],this.highlightSeries_=this.get("highlightSeriesOpts")||{},this.reparseSeries()});if(u.AXIS_STRING_MAPPINGS_={y:0,Y:0,y1:0,Y1:0,y2:1,Y2:1},u.axisToIndex_=function(t){if("string"==typeof t){if(u.AXIS_STRING_MAPPINGS_.hasOwnProperty(t))return u.AXIS_STRING_MAPPINGS_[t];throw"Unknown axis : "+t}if("number"==typeof t){if(0===t||1===t)return t;throw"Dygraphs only supports two y-axes, indexed from 0-1."}if(t)throw"Unknown axis : "+t;return 0},u.prototype.reparseSeries=function(){var t=this.get("labels");if(t){this.labels_=t.slice(1),this.yAxes_=[{series:[],options:{}}],this.xAxis_={options:{}},this.series_={};for(var e=this.user_.series||{},a=0;a<this.labels_.length;a++){var i=this.labels_[a],n=e[i]||{},r=u.axisToIndex_(n.axis);this.series_[i]={idx:a,yAxis:r,options:n},this.yAxes_[r]?this.yAxes_[r].series.push(i):this.yAxes_[r]={series:[i],options:{}}}var s=this.user_.axes||{};o.update(this.yAxes_[0].options,s.y||{}),this.yAxes_.length>1&&o.update(this.yAxes_[1].options,s.y2||{}),o.update(this.xAxis_.options,s.x||{})}},u.prototype.get=function(t){var e=this.getGlobalUser_(t);return null!==e?e:this.getGlobalDefault_(t)},u.prototype.getGlobalUser_=function(t){return this.user_.hasOwnProperty(t)?this.user_[t]:null},u.prototype.getGlobalDefault_=function(t){return this.global_.hasOwnProperty(t)?this.global_[t]:l.default.hasOwnProperty(t)?l.default[t]:null},u.prototype.getForAxis=function(t,e){var a,i;if("number"==typeof e)a=e,i=0===a?"y":"y2";else{if("y1"==e&&(e="y"),"y"==e)a=0;else if("y2"==e)a=1;else{if("x"!=e)throw"Unknown axis "+e;a=-1}i=e}var n=-1==a?this.xAxis_:this.yAxes_[a];if(n){var r=n.options;if(r.hasOwnProperty(t))return r[t]}if("x"!==e||"logscale"!==t){var o=this.getGlobalUser_(t);if(null!==o)return o}var s=l.default.axes[i];return s.hasOwnProperty(t)?s[t]:this.getGlobalDefault_(t)},u.prototype.getForSeries=function(t,e){if(e===this.dygraph_.getHighlightSeries()&&this.highlightSeries_.hasOwnProperty(t))return this.highlightSeries_[t];if(!this.series_.hasOwnProperty(e))throw"Unknown series: "+e;var a=this.series_[e],i=a.options;return i.hasOwnProperty(t)?i[t]:this.getForAxis(t,a.yAxis)},u.prototype.numAxes=function(){return this.yAxes_.length},u.prototype.axisForSeries=function(t){return this.series_[t].yAxis},u.prototype.axisOptions=function(t){return this.yAxes_[t].options},u.prototype.seriesForAxis=function(t){return this.yAxes_[t].series},u.prototype.seriesNames=function(){return this.labels_},void 0!==i);a.default=u,e.exports=a.default}).call(this,t("_process"))},{"./dygraph-default-attrs":10,"./dygraph-options-reference":14,"./dygraph-utils":17,_process:1}],16:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("./dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(t,e,a,i,n,r){return o(t,e,a,function(t){return"logscale"!==t&&i(t)},n,r)};a.numericLinearTicks=r;var o=function(t,e,a,i,r,o){var s,l,h,u,c=i("pixelsPerLabel"),p=[];if(o)for(s=0;s<o.length;s++)p.push({v:o[s]});else{if(i("logscale")){u=Math.floor(a/c);var g=n.binarySearch(t,d,1),f=n.binarySearch(e,d,-1);-1==g&&(g=0),-1==f&&(f=d.length-1);var v=null;if(f-g>=u/4){for(var _=f;_>=g;_--){var y=d[_],x=Math.log(y/t)/Math.log(e/t)*a,m={v:y};null===v?v={tickValue:y,pixel_coord:x}:Math.abs(x-v.pixel_coord)>=c?v={tickValue:y,pixel_coord:x}:m.label="",p.push(m)}p.reverse()}}if(0===p.length){var b,w,A=i("labelsKMG2");A?(b=[1,2,4,8,16,32,64,128,256],w=16):(b=[1,2,5,10,20,50,100],w=10);var O,D,E,L=Math.ceil(a/c),T=Math.abs(e-t)/L,S=Math.floor(Math.log(T)/Math.log(w)),P=Math.pow(w,S);for(l=0;l<b.length&&(O=P*b[l],D=Math.floor(t/O)*O,E=Math.ceil(e/O)*O,u=Math.abs(E-D)/O,!(a/u>c));l++);for(D>E&&(O*=-1),s=0;s<=u;s++)h=D+s*O,p.push({v:h})}}var C=i("axisLabelFormatter");for(s=0;s<p.length;s++)void 0===p[s].label&&(p[s].label=C.call(r,p[s].v,0,i,r));return p};a.numericTicks=o;var s=function(t,e,a,i,n,r){var o=c(t,e,a,i);return o>=0?g(t,e,o,i,n):[]};a.dateTicker=s;var l={MILLISECONDLY:0,TWO_MILLISECONDLY:1,FIVE_MILLISECONDLY:2,TEN_MILLISECONDLY:3,FIFTY_MILLISECONDLY:4,HUNDRED_MILLISECONDLY:5,FIVE_HUNDRED_MILLISECONDLY:6,SECONDLY:7,TWO_SECONDLY:8,FIVE_SECONDLY:9,TEN_SECONDLY:10,THIRTY_SECONDLY:11,MINUTELY:12,TWO_MINUTELY:13,FIVE_MINUTELY:14,TEN_MINUTELY:15,THIRTY_MINUTELY:16,HOURLY:17,TWO_HOURLY:18,SIX_HOURLY:19,DAILY:20,TWO_DAILY:21,WEEKLY:22,MONTHLY:23,QUARTERLY:24,BIANNUAL:25,ANNUAL:26,DECADAL:27,CENTENNIAL:28,NUM_GRANULARITIES:29};a.Granularity=l;var h={DATEFIELD_Y:0,DATEFIELD_M:1,DATEFIELD_D:2,DATEFIELD_HH:3,DATEFIELD_MM:4,DATEFIELD_SS:5,DATEFIELD_MS:6,NUM_DATEFIELDS:7},u=[];u[l.MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:1,spacing:1},u[l.TWO_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:2,spacing:2},u[l.FIVE_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:5,spacing:5},u[l.TEN_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:10,spacing:10},u[l.FIFTY_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:50,spacing:50},u[l.HUNDRED_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:100,spacing:100},u[l.FIVE_HUNDRED_MILLISECONDLY]={datefield:h.DATEFIELD_MS,step:500,spacing:500},u[l.SECONDLY]={datefield:h.DATEFIELD_SS,step:1,spacing:1e3},u[l.TWO_SECONDLY]={datefield:h.DATEFIELD_SS,step:2,spacing:2e3},u[l.FIVE_SECONDLY]={datefield:h.DATEFIELD_SS,step:5,spacing:5e3},u[l.TEN_SECONDLY]={datefield:h.DATEFIELD_SS,step:10,spacing:1e4},u[l.THIRTY_SECONDLY]={datefield:h.DATEFIELD_SS,step:30,spacing:3e4},u[l.MINUTELY]={datefield:h.DATEFIELD_MM,step:1,spacing:6e4},u[l.TWO_MINUTELY]={datefield:h.DATEFIELD_MM,step:2,spacing:12e4},u[l.FIVE_MINUTELY]={datefield:h.DATEFIELD_MM,step:5,spacing:3e5},u[l.TEN_MINUTELY]={datefield:h.DATEFIELD_MM,step:10,spacing:6e5},u[l.THIRTY_MINUTELY]={datefield:h.DATEFIELD_MM,step:30,spacing:18e5},u[l.HOURLY]={datefield:h.DATEFIELD_HH,step:1,spacing:36e5},u[l.TWO_HOURLY]={datefield:h.DATEFIELD_HH,step:2,spacing:72e5},u[l.SIX_HOURLY]={datefield:h.DATEFIELD_HH,step:6,spacing:216e5},u[l.DAILY]={datefield:h.DATEFIELD_D,step:1,spacing:864e5},u[l.TWO_DAILY]={datefield:h.DATEFIELD_D,step:2,spacing:1728e5},u[l.WEEKLY]={datefield:h.DATEFIELD_D,step:7,spacing:6048e5},u[l.MONTHLY]={datefield:h.DATEFIELD_M,step:1,spacing:2629817280},u[l.QUARTERLY]={datefield:h.DATEFIELD_M,step:3,spacing:216e5*365.2524},u[l.BIANNUAL]={datefield:h.DATEFIELD_M,step:6,spacing:432e5*365.2524},u[l.ANNUAL]={datefield:h.DATEFIELD_Y,step:1,spacing:864e5*365.2524},u[l.DECADAL]={datefield:h.DATEFIELD_Y,step:10,spacing:315578073600},u[l.CENTENNIAL]={datefield:h.DATEFIELD_Y,step:100,spacing:3155780736e3};var d=function(){for(var t=[],e=-39;e<=39;e++)for(var a=Math.pow(10,e),i=1;i<=9;i++){var n=a*i;t.push(n)}return t}(),c=function(t,e,a,i){for(var n=i("pixelsPerLabel"),r=0;r<l.NUM_GRANULARITIES;r++){if(a/p(t,e,r)>=n)return r}return-1},p=function(t,e,a){var i=u[a].spacing;return Math.round(1*(e-t)/i)},g=function(t,e,a,i,r){var o=i("axisLabelFormatter"),s=i("labelsUTC"),d=s?n.DateAccessorsUTC:n.DateAccessorsLocal,c=u[a].datefield,p=u[a].step,g=u[a].spacing,f=new Date(t),v=[];v[h.DATEFIELD_Y]=d.getFullYear(f),v[h.DATEFIELD_M]=d.getMonth(f),v[h.DATEFIELD_D]=d.getDate(f),v[h.DATEFIELD_HH]=d.getHours(f),v[h.DATEFIELD_MM]=d.getMinutes(f),v[h.DATEFIELD_SS]=d.getSeconds(f),v[h.DATEFIELD_MS]=d.getMilliseconds(f);var _=v[c]%p;a==l.WEEKLY&&(_=d.getDay(f)),v[c]-=_;for(var y=c+1;y<h.NUM_DATEFIELDS;y++)v[y]=y===h.DATEFIELD_D?1:0;var x=[],m=d.makeDate.apply(null,v),b=m.getTime();if(a<=l.HOURLY)for(b<t&&(b+=g,m=new Date(b));b<=e;)x.push({v:b,label:o.call(r,m,a,i,r)}),b+=g,m=new Date(b);else for(b<t&&(v[c]+=p,m=d.makeDate.apply(null,v),b=m.getTime());b<=e;)(a>=l.DAILY||d.getHours(m)%p==0)&&x.push({v:b,label:o.call(r,m,a,i,r)}),v[c]+=p,m=d.makeDate.apply(null,v),b=m.getTime();return x};a.getDateAxis=g},{"./dygraph-utils":17}],17:[function(t,e,a){"use strict";function i(t,e,a){t.removeEventListener(e,a,!1)}function n(t){return t=t||window.event,t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),t.cancelBubble=!0,t.cancel=!0,t.returnValue=!1,!1}function r(t,e,a){var i,n,r;if(0===e)i=a,n=a,r=a;else{var o=Math.floor(6*t),s=6*t-o,l=a*(1-e),h=a*(1-e*s),u=a*(1-e*(1-s));switch(o){case 1:i=h,n=a,r=l;break;case 2:i=l,n=a,r=u;break;case 3:i=l,n=h,r=a;break;case 4:i=u,n=l,r=a;break;case 5:i=a,n=l,r=h;break;case 6:case 0:i=a,n=u,r=l}}return i=Math.floor(255*i+.5),n=Math.floor(255*n+.5),r=Math.floor(255*r+.5),"rgb("+i+","+n+","+r+")"}function o(t){var e=t.getBoundingClientRect(),a=window,i=document.documentElement;return{x:e.left+(a.pageXOffset||i.scrollLeft),y:e.top+(a.pageYOffset||i.scrollTop)}}function s(t){return!t.pageX||t.pageX<0?0:t.pageX}function l(t){return!t.pageY||t.pageY<0?0:t.pageY}function h(t,e){return s(t)-e.px}function u(t,e){return l(t)-e.py}function d(t){return!!t&&!isNaN(t)}function c(t,e){return!!t&&(null!==t.yval&&(null!==t.x&&void 0!==t.x&&(null!==t.y&&void 0!==t.y&&!(isNaN(t.x)||!e&&isNaN(t.y)))))}function p(t,e){var a=Math.min(Math.max(1,e||2),21);return Math.abs(t)<.001&&0!==t?t.toExponential(a-1):t.toPrecision(a)}function g(t){return t<10?"0"+t:""+t}function f(t,e,a,i){var n=g(t)+":"+g(e);if(a&&(n+=":"+g(a),i)){var r=""+i;n+="."+("000"+r).substring(r.length)}return n}function v(t,e){var a=e?tt:$,i=new Date(t),n=a.getFullYear(i),r=a.getMonth(i),o=a.getDate(i),s=a.getHours(i),l=a.getMinutes(i),h=a.getSeconds(i),u=a.getMilliseconds(i),d=""+n,c=g(r+1),p=g(o),v=3600*s+60*l+h+.001*u,_=d+"/"+c+"/"+p;return v&&(_+=" "+f(s,l,h,u)),_}function _(t,e){var a=Math.pow(10,e);return Math.round(t*a)/a}function y(t,e,a,i,n){for(var r=!0;r;){var o=t,s=e,l=a,h=i,u=n;if(r=!1,null!==h&&void 0!==h&&null!==u&&void 0!==u||(h=0,u=s.length-1),h>u)return-1;null!==l&&void 0!==l||(l=0);var d,c=function(t){return t>=0&&t<s.length},p=parseInt((h+u)/2,10),g=s[p];if(g==o)return p;if(g>o){if(l>0&&(d=p-1,c(d)&&s[d]<o))return p;t=o,e=s,a=l,i=h,n=p-1,r=!0,c=p=g=d=void 0}else{if(!(g<o))return-1;if(l<0&&(d=p+1,c(d)&&s[d]>o))return p;t=o,e=s,a=l,i=p+1,n=u,r=!0,c=p=g=d=void 0}}}function x(t){var e,a;if((-1==t.search("-")||-1!=t.search("T")||-1!=t.search("Z"))&&(a=m(t))&&!isNaN(a))return a;if(-1!=t.search("-")){for(e=t.replace("-","/","g");-1!=e.search("-");)e=e.replace("-","/");a=m(e)}else 8==t.length?(e=t.substr(0,4)+"/"+t.substr(4,2)+"/"+t.substr(6,2),a=m(e)):a=m(t);return a&&!isNaN(a)||console.error("Couldn't parse "+t+" as a date"),a}function m(t){return new Date(t).getTime()}function b(t,e){if(void 0!==e&&null!==e)for(var a in e)e.hasOwnProperty(a)&&(t[a]=e[a]);return t}function w(t,e){if(void 0!==e&&null!==e)for(var a in e)e.hasOwnProperty(a)&&(null===e[a]?t[a]=null:A(e[a])?t[a]=e[a].slice():!function(t){return"object"==typeof Node?t instanceof Node:"object"==typeof t&&"number"==typeof t.nodeType&&"string"==typeof t.nodeName}(e[a])&&"object"==typeof e[a]?("object"==typeof t[a]&&null!==t[a]||(t[a]={}),w(t[a],e[a])):t[a]=e[a]);return t}function A(t){var e=typeof t;return("object"==e||"function"==e&&"function"==typeof t.item)&&null!==t&&"number"==typeof t.length&&3!==t.nodeType}function O(t){return"object"==typeof t&&null!==t&&"function"==typeof t.getTime}function D(t){for(var e=[],a=0;a<t.length;a++)A(t[a])?e.push(D(t[a])):e.push(t[a]);return e}function E(){return document.createElement("canvas")}function L(t){try{var e=window.devicePixelRatio,a=t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||t.backingStorePixelRatio||1;return void 0!==e?e/a:1}catch(t){return 1}}function T(t,e,a,i){e=e||0,a=a||t.length,this.hasNext=!0,this.peek=null,this.start_=e,this.array_=t,this.predicate_=i,this.end_=Math.min(t.length,e+a),this.nextIdx_=e-1,this.next()}function S(t,e,a,i){return new T(t,e,a,i)}function P(t,e,a,i){var n,r=0,o=(new Date).getTime();if(t(r),1==e)return void i();var s=e-1;!function l(){r>=e||et.call(window,function(){var e=(new Date).getTime(),h=e-o;n=r,r=Math.floor(h/a);var u=r-n;r+u>s||r>=s?(t(s),i()):(0!==u&&t(r),l())})}()}function C(t,e){var a={};if(t)for(var i=1;i<t.length;i++)a[t[i]]=!0;var n=function(t){for(var e in t)if(t.hasOwnProperty(e)&&!at[e])return!0;return!1};for(var r in e)if(e.hasOwnProperty(r))if("highlightSeriesOpts"==r||a[r]&&!e.series){if(n(e[r]))return!0}else if("series"==r||"axes"==r){var o=e[r];for(var s in o)if(o.hasOwnProperty(s)&&n(o[s]))return!0}else if(!at[r])return!0;return!1}function M(t){for(var e=0;e<t.length;e++){var a=t.charAt(e);if("\r"===a)return e+1<t.length&&"\n"===t.charAt(e+1)?"\r\n":a;if("\n"===a)return e+1<t.length&&"\r"===t.charAt(e+1)?"\n\r":a}return null}function N(t,e){if(null===e||null===t)return!1;for(var a=t;a&&a!==e;)a=a.parentNode;return a===e}function F(t,e){return e<0?1/Math.pow(t,-e):Math.pow(t,e)}function k(t){var e=nt.exec(t);if(!e)return null;var a=parseInt(e[1],10),i=parseInt(e[2],10),n=parseInt(e[3],10);return e[4]?{r:a,g:i,b:n,a:parseFloat(e[4])}:{r:a,g:i,b:n}}function R(t){var e=k(t);if(e)return e;var a=document.createElement("div");a.style.backgroundColor=t,a.style.visibility="hidden",document.body.appendChild(a);var i=window.getComputedStyle(a,null).backgroundColor;return document.body.removeChild(a),k(i)}function I(t){try{(t||document.createElement("canvas")).getContext("2d")}catch(t){return!1}return!0}function H(t,e,a){var i=parseFloat(t);if(!isNaN(i))return i;if(/^ *$/.test(t))return null;if(/^ *nan *$/i.test(t))return NaN;var n="Unable to parse '"+t+"' as a number";return void 0!==a&&void 0!==e&&(n+=" on line "+(1+(e||0))+" ('"+a+"') of CSV."),console.error(n),null}function Y(t,e){var a=e("sigFigs");if(null!==a)return p(t,a);var i,n=e("digitsAfterDecimal"),r=e("maxNumberWidth"),o=e("labelsKMB"),s=e("labelsKMG2");if(i=0!==t&&(Math.abs(t)>=Math.pow(10,r)||Math.abs(t)<Math.pow(10,-n))?t.toExponential(n):""+_(t,n),o||s){var l,h=[],u=[];o&&(l=1e3,h=rt),s&&(o&&console.warn("Setting both labelsKMB and labelsKMG2. Pick one!"),l=1024,h=ot,u=st);for(var d=Math.abs(t),c=F(l,h.length),g=h.length-1;g>=0;g--,c/=l)if(d>=c){i=_(t/c,n)+h[g];break}if(s){var f=String(t.toExponential()).split("e-");2===f.length&&f[1]>=3&&f[1]<=24&&(i=f[1]%3>0?_(f[0]/F(10,f[1]%3),n):Number(f[0]).toFixed(2),i+=u[Math.floor(f[1]/3)-1])}}return i}function X(t,e,a){return Y.call(this,t,a)}function V(t,e,a){var i=a("labelsUTC"),n=i?tt:$,r=n.getFullYear(t),o=n.getMonth(t),s=n.getDate(t),l=n.getHours(t),h=n.getMinutes(t),u=n.getSeconds(t),d=n.getMilliseconds(t);if(e>=G.Granularity.DECADAL)return""+r;if(e>=G.Granularity.MONTHLY)return lt[o]+" "+r;if(0===3600*l+60*h+u+.001*d||e>=G.Granularity.DAILY)return g(s)+" "+lt[o];if(e<G.Granularity.SECONDLY){var c=""+d;return g(u)+"."+("000"+c).substring(c.length)}return e>G.Granularity.MINUTELY?f(l,h,u,0):f(l,h,u,d)}function Z(t,e){return v(t,e("labelsUTC"))}Object.defineProperty(a,"__esModule",{value:!0}),a.removeEvent=i,a.cancelEvent=n,a.hsvToRGB=r,a.findPos=o,a.pageX=s,a.pageY=l,a.dragGetX_=h,a.dragGetY_=u,a.isOK=d,a.isValidPoint=c,a.floatFormat=p,a.zeropad=g,a.hmsString_=f,a.dateString_=v,a.round_=_,a.binarySearch=y,a.dateParser=x,a.dateStrToMillis=m,a.update=b,a.updateDeep=w,a.isArrayLike=A,a.isDateLike=O,a.clone=D,a.createCanvas=E,a.getContextPixelRatio=L,a.Iterator=T,a.createIterator=S,a.repeatAndCleanup=P,a.isPixelChangingOptionList=C,a.detectLineDelimiter=M,a.isNodeContainedBy=N,a.pow=F,a.toRGB_=R,a.isCanvasSupported=I,a.parseFloat_=H,a.numberValueFormatter=Y,a.numberAxisLabelFormatter=X,a.dateAxisLabelFormatter=V,a.dateValueFormatter=Z;var B=t("./dygraph-tickers"),G=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(B);a.LOG_SCALE=10;var W=Math.log(10);a.LN_TEN=W;var U=function(t){return Math.log(t)/W};a.log10=U;var z=function(t,e,a){var i=U(t),n=U(e),r=i+a*(n-i);return Math.pow(10,r)};a.logRangeFraction=z;var j=[2,2];a.DOTTED_LINE=j;var K=[7,3];a.DASHED_LINE=K;var q=[7,2,2,2];a.DOT_DASH_LINE=q;a.HORIZONTAL=1;a.VERTICAL=2;var Q=function(t){return t.getContext("2d")};a.getContext=Q;var J=function(t,e,a){t.addEventListener(e,a,!1)};a.addEvent=J;var $={getFullYear:function(t){return t.getFullYear()},getMonth:function(t){return t.getMonth()},getDate:function(t){return t.getDate()},getHours:function(t){return t.getHours()},getMinutes:function(t){return t.getMinutes()},getSeconds:function(t){return t.getSeconds()},getMilliseconds:function(t){return t.getMilliseconds()},getDay:function(t){return t.getDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(t,e,a,i,n,r,o)}};a.DateAccessorsLocal=$;var tt={getFullYear:function(t){return t.getUTCFullYear()},getMonth:function(t){return t.getUTCMonth()},getDate:function(t){return t.getUTCDate()},getHours:function(t){return t.getUTCHours()},getMinutes:function(t){return t.getUTCMinutes()},getSeconds:function(t){return t.getUTCSeconds()},getMilliseconds:function(t){return t.getUTCMilliseconds()},getDay:function(t){return t.getUTCDay()},makeDate:function(t,e,a,i,n,r,o){return new Date(Date.UTC(t,e,a,i,n,r,o))}};a.DateAccessorsUTC=tt,T.prototype.next=function(){if(!this.hasNext)return null;for(var t=this.peek,e=this.nextIdx_+1,a=!1;e<this.end_;){if(!this.predicate_||this.predicate_(this.array_,e)){this.peek=this.array_[e],a=!0;break}e++}return this.nextIdx_=e,a||(this.hasNext=!1,this.peek=null),t};var et=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)}}();a.requestAnimFrame=et;var at={annotationClickHandler:!0,annotationDblClickHandler:!0,annotationMouseOutHandler:!0,annotationMouseOverHandler:!0,axisLineColor:!0,axisLineWidth:!0,clickCallback:!0,drawCallback:!0,drawHighlightPointCallback:!0,drawPoints:!0,drawPointCallback:!0,drawGrid:!0,fillAlpha:!0,gridLineColor:!0,gridLineWidth:!0,hideOverlayOnMouseOut:!0,highlightCallback:!0,highlightCircleSize:!0,interactionModel:!0,labelsDiv:!0,labelsKMB:!0,labelsKMG2:!0,labelsSeparateLines:!0,labelsShowZeroValues:!0,legend:!0,panEdgeFraction:!0,pixelsPerYLabel:!0,pointClickCallback:!0,pointSize:!0,rangeSelectorPlotFillColor:!0,rangeSelectorPlotFillGradientColor:!0,rangeSelectorPlotStrokeColor:!0,rangeSelectorBackgroundStrokeColor:!0,rangeSelectorBackgroundLineWidth:!0,rangeSelectorPlotLineWidth:!0,rangeSelectorForegroundStrokeColor:!0,rangeSelectorForegroundLineWidth:!0,rangeSelectorAlpha:!0,showLabelsOnHighlight:!0,showRoller:!0,strokeWidth:!0,underlayCallback:!0,unhighlightCallback:!0,zoomCallback:!0},it={DEFAULT:function(t,e,a,i,n,r,o){a.beginPath(),a.fillStyle=r,a.arc(i,n,o,0,2*Math.PI,!1),a.fill()}};a.Circles=it;var nt=/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([01](?:\.\d+)?))?\)$/,rt=["K","M","B","T","Q"],ot=["k","M","G","T","P","E","Z","Y"],st=["m","u","n","p","f","a","z","y"],lt=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]},{"./dygraph-tickers":16}],18:[function(t,e,a){(function(i){"use strict";function n(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}function r(t){return t&&t.__esModule?t:{default:t}}function o(t){var e=t[0],a=e[0];if("number"!=typeof a&&!x.isDateLike(a))throw new Error("Expected number or date but got "+typeof a+": "+a+".");for(var i=1;i<e.length;i++){var n=e[i];if(null!==n&&void 0!==n&&("number"!=typeof n&&!x.isArrayLike(n)))throw new Error("Expected number or array but got "+typeof n+": "+n+".")}}Object.defineProperty(a,"__esModule",{value:!0});var s=function(){function t(t,e){var a=[],i=!0,n=!1,r=void 0;try{for(var o,s=t[Symbol.iterator]();!(i=(o=s.next()).done)&&(a.push(o.value),!e||a.length!==e);i=!0);}catch(t){n=!0,r=t}finally{try{!i&&s.return&&s.return()}finally{if(n)throw r}}return a}return function(e,a){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,a);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),l=t("./dygraph-layout"),h=r(l),u=t("./dygraph-canvas"),d=r(u),c=t("./dygraph-options"),p=r(c),g=t("./dygraph-interaction-model"),f=r(g),v=t("./dygraph-tickers"),_=n(v),y=t("./dygraph-utils"),x=n(y),m=t("./dygraph-default-attrs"),b=r(m),w=t("./dygraph-options-reference"),A=(r(w),t("./iframe-tarp")),O=r(A),D=t("./datahandler/default"),E=r(D),L=t("./datahandler/bars-error"),T=r(L),S=t("./datahandler/bars-custom"),P=r(S),C=t("./datahandler/default-fractions"),M=r(C),N=t("./datahandler/bars-fractions"),F=r(N),k=t("./datahandler/bars"),R=r(k),I=t("./plugins/annotations"),H=r(I),Y=t("./plugins/axes"),X=r(Y),V=t("./plugins/chart-labels"),Z=r(V),B=t("./plugins/grid"),G=r(B),W=t("./plugins/legend"),U=r(W),z=t("./plugins/range-selector"),j=r(z),K=t("./dygraph-gviz"),q=r(K),Q=function(t,e,a){this.__init__(t,e,a)};Q.NAME="Dygraph",Q.VERSION="2.1.0",Q.DEFAULT_ROLL_PERIOD=1,Q.DEFAULT_WIDTH=480,Q.DEFAULT_HEIGHT=320,Q.ANIMATION_STEPS=12,Q.ANIMATION_DURATION=200,Q.Plotters=d.default._Plotters,Q.addedAnnotationCSS=!1,Q.prototype.__init__=function(t,e,a){if(this.is_initial_draw_=!0,this.readyFns_=[],null!==a&&void 0!==a||(a={}),a=Q.copyUserAttrs_(a),"string"==typeof t&&(t=document.getElementById(t)),!t)throw new Error("Constructing dygraph with a non-existent div!");this.maindiv_=t,this.file_=e,this.rollPeriod_=a.rollPeriod||Q.DEFAULT_ROLL_PERIOD,this.previousVerticalX_=-1,this.fractions_=a.fractions||!1,this.dateWindow_=a.dateWindow||null,this.annotations_=[],t.innerHTML="",""===t.style.width&&a.width&&(t.style.width=a.width+"px"),""===t.style.height&&a.height&&(t.style.height=a.height+"px"),""===t.style.height&&0===t.clientHeight&&(t.style.height=Q.DEFAULT_HEIGHT+"px",""===t.style.width&&(t.style.width=Q.DEFAULT_WIDTH+"px")),this.width_=t.clientWidth||a.width||0,this.height_=t.clientHeight||a.height||0,a.stackedGraph&&(a.fillGraph=!0),this.user_attrs_={},x.update(this.user_attrs_,a),this.attrs_={},x.updateDeep(this.attrs_,b.default),this.boundaryIds_=[],this.setIndexByName_={},this.datasetIndex_=[],this.registeredEvents_=[],this.eventListeners_={},this.attributes_=new p.default(this),this.createInterface_(),this.plugins_=[];for(var i=Q.PLUGINS.concat(this.getOption("plugins")),n=0;n<i.length;n++){var r,o=i[n];r=void 0!==o.activate?o:new o;var s={plugin:r,events:{},options:{},pluginOptions:{}},l=r.activate(this);for(var h in l)l.hasOwnProperty(h)&&(s.events[h]=l[h]);this.plugins_.push(s)}for(var n=0;n<this.plugins_.length;n++){var u=this.plugins_[n];for(var h in u.events)if(u.events.hasOwnProperty(h)){var d=u.events[h],c=[u.plugin,d];h in this.eventListeners_?this.eventListeners_[h].push(c):this.eventListeners_[h]=[c]}}this.createDragInterface_(),this.start_()},Q.prototype.cascadeEvents_=function(t,e){if(!(t in this.eventListeners_))return!1;var a={dygraph:this,cancelable:!1,defaultPrevented:!1,preventDefault:function(){if(!a.cancelable)throw"Cannot call preventDefault on non-cancelable event.";a.defaultPrevented=!0},propagationStopped:!1,stopPropagation:function(){a.propagationStopped=!0}};x.update(a,e);var i=this.eventListeners_[t];if(i)for(var n=i.length-1;n>=0;n--){var r=i[n][0],o=i[n][1];if(o.call(r,a),a.propagationStopped)break}return a.defaultPrevented},Q.prototype.getPluginInstance_=function(t){for(var e=0;e<this.plugins_.length;e++){var a=this.plugins_[e];if(a.plugin instanceof t)return a.plugin}return null},Q.prototype.isZoomed=function(t){var e=!!this.dateWindow_;if("x"===t)return e;var a=this.axes_.map(function(t){return!!t.valueRange}).indexOf(!0)>=0;if(null===t||void 0===t)return e||a;if("y"===t)return a;throw new Error("axis parameter is ["+t+"] must be null, 'x' or 'y'.")},Q.prototype.toString=function(){var t=this.maindiv_;return"[Dygraph "+(t&&t.id?t.id:t)+"]"},Q.prototype.attr_=function(t,e){return e?this.attributes_.getForSeries(t,e):this.attributes_.get(t)},Q.prototype.getOption=function(t,e){return this.attr_(t,e)},Q.prototype.getNumericOption=function(t,e){return this.getOption(t,e)},Q.prototype.getStringOption=function(t,e){return this.getOption(t,e)},Q.prototype.getBooleanOption=function(t,e){return this.getOption(t,e)},Q.prototype.getFunctionOption=function(t,e){return this.getOption(t,e)},Q.prototype.getOptionForAxis=function(t,e){return this.attributes_.getForAxis(t,e)},Q.prototype.optionsViewForAxis_=function(t){var e=this;return function(a){var i=e.user_attrs_.axes;return i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:("x"!==t||"logscale"!==a)&&(void 0!==e.user_attrs_[a]?e.user_attrs_[a]:(i=e.attrs_.axes,i&&i[t]&&i[t].hasOwnProperty(a)?i[t][a]:"y"==t&&e.axes_[0].hasOwnProperty(a)?e.axes_[0][a]:"y2"==t&&e.axes_[1].hasOwnProperty(a)?e.axes_[1][a]:e.attr_(a)))}},Q.prototype.rollPeriod=function(){return this.rollPeriod_},Q.prototype.xAxisRange=function(){return this.dateWindow_?this.dateWindow_:this.xAxisExtremes()},Q.prototype.xAxisExtremes=function(){var t=this.getNumericOption("xRangePad")/this.plotter_.area.w;if(0===this.numRows())return[0-t,1+t];var e=this.rawData_[0][0],a=this.rawData_[this.rawData_.length-1][0];if(t){var i=a-e;e-=i*t,a+=i*t}return[e,a]},Q.prototype.yAxisExtremes=function(){var t=this.gatherDatasets_(this.rolledSeries_,null),e=t.extremes,a=this.axes_;this.computeYAxisRanges_(e);var i=this.axes_;return this.axes_=a,i.map(function(t){return t.extremeRange})},Q.prototype.yAxisRange=function(t){if(void 0===t&&(t=0),t<0||t>=this.axes_.length)return null;var e=this.axes_[t];return[e.computedValueRange[0],e.computedValueRange[1]]},Q.prototype.yAxisRanges=function(){for(var t=[],e=0;e<this.axes_.length;e++)t.push(this.yAxisRange(e));return t},Q.prototype.toDomCoords=function(t,e,a){return[this.toDomXCoord(t),this.toDomYCoord(e,a)]},Q.prototype.toDomXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();return e.x+(t-a[0])/(a[1]-a[0])*e.w},Q.prototype.toDomYCoord=function(t,e){var a=this.toPercentYCoord(t,e);if(null===a)return null;var i=this.plotter_.area;return i.y+a*i.h},Q.prototype.toDataCoords=function(t,e,a){return[this.toDataXCoord(t),this.toDataYCoord(e,a)]},Q.prototype.toDataXCoord=function(t){if(null===t)return null;var e=this.plotter_.area,a=this.xAxisRange();if(this.attributes_.getForAxis("logscale","x")){var i=(t-e.x)/e.w;return x.logRangeFraction(a[0],a[1],i)}return a[0]+(t-e.x)/e.w*(a[1]-a[0])},Q.prototype.toDataYCoord=function(t,e){if(null===t)return null;var a=this.plotter_.area,i=this.yAxisRange(e);if(void 0===e&&(e=0),this.attributes_.getForAxis("logscale",e)){var n=(t-a.y)/a.h;return x.logRangeFraction(i[1],i[0],n)}return i[0]+(a.y+a.h-t)/a.h*(i[1]-i[0])},Q.prototype.toPercentYCoord=function(t,e){if(null===t)return null;void 0===e&&(e=0);var a,i=this.yAxisRange(e);if(this.attributes_.getForAxis("logscale",e)){var n=x.log10(i[0]),r=x.log10(i[1]);a=(r-x.log10(t))/(r-n)}else a=(i[1]-t)/(i[1]-i[0]);return a},Q.prototype.toPercentXCoord=function(t){if(null===t)return null;var e,a=this.xAxisRange();if(!0===this.attributes_.getForAxis("logscale","x")){var i=x.log10(a[0]),n=x.log10(a[1]);e=(x.log10(t)-i)/(n-i)}else e=(t-a[0])/(a[1]-a[0]);return e},Q.prototype.numColumns=function(){return this.rawData_?this.rawData_[0]?this.rawData_[0].length:this.attr_("labels").length:0},Q.prototype.numRows=function(){return this.rawData_?this.rawData_.length:0},Q.prototype.getValue=function(t,e){return t<0||t>this.rawData_.length?null:e<0||e>this.rawData_[t].length?null:this.rawData_[t][e]},Q.prototype.createInterface_=function(){var t=this.maindiv_;this.graphDiv=document.createElement("div"),this.graphDiv.style.textAlign="left",this.graphDiv.style.position="relative",t.appendChild(this.graphDiv),this.canvas_=x.createCanvas(),this.canvas_.style.position="absolute",this.hidden_=this.createPlotKitCanvas_(this.canvas_),this.canvas_ctx_=x.getContext(this.canvas_),this.hidden_ctx_=x.getContext(this.hidden_),this.resizeElements_(),this.graphDiv.appendChild(this.hidden_),this.graphDiv.appendChild(this.canvas_),this.mouseEventElement_=this.createMouseEventElement_(),this.layout_=new h.default(this);var e=this;this.mouseMoveHandler_=function(t){e.mouseMove_(t)},this.mouseOutHandler_=function(t){var a=t.target||t.fromElement,i=t.relatedTarget||t.toElement;x.isNodeContainedBy(a,e.graphDiv)&&!x.isNodeContainedBy(i,e.graphDiv)&&e.mouseOut_(t)},this.addAndTrackEvent(window,"mouseout",this.mouseOutHandler_),this.addAndTrackEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),this.resizeHandler_||(this.resizeHandler_=function(t){e.resize()},this.addAndTrackEvent(window,"resize",this.resizeHandler_))},Q.prototype.resizeElements_=function(){this.graphDiv.style.width=this.width_+"px",this.graphDiv.style.height=this.height_+"px";var t=this.getNumericOption("pixelRatio"),e=t||x.getContextPixelRatio(this.canvas_ctx_);this.canvas_.width=this.width_*e,this.canvas_.height=this.height_*e,this.canvas_.style.width=this.width_+"px",this.canvas_.style.height=this.height_+"px",1!==e&&this.canvas_ctx_.scale(e,e);var a=t||x.getContextPixelRatio(this.hidden_ctx_);this.hidden_.width=this.width_*a,this.hidden_.height=this.height_*a,this.hidden_.style.width=this.width_+"px",this.hidden_.style.height=this.height_+"px",1!==a&&this.hidden_ctx_.scale(a,a)},Q.prototype.destroy=function(){this.canvas_ctx_.restore(),this.hidden_ctx_.restore();for(var t=this.plugins_.length-1;t>=0;t--){var e=this.plugins_.pop();e.plugin.destroy&&e.plugin.destroy()}this.removeTrackedEvents_(),x.removeEvent(window,"mouseout",this.mouseOutHandler_),x.removeEvent(this.mouseEventElement_,"mousemove",this.mouseMoveHandler_),x.removeEvent(window,"resize",this.resizeHandler_),this.resizeHandler_=null,function t(e){for(;e.hasChildNodes();)t(e.firstChild),e.removeChild(e.firstChild)}(this.maindiv_);var a=function(t){for(var e in t)"object"==typeof t[e]&&(t[e]=null)};a(this.layout_),a(this.plotter_),a(this)},Q.prototype.createPlotKitCanvas_=function(t){var e=x.createCanvas();return e.style.position="absolute",e.style.top=t.style.top,e.style.left=t.style.left, +e.width=this.width_,e.height=this.height_,e.style.width=this.width_+"px",e.style.height=this.height_+"px",e},Q.prototype.createMouseEventElement_=function(){return this.canvas_},Q.prototype.setColors_=function(){var t=this.getLabels(),e=t.length-1;this.colors_=[],this.colorsMap_={};for(var a=this.getNumericOption("colorSaturation")||1,i=this.getNumericOption("colorValue")||.5,n=Math.ceil(e/2),r=this.getOption("colors"),o=this.visibility(),s=0;s<e;s++)if(o[s]){var l=t[s+1],h=this.attributes_.getForSeries("color",l);if(!h)if(r)h=r[s%r.length];else{var u=s%2?n+(s+1)/2:Math.ceil((s+1)/2),d=1*u/(1+e);h=x.hsvToRGB(d,a,i)}this.colors_.push(h),this.colorsMap_[l]=h}},Q.prototype.getColors=function(){return this.colors_},Q.prototype.getPropertiesForSeries=function(t){for(var e=-1,a=this.getLabels(),i=1;i<a.length;i++)if(a[i]==t){e=i;break}return-1==e?null:{name:t,column:e,visible:this.visibility()[e-1],color:this.colorsMap_[t],axis:1+this.attributes_.axisForSeries(t)}},Q.prototype.createRollInterface_=function(){var t=this,e=this.roller_;e||(this.roller_=e=document.createElement("input"),e.type="text",e.style.display="none",e.className="dygraph-roller",this.graphDiv.appendChild(e));var a=this.getBooleanOption("showRoller")?"block":"none",i=this.getArea(),n={top:i.y+i.h-25+"px",left:i.x+1+"px",display:a};e.size="2",e.value=this.rollPeriod_,x.update(e.style,n),e.onchange=function(){return t.adjustRoll(e.value)}},Q.prototype.createDragInterface_=function(){var t={isZooming:!1,isPanning:!1,is2DPan:!1,dragStartX:null,dragStartY:null,dragEndX:null,dragEndY:null,dragDirection:null,prevEndX:null,prevEndY:null,prevDragDirection:null,cancelNextDblclick:!1,initialLeftmostDate:null,xUnitsPerPixel:null,dateRange:null,px:0,py:0,boundedDates:null,boundedValues:null,tarp:new O.default,initializeMouseDown:function(t,e,a){t.preventDefault?t.preventDefault():(t.returnValue=!1,t.cancelBubble=!0);var i=x.findPos(e.canvas_);a.px=i.x,a.py=i.y,a.dragStartX=x.dragGetX_(t,a),a.dragStartY=x.dragGetY_(t,a),a.cancelNextDblclick=!1,a.tarp.cover()},destroy:function(){var t=this;if((t.isZooming||t.isPanning)&&(t.isZooming=!1,t.dragStartX=null,t.dragStartY=null),t.isPanning){t.isPanning=!1,t.draggingDate=null,t.dateRange=null;for(var e=0;e<a.axes_.length;e++)delete a.axes_[e].draggingValue,delete a.axes_[e].dragValueRange}t.tarp.uncover()}},e=this.getOption("interactionModel"),a=this;for(var i in e)e.hasOwnProperty(i)&&this.addAndTrackEvent(this.mouseEventElement_,i,function(e){return function(i){e(i,a,t)}}(e[i]));if(!e.willDestroyContextMyself){var n=function(e){t.destroy()};this.addAndTrackEvent(document,"mouseup",n)}},Q.prototype.drawZoomRect_=function(t,e,a,i,n,r,o,s){var l=this.canvas_ctx_;r==x.HORIZONTAL?l.clearRect(Math.min(e,o),this.layout_.getPlotArea().y,Math.abs(e-o),this.layout_.getPlotArea().h):r==x.VERTICAL&&l.clearRect(this.layout_.getPlotArea().x,Math.min(i,s),this.layout_.getPlotArea().w,Math.abs(i-s)),t==x.HORIZONTAL?a&&e&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(Math.min(e,a),this.layout_.getPlotArea().y,Math.abs(a-e),this.layout_.getPlotArea().h)):t==x.VERTICAL&&n&&i&&(l.fillStyle="rgba(128,128,128,0.33)",l.fillRect(this.layout_.getPlotArea().x,Math.min(i,n),this.layout_.getPlotArea().w,Math.abs(n-i)))},Q.prototype.clearZoomRect_=function(){this.currentZoomRectArgs_=null,this.canvas_ctx_.clearRect(0,0,this.width_,this.height_)},Q.prototype.doZoomX_=function(t,e){this.currentZoomRectArgs_=null;var a=this.toDataXCoord(t),i=this.toDataXCoord(e);this.doZoomXDates_(a,i)},Q.prototype.doZoomXDates_=function(t,e){var a=this,i=this.xAxisRange(),n=[t,e],r=this.getFunctionOption("zoomCallback");this.doAnimatedZoom(i,n,null,null,function(){r&&r.call(a,t,e,a.yAxisRanges())})},Q.prototype.doZoomY_=function(t,e){var a=this;this.currentZoomRectArgs_=null;for(var i=this.yAxisRanges(),n=[],r=0;r<this.axes_.length;r++){var o=this.toDataYCoord(t,r),l=this.toDataYCoord(e,r);n.push([l,o])}var h=this.getFunctionOption("zoomCallback");this.doAnimatedZoom(null,null,i,n,function(){if(h){var t=a.xAxisRange(),e=s(t,2),i=e[0],n=e[1];h.call(a,i,n,a.yAxisRanges())}})},Q.zoomAnimationFunction=function(t,e){return(1-Math.pow(1.5,-t))/(1-Math.pow(1.5,-e))},Q.prototype.resetZoom=function(){var t=this,e=this.isZoomed("x"),a=this.isZoomed("y"),i=e||a;if(this.clearSelection(),i){var n=this.xAxisExtremes(),r=s(n,2),o=r[0],l=r[1],h=this.getBooleanOption("animatedZooms"),u=this.getFunctionOption("zoomCallback");if(!h)return this.dateWindow_=null,this.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),this.drawGraph_(),void(u&&u.call(this,o,l,this.yAxisRanges()));var d=null,c=null,p=null,g=null;e&&(d=this.xAxisRange(),c=[o,l]),a&&(p=this.yAxisRanges(),g=this.yAxisExtremes()),this.doAnimatedZoom(d,c,p,g,function(){t.dateWindow_=null,t.axes_.forEach(function(t){t.valueRange&&delete t.valueRange}),u&&u.call(t,o,l,t.yAxisRanges())})}},Q.prototype.doAnimatedZoom=function(t,e,a,i,n){var r,o,s=this,l=this.getBooleanOption("animatedZooms")?Q.ANIMATION_STEPS:1,h=[],u=[];if(null!==t&&null!==e)for(r=1;r<=l;r++)o=Q.zoomAnimationFunction(r,l),h[r-1]=[t[0]*(1-o)+o*e[0],t[1]*(1-o)+o*e[1]];if(null!==a&&null!==i)for(r=1;r<=l;r++){o=Q.zoomAnimationFunction(r,l);for(var d=[],c=0;c<this.axes_.length;c++)d.push([a[c][0]*(1-o)+o*i[c][0],a[c][1]*(1-o)+o*i[c][1]]);u[r-1]=d}x.repeatAndCleanup(function(t){if(u.length)for(var e=0;e<s.axes_.length;e++){var a=u[t][e];s.axes_[e].valueRange=[a[0],a[1]]}h.length&&(s.dateWindow_=h[t]),s.drawGraph_()},l,Q.ANIMATION_DURATION/l,n)},Q.prototype.getArea=function(){return this.plotter_.area},Q.prototype.eventToDomCoords=function(t){if(t.offsetX&&t.offsetY)return[t.offsetX,t.offsetY];var e=x.findPos(this.mouseEventElement_);return[x.pageX(t)-e.x,x.pageY(t)-e.y]},Q.prototype.findClosestRow=function(t){for(var e=1/0,a=-1,i=this.layout_.points,n=0;n<i.length;n++)for(var r=i[n],o=r.length,s=0;s<o;s++){var l=r[s];if(x.isValidPoint(l,!0)){var h=Math.abs(l.canvasx-t);h<e&&(e=h,a=l.idx)}}return a},Q.prototype.findClosestPoint=function(t,e){for(var a,i,n,r,o,s,l,h=1/0,u=this.layout_.points.length-1;u>=0;--u)for(var d=this.layout_.points[u],c=0;c<d.length;++c)r=d[c],x.isValidPoint(r)&&(i=r.canvasx-t,n=r.canvasy-e,(a=i*i+n*n)<h&&(h=a,o=r,s=u,l=r.idx));return{row:l,seriesName:this.layout_.setNames[s],point:o}},Q.prototype.findStackedPoint=function(t,e){for(var a,i,n=this.findClosestRow(t),r=0;r<this.layout_.points.length;++r){var o=this.getLeftBoundary_(r),s=n-o,l=this.layout_.points[r];if(!(s>=l.length)){var h=l[s];if(x.isValidPoint(h)){var u=h.canvasy;if(t>h.canvasx&&s+1<l.length){var d=l[s+1];if(x.isValidPoint(d)){var c=d.canvasx-h.canvasx;if(c>0){var p=(t-h.canvasx)/c;u+=p*(d.canvasy-h.canvasy)}}}else if(t<h.canvasx&&s>0){var g=l[s-1];if(x.isValidPoint(g)){var c=h.canvasx-g.canvasx;if(c>0){var p=(h.canvasx-t)/c;u+=p*(g.canvasy-h.canvasy)}}}(0===r||u<e)&&(a=h,i=r)}}}return{row:n,seriesName:this.layout_.setNames[i],point:a}},Q.prototype.mouseMove_=function(t){var e=this.layout_.points;if(void 0!==e&&null!==e){var a=this.eventToDomCoords(t),i=a[0],n=a[1],r=this.getOption("highlightSeriesOpts"),o=!1;if(r&&!this.isSeriesLocked()){var s;s=this.getBooleanOption("stackedGraph")?this.findStackedPoint(i,n):this.findClosestPoint(i,n),o=this.setSelection(s.row,s.seriesName)}else{var l=this.findClosestRow(i);o=this.setSelection(l)}var h=this.getFunctionOption("highlightCallback");h&&o&&h.call(this,t,this.lastx_,this.selPoints_,this.lastRow_,this.highlightSet_)}},Q.prototype.getLeftBoundary_=function(t){if(this.boundaryIds_[t])return this.boundaryIds_[t][0];for(var e=0;e<this.boundaryIds_.length;e++)if(void 0!==this.boundaryIds_[e])return this.boundaryIds_[e][0];return 0},Q.prototype.animateSelection_=function(t){void 0===this.fadeLevel&&(this.fadeLevel=0),void 0===this.animateId&&(this.animateId=0);var e=this.fadeLevel,a=t<0?e:10-e;if(a<=0)return void(this.fadeLevel&&this.updateSelection_(1));var i=++this.animateId,n=this,r=function(){0!==n.fadeLevel&&t<0&&(n.fadeLevel=0,n.clearSelection())};x.repeatAndCleanup(function(e){n.animateId==i&&(n.fadeLevel+=t,0===n.fadeLevel?n.clearSelection():n.updateSelection_(n.fadeLevel/10))},a,30,r)},Q.prototype.updateSelection_=function(t){this.cascadeEvents_("select",{selectedRow:-1===this.lastRow_?void 0:this.lastRow_,selectedX:-1===this.lastx_?void 0:this.lastx_,selectedPoints:this.selPoints_});var e,a=this.canvas_ctx_;if(this.getOption("highlightSeriesOpts")){a.clearRect(0,0,this.width_,this.height_);var i=1-this.getNumericOption("highlightSeriesBackgroundAlpha"),n=x.toRGB_(this.getOption("highlightSeriesBackgroundColor"));if(i){if(void 0===t)return void this.animateSelection_(1);i*=t,a.fillStyle="rgba("+n.r+","+n.g+","+n.b+","+i+")",a.fillRect(0,0,this.width_,this.height_)}this.plotter_._renderLineChart(this.highlightSet_,a)}else if(this.previousVerticalX_>=0){var r=0,o=this.attr_("labels");for(e=1;e<o.length;e++){var s=this.getNumericOption("highlightCircleSize",o[e]);s>r&&(r=s)}var l=this.previousVerticalX_;a.clearRect(l-r-1,0,2*r+2,this.height_)}if(this.selPoints_.length>0){var h=this.selPoints_[0].canvasx;for(a.save(),e=0;e<this.selPoints_.length;e++){var u=this.selPoints_[e];if(!isNaN(u.canvasy)){var d=this.getNumericOption("highlightCircleSize",u.name),c=this.getFunctionOption("drawHighlightPointCallback",u.name),p=this.plotter_.colors[u.name];c||(c=x.Circles.DEFAULT),a.lineWidth=this.getNumericOption("strokeWidth",u.name),a.strokeStyle=p,a.fillStyle=p,c.call(this,this,u.name,a,h,u.canvasy,p,d,u.idx)}}a.restore(),this.previousVerticalX_=h}},Q.prototype.setSelection=function(t,e,a){this.selPoints_=[];var i=!1;if(!1!==t&&t>=0){t!=this.lastRow_&&(i=!0),this.lastRow_=t;for(var n=0;n<this.layout_.points.length;++n){var r=this.layout_.points[n],o=t-this.getLeftBoundary_(n);if(o>=0&&o<r.length&&r[o].idx==t){var s=r[o];null!==s.yval&&this.selPoints_.push(s)}else for(var l=0;l<r.length;++l){var s=r[l];if(s.idx==t){null!==s.yval&&this.selPoints_.push(s);break}}}}else this.lastRow_>=0&&(i=!0),this.lastRow_=-1;return this.selPoints_.length?this.lastx_=this.selPoints_[0].xval:this.lastx_=-1,void 0!==e&&(this.highlightSet_!==e&&(i=!0),this.highlightSet_=e),void 0!==a&&(this.lockedSet_=a),i&&this.updateSelection_(void 0),i},Q.prototype.mouseOut_=function(t){this.getFunctionOption("unhighlightCallback")&&this.getFunctionOption("unhighlightCallback").call(this,t),this.getBooleanOption("hideOverlayOnMouseOut")&&!this.lockedSet_&&this.clearSelection()},Q.prototype.clearSelection=function(){if(this.cascadeEvents_("deselect",{}),this.lockedSet_=!1,this.fadeLevel)return void this.animateSelection_(-1);this.canvas_ctx_.clearRect(0,0,this.width_,this.height_),this.fadeLevel=0,this.selPoints_=[],this.lastx_=-1,this.lastRow_=-1,this.highlightSet_=null},Q.prototype.getSelection=function(){if(!this.selPoints_||this.selPoints_.length<1)return-1;for(var t=0;t<this.layout_.points.length;t++)for(var e=this.layout_.points[t],a=0;a<e.length;a++)if(e[a].x==this.selPoints_[0].x)return e[a].idx;return-1},Q.prototype.getHighlightSeries=function(){return this.highlightSet_},Q.prototype.isSeriesLocked=function(){return this.lockedSet_},Q.prototype.loadedEvent_=function(t){this.rawData_=this.parseCSV_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_()},Q.prototype.addXTicks_=function(){var t;t=this.dateWindow_?[this.dateWindow_[0],this.dateWindow_[1]]:this.xAxisExtremes();var e=this.optionsViewForAxis_("x"),a=e("ticker")(t[0],t[1],this.plotter_.area.w,e,this);this.layout_.setXTicks(a)},Q.prototype.getHandlerClass_=function(){return this.attr_("dataHandler")?this.attr_("dataHandler"):this.fractions_?this.getBooleanOption("errorBars")?F.default:M.default:this.getBooleanOption("customBars")?P.default:this.getBooleanOption("errorBars")?T.default:E.default},Q.prototype.predraw_=function(){var t=new Date;this.dataHandler_=new(this.getHandlerClass_()),this.layout_.computePlotArea(),this.computeYAxes_(),this.is_initial_draw_||(this.canvas_ctx_.restore(),this.hidden_ctx_.restore()),this.canvas_ctx_.save(),this.hidden_ctx_.save(),this.plotter_=new d.default(this,this.hidden_,this.hidden_ctx_,this.layout_),this.createRollInterface_(),this.cascadeEvents_("predraw"),this.rolledSeries_=[null];for(var e=1;e<this.numColumns();e++){var a=this.dataHandler_.extractSeries(this.rawData_,e,this.attributes_);this.rollPeriod_>1&&(a=this.dataHandler_.rollingAverage(a,this.rollPeriod_,this.attributes_)),this.rolledSeries_.push(a)}this.drawGraph_();var i=new Date;this.drawingTimeMs_=i-t},Q.PointType=void 0,Q.stackPoints_=function(t,e,a,i){for(var n=null,r=null,o=null,s=-1,l=0;l<t.length;++l){var h=t[l],u=h.xval;void 0===e[u]&&(e[u]=0);var d=h.yval;isNaN(d)||null===d?"none"==i?d=0:(!function(e){if(!(s>=e))for(var a=e;a<t.length;++a)if(o=null,!isNaN(t[a].yval)&&null!==t[a].yval){s=a,o=t[a];break}}(l),d=r&&o&&"none"!=i?r.yval+(o.yval-r.yval)*((u-r.xval)/(o.xval-r.xval)):r&&"all"==i?r.yval:o&&"all"==i?o.yval:0):r=h;var c=e[u];n!=u&&(c+=d,e[u]=c),n=u,h.yval_stacked=c,c>a[1]&&(a[1]=c),c<a[0]&&(a[0]=c)}},Q.prototype.gatherDatasets_=function(t,e){var a,i,n,r,o,s,l=[],h=[],u=[],d={},c=t.length-1;for(a=c;a>=1;a--)if(this.visibility()[a-1]){if(e){s=t[a];var p=e[0],g=e[1];for(n=null,r=null,i=0;i<s.length;i++)s[i][0]>=p&&null===n&&(n=i),s[i][0]<=g&&(r=i);null===n&&(n=0);for(var f=n,v=!0;v&&f>0;)f--,v=null===s[f][1];null===r&&(r=s.length-1);var _=r;for(v=!0;v&&_<s.length-1;)_++,v=null===s[_][1];f!==n&&(n=f),_!==r&&(r=_),l[a-1]=[n,r],s=s.slice(n,r+1)}else s=t[a],l[a-1]=[0,s.length-1];var y=this.attr_("labels")[a],x=this.dataHandler_.getExtremeYValues(s,e,this.getBooleanOption("stepPlot",y)),m=this.dataHandler_.seriesToPoints(s,y,l[a-1][0]);this.getBooleanOption("stackedGraph")&&(o=this.attributes_.axisForSeries(y),void 0===u[o]&&(u[o]=[]),Q.stackPoints_(m,u[o],x,this.getBooleanOption("stackedGraphNaNFill"))),d[y]=x,h[a]=m}return{points:h,extremes:d,boundaryIds:l}},Q.prototype.drawGraph_=function(){var t=new Date,e=this.is_initial_draw_;this.is_initial_draw_=!1,this.layout_.removeAllDatasets(),this.setColors_(),this.attrs_.pointSize=.5*this.getNumericOption("highlightCircleSize");var a=this.gatherDatasets_(this.rolledSeries_,this.dateWindow_),i=a.points,n=a.extremes;this.boundaryIds_=a.boundaryIds,this.setIndexByName_={};for(var r=this.attr_("labels"),o=0,s=1;s<i.length;s++)this.visibility()[s-1]&&(this.layout_.addDataset(r[s],i[s]),this.datasetIndex_[s]=o++);for(var s=0;s<r.length;s++)this.setIndexByName_[r[s]]=s;if(this.computeYAxisRanges_(n),this.layout_.setYAxes(this.axes_),this.addXTicks_(),this.layout_.evaluate(),this.renderGraph_(e),this.getStringOption("timingName")){var l=new Date;console.log(this.getStringOption("timingName")+" - drawGraph: "+(l-t)+"ms")}},Q.prototype.renderGraph_=function(t){this.cascadeEvents_("clearChart"),this.plotter_.clear();var e=this.getFunctionOption("underlayCallback");e&&e.call(this,this.hidden_ctx_,this.layout_.getPlotArea(),this,this);var a={canvas:this.hidden_,drawingContext:this.hidden_ctx_};this.cascadeEvents_("willDrawChart",a),this.plotter_.render(),this.cascadeEvents_("didDrawChart",a),this.lastRow_=-1,this.canvas_.getContext("2d").clearRect(0,0,this.width_,this.height_);var i=this.getFunctionOption("drawCallback");if(null!==i&&i.call(this,this,t),t)for(this.readyFired_=!0;this.readyFns_.length>0;){var n=this.readyFns_.pop();n(this)}},Q.prototype.computeYAxes_=function(){var t,e,a;for(this.axes_=[],t=0;t<this.attributes_.numAxes();t++)e={g:this},x.update(e,this.attributes_.axisOptions(t)),this.axes_[t]=e;for(t=0;t<this.axes_.length;t++)if(0===t)e=this.optionsViewForAxis_("y"+(t?"2":"")),(a=e("valueRange"))&&(this.axes_[t].valueRange=a);else{var i=this.user_attrs_.axes;i&&i.y2&&(a=i.y2.valueRange)&&(this.axes_[t].valueRange=a)}},Q.prototype.numAxes=function(){return this.attributes_.numAxes()},Q.prototype.axisPropertiesForSeries=function(t){return this.axes_[this.attributes_.axisForSeries(t)]},Q.prototype.computeYAxisRanges_=function(t){for(var e,a,i,n,r,o=function(t){return isNaN(parseFloat(t))},s=this.attributes_.numAxes(),l=0;l<s;l++){var h=this.axes_[l],u=this.attributes_.getForAxis("logscale",l),d=this.attributes_.getForAxis("includeZero",l),c=this.attributes_.getForAxis("independentTicks",l);i=this.attributes_.seriesForAxis(l),e=!0,n=.1;var p=this.getNumericOption("yRangePad");if(null!==p&&(e=!1,n=p/this.plotter_.area.h),0===i.length)h.extremeRange=[0,1];else{for(var g,f,v=1/0,_=-1/0,y=0;y<i.length;y++)t.hasOwnProperty(i[y])&&(g=t[i[y]][0],null!==g&&(v=Math.min(g,v)),null!==(f=t[i[y]][1])&&(_=Math.max(f,_)));d&&!u&&(v>0&&(v=0),_<0&&(_=0)),v==1/0&&(v=0),_==-1/0&&(_=1),a=_-v,0===a&&(0!==_?a=Math.abs(_):(_=1,a=1));var m=_,b=v;e&&(u?(m=_+n*a,b=v):(m=_+n*a,b=v-n*a,b<0&&v>=0&&(b=0),m>0&&_<=0&&(m=0))),h.extremeRange=[b,m]}if(h.valueRange){var w=o(h.valueRange[0])?h.extremeRange[0]:h.valueRange[0],A=o(h.valueRange[1])?h.extremeRange[1]:h.valueRange[1];h.computedValueRange=[w,A]}else h.computedValueRange=h.extremeRange;if(!e)if(w=h.computedValueRange[0],A=h.computedValueRange[1],w===A&&(w-=.5,A+=.5),u){var O=n/(2*n-1),D=(n-1)/(2*n-1);h.computedValueRange[0]=x.logRangeFraction(w,A,O),h.computedValueRange[1]=x.logRangeFraction(w,A,D)}else a=A-w,h.computedValueRange[0]=w-a*n,h.computedValueRange[1]=A+a*n;if(c){h.independentTicks=c;var E=this.optionsViewForAxis_("y"+(l?"2":"")),L=E("ticker");h.ticks=L(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,E,this),r||(r=h)}}if(void 0===r)throw'Configuration Error: At least one axis has to have the "independentTicks" option activated.';for(var l=0;l<s;l++){var h=this.axes_[l];if(!h.independentTicks){for(var E=this.optionsViewForAxis_("y"+(l?"2":"")),L=E("ticker"),T=r.ticks,S=r.computedValueRange[1]-r.computedValueRange[0],P=h.computedValueRange[1]-h.computedValueRange[0],C=[],M=0;M<T.length;M++){var N=(T[M].v-r.computedValueRange[0])/S,F=h.computedValueRange[0]+N*P;C.push(F)}h.ticks=L(h.computedValueRange[0],h.computedValueRange[1],this.plotter_.area.h,E,this,C)}}},Q.prototype.detectTypeFromString_=function(t){var e=!1,a=t.indexOf("-");a>0&&"e"!=t[a-1]&&"E"!=t[a-1]||t.indexOf("/")>=0||isNaN(parseFloat(t))?e=!0:8==t.length&&t>"19700101"&&t<"20371231"&&(e=!0),this.setXAxisOptions_(e)},Q.prototype.setXAxisOptions_=function(t){t?(this.attrs_.xValueParser=x.dateParser,this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=_.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter):(this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=_.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter)},Q.prototype.parseCSV_=function(t){var e,a,i=[],n=x.detectLineDelimiter(t),r=t.split(n||"\n"),o=this.getStringOption("delimiter");-1==r[0].indexOf(o)&&r[0].indexOf("\t")>=0&&(o="\t");var s=0;"labels"in this.user_attrs_||(s=1,this.attrs_.labels=r[0].split(o),this.attributes_.reparseSeries());for(var l,h=!1,u=this.attr_("labels").length,d=!1,c=s;c<r.length;c++){var p=r[c];if(c,0!==p.length&&"#"!=p[0]){var g=p.split(o);if(!(g.length<2)){var f=[];if(h||(this.detectTypeFromString_(g[0]),l=this.getFunctionOption("xValueParser"),h=!0),f[0]=l(g[0],this),this.fractions_)for(a=1;a<g.length;a++)e=g[a].split("/"),2!=e.length?(console.error('Expected fractional "num/den" values in CSV data but found a value \''+g[a]+"' on line "+(1+c)+" ('"+p+"') which is not of this form."),f[a]=[0,0]):f[a]=[x.parseFloat_(e[0],c,p),x.parseFloat_(e[1],c,p)];else if(this.getBooleanOption("errorBars"))for(g.length%2!=1&&console.error("Expected alternating (value, stdev.) pairs in CSV data but line "+(1+c)+" has an odd number of values ("+(g.length-1)+"): '"+p+"'"),a=1;a<g.length;a+=2)f[(a+1)/2]=[x.parseFloat_(g[a],c,p),x.parseFloat_(g[a+1],c,p)];else if(this.getBooleanOption("customBars"))for(a=1;a<g.length;a++){var v=g[a];/^ *$/.test(v)?f[a]=[null,null,null]:(e=v.split(";"),3==e.length?f[a]=[x.parseFloat_(e[0],c,p),x.parseFloat_(e[1],c,p),x.parseFloat_(e[2],c,p)]:console.warn('When using customBars, values must be either blank or "low;center;high" tuples (got "'+v+'" on line '+(1+c)))}else for(a=1;a<g.length;a++)f[a]=x.parseFloat_(g[a],c,p);if(i.length>0&&f[0]<i[i.length-1][0]&&(d=!0),f.length!=u&&console.error("Number of columns in line "+c+" ("+f.length+") does not agree with number of labels ("+u+") "+p),0===c&&this.attr_("labels")){var _=!0;for(a=0;_&&a<f.length;a++)f[a]&&(_=!1);if(_){console.warn("The dygraphs 'labels' option is set, but the first row of CSV data ('"+p+"') appears to also contain labels. Will drop the CSV labels and use the option labels.");continue}}i.push(f)}}}return d&&(console.warn("CSV is out of order; order it correctly to speed loading."),i.sort(function(t,e){return t[0]-e[0]})),i},Q.prototype.parseArray_=function(t){if(0===t.length)return console.error("Can't plot empty data set"),null;if(0===t[0].length)return console.error("Data set cannot contain an empty row"),null;o(t);var e;if(null===this.attr_("labels")){for(console.warn("Using default labels. Set labels explicitly via 'labels' in the options parameter"),this.attrs_.labels=["X"],e=1;e<t[0].length;e++)this.attrs_.labels.push("Y"+e);this.attributes_.reparseSeries()}else{var a=this.attr_("labels");if(a.length!=t[0].length)return console.error("Mismatch between number of labels ("+a+") and number of columns in array ("+t[0].length+")"),null}if(x.isDateLike(t[0][0])){this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=_.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter;var i=x.clone(t);for(e=0;e<t.length;e++){if(0===i[e].length)return console.error("Row "+(1+e)+" of data is empty"),null;if(null===i[e][0]||"function"!=typeof i[e][0].getTime||isNaN(i[e][0].getTime()))return console.error("x value in row "+(1+e)+" is not a Date"),null;i[e][0]=i[e][0].getTime()}return i}return this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=_.numericTicks,this.attrs_.axes.x.axisLabelFormatter=x.numberAxisLabelFormatter,t},Q.prototype.parseDataTable_=function(t){var e=t.getNumberOfColumns(),a=t.getNumberOfRows(),i=t.getColumnType(0);if("date"==i||"datetime"==i)this.attrs_.xValueParser=x.dateParser,this.attrs_.axes.x.valueFormatter=x.dateValueFormatter,this.attrs_.axes.x.ticker=_.dateTicker,this.attrs_.axes.x.axisLabelFormatter=x.dateAxisLabelFormatter;else{if("number"!=i)throw new Error("only 'date', 'datetime' and 'number' types are supported for column 1 of DataTable input (Got '"+i+"')");this.attrs_.xValueParser=function(t){return parseFloat(t)},this.attrs_.axes.x.valueFormatter=function(t){return t},this.attrs_.axes.x.ticker=_.numericTicks,this.attrs_.axes.x.axisLabelFormatter=this.attrs_.axes.x.valueFormatter}var n,r,o=[],s={},l=!1;for(n=1;n<e;n++){var h=t.getColumnType(n);if("number"==h)o.push(n);else{if("string"!=h||!this.getBooleanOption("displayAnnotations"))throw new Error("Only 'number' is supported as a dependent type with Gviz. 'string' is only supported if displayAnnotations is true");var u=o[o.length-1];s.hasOwnProperty(u)?s[u].push(n):s[u]=[n],l=!0}}var d=[t.getColumnLabel(0)];for(n=0;n<o.length;n++)d.push(t.getColumnLabel(o[n])),this.getBooleanOption("errorBars")&&(n+=1);this.attrs_.labels=d,e=d.length;var c=[],p=!1,g=[];for(n=0;n<a;n++){var f=[];if(void 0!==t.getValue(n,0)&&null!==t.getValue(n,0)){if("date"==i||"datetime"==i?f.push(t.getValue(n,0).getTime()):f.push(t.getValue(n,0)),this.getBooleanOption("errorBars"))for(r=0;r<e-1;r++)f.push([t.getValue(n,1+2*r),t.getValue(n,2+2*r)]);else{for(r=0;r<o.length;r++){var v=o[r];if(f.push(t.getValue(n,v)),l&&s.hasOwnProperty(v)&&null!==t.getValue(n,s[v][0])){var y={};y.series=t.getColumnLabel(v),y.xval=f[0],y.shortText=function(t){var e=String.fromCharCode(65+t%26);for(t=Math.floor(t/26);t>0;)e=String.fromCharCode(65+(t-1)%26)+e.toLowerCase(),t=Math.floor((t-1)/26);return e}(g.length),y.text="";for(var m=0;m<s[v].length;m++)m&&(y.text+="\n"),y.text+=t.getValue(n,s[v][m]);g.push(y)}}for(r=0;r<f.length;r++)isFinite(f[r])||(f[r]=null)}c.length>0&&f[0]<c[c.length-1][0]&&(p=!0),c.push(f)}else console.warn("Ignoring row "+n+" of DataTable because of undefined or null first column.")}p&&(console.warn("DataTable is out of order; order it correctly to speed loading."),c.sort(function(t,e){return t[0]-e[0]})),this.rawData_=c,g.length>0&&this.setAnnotations(g,!0),this.attributes_.reparseSeries()},Q.prototype.cascadeDataDidUpdateEvent_=function(){this.cascadeEvents_("dataDidUpdate",{})},Q.prototype.start_=function(){var t=this.file_;if("function"==typeof t&&(t=t()),x.isArrayLike(t))this.rawData_=this.parseArray_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("object"==typeof t&&"function"==typeof t.getColumnRange)this.parseDataTable_(t),this.cascadeDataDidUpdateEvent_(),this.predraw_();else if("string"==typeof t){var e=x.detectLineDelimiter(t);if(e)this.loadedEvent_(t);else{var a;a=window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP");var i=this;a.onreadystatechange=function(){4==a.readyState&&(200!==a.status&&0!==a.status||i.loadedEvent_(a.responseText))},a.open("GET",t,!0),a.send(null)}}else console.error("Unknown data format: "+typeof t)},Q.prototype.updateOptions=function(t,e){void 0===e&&(e=!1);var a=t.file,i=Q.copyUserAttrs_(t);"rollPeriod"in i&&(this.rollPeriod_=i.rollPeriod),"dateWindow"in i&&(this.dateWindow_=i.dateWindow);var n=x.isPixelChangingOptionList(this.attr_("labels"),i);x.updateDeep(this.user_attrs_,i),this.attributes_.reparseSeries(),a?(this.cascadeEvents_("dataWillUpdate",{}),this.file_=a,e||this.start_()):e||(n?this.predraw_():this.renderGraph_(!1))},Q.copyUserAttrs_=function(t){var e={};for(var a in t)t.hasOwnProperty(a)&&"file"!=a&&t.hasOwnProperty(a)&&(e[a]=t[a]);return e},Q.prototype.resize=function(t,e){if(!this.resize_lock){this.resize_lock=!0,null===t!=(null===e)&&(console.warn("Dygraph.resize() should be called with zero parameters or two non-NULL parameters. Pretending it was zero."),t=e=null);var a=this.width_,i=this.height_;t?(this.maindiv_.style.width=t+"px",this.maindiv_.style.height=e+"px",this.width_=t,this.height_=e):(this.width_=this.maindiv_.clientWidth,this.height_=this.maindiv_.clientHeight),a==this.width_&&i==this.height_||(this.resizeElements_(),this.predraw_()),this.resize_lock=!1}},Q.prototype.adjustRoll=function(t){this.rollPeriod_=t,this.predraw_()},Q.prototype.visibility=function(){for(this.getOption("visibility")||(this.attrs_.visibility=[]);this.getOption("visibility").length<this.numColumns()-1;)this.attrs_.visibility.push(!0);return this.getOption("visibility")},Q.prototype.setVisibility=function(t,e){var a=this.visibility(),i=!1;if(Array.isArray(t)||(null!==t&&"object"==typeof t?i=!0:t=[t]),i)for(var n in t)t.hasOwnProperty(n)&&(n<0||n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]);else for(var n=0;n<t.length;n++)"boolean"==typeof t[n]?n>=a.length?console.warn("Invalid series number in setVisibility: "+n):a[n]=t[n]:t[n]<0||t[n]>=a.length?console.warn("Invalid series number in setVisibility: "+t[n]):a[t[n]]=e;this.predraw_()},Q.prototype.size=function(){return{width:this.width_,height:this.height_}},Q.prototype.setAnnotations=function(t,e){if(this.annotations_=t,!this.layout_)return void console.warn("Tried to setAnnotations before dygraph was ready. Try setting them in a ready() block. See dygraphs.com/tests/annotation.html");this.layout_.setAnnotations(this.annotations_),e||this.predraw_()},Q.prototype.annotations=function(){return this.annotations_},Q.prototype.getLabels=function(){var t=this.attr_("labels");return t?t.slice():null},Q.prototype.indexFromSetName=function(t){return this.setIndexByName_[t]},Q.prototype.getRowForX=function(t){for(var e=0,a=this.numRows()-1;e<=a;){var i=a+e>>1,n=this.getValue(i,0);if(n<t)e=i+1;else if(n>t)a=i-1;else{if(e==i)return i;a=i}}return null},Q.prototype.ready=function(t){this.is_initial_draw_?this.readyFns_.push(t):t.call(this,this)},Q.prototype.addAndTrackEvent=function(t,e,a){x.addEvent(t,e,a),this.registeredEvents_.push({elem:t,type:e,fn:a})},Q.prototype.removeTrackedEvents_=function(){if(this.registeredEvents_)for(var t=0;t<this.registeredEvents_.length;t++){var e=this.registeredEvents_[t];x.removeEvent(e.elem,e.type,e.fn)}this.registeredEvents_=[]},Q.PLUGINS=[U.default,X.default,j.default,Z.default,H.default,G.default],Q.GVizChart=q.default,Q.DASHED_LINE=x.DASHED_LINE,Q.DOT_DASH_LINE=x.DOT_DASH_LINE,Q.dateAxisLabelFormatter=x.dateAxisLabelFormatter,Q.toRGB_=x.toRGB_,Q.findPos=x.findPos,Q.pageX=x.pageX,Q.pageY=x.pageY,Q.dateString_=x.dateString_,Q.defaultInteractionModel=f.default.defaultModel,Q.nonInteractiveModel=Q.nonInteractiveModel_=f.default.nonInteractiveModel_,Q.Circles=x.Circles,Q.Plugins={Legend:U.default,Axes:X.default,Annotations:H.default,ChartLabels:Z.default,Grid:G.default,RangeSelector:j.default},Q.DataHandlers={DefaultHandler:E.default,BarsHandler:R.default,CustomBarsHandler:P.default,DefaultFractionHandler:M.default,ErrorBarsHandler:T.default,FractionsBarsHandler:F.default},Q.startPan=f.default.startPan,Q.startZoom=f.default.startZoom,Q.movePan=f.default.movePan,Q.moveZoom=f.default.moveZoom,Q.endPan=f.default.endPan,Q.endZoom=f.default.endZoom,Q.numericLinearTicks=_.numericLinearTicks,Q.numericTicks=_.numericTicks,Q.dateTicker=_.dateTicker,Q.Granularity=_.Granularity,Q.getDateAxis=_.getDateAxis,Q.floatFormat=x.floatFormat,a.default=Q,e.exports=a.default}).call(this,t("_process"))},{"./datahandler/bars":5,"./datahandler/bars-custom":2,"./datahandler/bars-error":3,"./datahandler/bars-fractions":4,"./datahandler/default":8,"./datahandler/default-fractions":7,"./dygraph-canvas":9,"./dygraph-default-attrs":10,"./dygraph-gviz":11,"./dygraph-interaction-model":12,"./dygraph-layout":13,"./dygraph-options":15,"./dygraph-options-reference":14,"./dygraph-tickers":16,"./dygraph-utils":17,"./iframe-tarp":19,"./plugins/annotations":20,"./plugins/axes":21,"./plugins/chart-labels":22,"./plugins/grid":23,"./plugins/legend":24,"./plugins/range-selector":25,_process:1}],19:[function(t,e,a){"use strict";function i(){this.tarps=[]}Object.defineProperty(a,"__esModule",{value:!0});var n=t("./dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n);i.prototype.cover=function(){for(var t=document.getElementsByTagName("iframe"),e=0;e<t.length;e++){var a=t[e],i=r.findPos(a),n=i.x,o=i.y,s=a.offsetWidth,l=a.offsetHeight,h=document.createElement("div");h.style.position="absolute",h.style.left=n+"px",h.style.top=o+"px",h.style.width=s+"px",h.style.height=l+"px",h.style.zIndex=999,document.body.appendChild(h),this.tarps.push(h)}},i.prototype.uncover=function(){for(var t=0;t<this.tarps.length;t++)this.tarps[t].parentNode.removeChild(this.tarps[t]);this.tarps=[]},a.default=i,e.exports=a.default},{"./dygraph-utils":17}],20:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.annotations_=[]};i.prototype.toString=function(){return"Annotations Plugin"},i.prototype.activate=function(t){return{clearChart:this.clearChart,didDrawChart:this.didDrawChart}},i.prototype.detachLabels=function(){for(var t=0;t<this.annotations_.length;t++){var e=this.annotations_[t];e.parentNode&&e.parentNode.removeChild(e),this.annotations_[t]=null}this.annotations_=[]},i.prototype.clearChart=function(t){this.detachLabels()},i.prototype.didDrawChart=function(t){var e=t.dygraph,a=e.layout_.annotated_points;if(a&&0!==a.length)for(var i=t.canvas.parentNode,n=function(t,a,i){return function(n){var r=i.annotation;r.hasOwnProperty(t)?r[t](r,i,e,n):e.getOption(a)&&e.getOption(a)(r,i,e,n)}},r=t.dygraph.getArea(),o={},s=0;s<a.length;s++){var l=a[s];if(!(l.canvasx<r.x||l.canvasx>r.x+r.w||l.canvasy<r.y||l.canvasy>r.y+r.h)){var h=l.annotation,u=6;h.hasOwnProperty("tickHeight")&&(u=h.tickHeight);var d=document.createElement("div");d.style.fontSize=e.getOption("axisLabelFontSize")+"px" +;var c="dygraph-annotation";h.hasOwnProperty("icon")||(c+=" dygraphDefaultAnnotation dygraph-default-annotation"),h.hasOwnProperty("cssClass")&&(c+=" "+h.cssClass),d.className=c;var p=h.hasOwnProperty("width")?h.width:16,g=h.hasOwnProperty("height")?h.height:16;if(h.hasOwnProperty("icon")){var f=document.createElement("img");f.src=h.icon,f.width=p,f.height=g,d.appendChild(f)}else l.annotation.hasOwnProperty("shortText")&&d.appendChild(document.createTextNode(l.annotation.shortText));var v=l.canvasx-p/2;d.style.left=v+"px";var _=0;if(h.attachAtBottom){var y=r.y+r.h-g-u;o[v]?y-=o[v]:o[v]=0,o[v]+=u+g,_=y}else _=l.canvasy-g-u;d.style.top=_+"px",d.style.width=p+"px",d.style.height=g+"px",d.title=l.annotation.text,d.style.color=e.colorsMap_[l.name],d.style.borderColor=e.colorsMap_[l.name],h.div=d,e.addAndTrackEvent(d,"click",n("clickHandler","annotationClickHandler",l)),e.addAndTrackEvent(d,"mouseover",n("mouseOverHandler","annotationMouseOverHandler",l)),e.addAndTrackEvent(d,"mouseout",n("mouseOutHandler","annotationMouseOutHandler",l)),e.addAndTrackEvent(d,"dblclick",n("dblClickHandler","annotationDblClickHandler",l)),i.appendChild(d),this.annotations_.push(d);var x=t.drawingContext;if(x.save(),x.strokeStyle=h.hasOwnProperty("tickColor")?h.tickColor:e.colorsMap_[l.name],x.lineWidth=h.hasOwnProperty("tickWidth")?h.tickWidth:e.getOption("strokeWidth"),x.beginPath(),h.attachAtBottom){var y=_+g;x.moveTo(l.canvasx,y),x.lineTo(l.canvasx,y+u)}else x.moveTo(l.canvasx,l.canvasy),x.lineTo(l.canvasx,l.canvasy-2-u);x.closePath(),x.stroke(),x.restore()}}},i.prototype.destroy=function(){this.detachLabels()},a.default=i,e.exports=a.default},{}],21:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=t("../dygraph-utils"),n=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(i),r=function(){this.xlabels_=[],this.ylabels_=[]};r.prototype.toString=function(){return"Axes Plugin"},r.prototype.activate=function(t){return{layout:this.layout,clearChart:this.clearChart,willDrawChart:this.willDrawChart}},r.prototype.layout=function(t){var e=t.dygraph;if(e.getOptionForAxis("drawAxis","y")){var a=e.getOptionForAxis("axisLabelWidth","y")+2*e.getOptionForAxis("axisTickSize","y");t.reserveSpaceLeft(a)}if(e.getOptionForAxis("drawAxis","x")){var i;i=e.getOption("xAxisHeight")?e.getOption("xAxisHeight"):e.getOptionForAxis("axisLabelFontSize","x")+2*e.getOptionForAxis("axisTickSize","x"),t.reserveSpaceBottom(i)}if(2==e.numAxes()){if(e.getOptionForAxis("drawAxis","y2")){var a=e.getOptionForAxis("axisLabelWidth","y2")+2*e.getOptionForAxis("axisTickSize","y2");t.reserveSpaceRight(a)}}else e.numAxes()>2&&e.error("Only two y-axes are supported at this time. (Trying to use "+e.numAxes()+")")},r.prototype.detachLabels=function(){function t(t){for(var e=0;e<t.length;e++){var a=t[e];a.parentNode&&a.parentNode.removeChild(a)}}t(this.xlabels_),t(this.ylabels_),this.xlabels_=[],this.ylabels_=[]},r.prototype.clearChart=function(t){this.detachLabels()},r.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i=this,r=t.dygraph;if(r.getOptionForAxis("drawAxis","x")||r.getOptionForAxis("drawAxis","y")||r.getOptionForAxis("drawAxis","y2")){var o,s,l,h=t.drawingContext,u=t.canvas.parentNode,d=r.width_,c=r.height_,p=function(t){return{position:"absolute",fontSize:r.getOptionForAxis("axisLabelFontSize",t)+"px",width:r.getOptionForAxis("axisLabelWidth",t)+"px"}},g={x:p("x"),y:p("y"),y2:p("y2")},f=function(t,e,a){var i=document.createElement("div"),r=g["y2"==a?"y2":e];n.update(i.style,r);var o=document.createElement("div");return o.className="dygraph-axis-label dygraph-axis-label-"+e+(a?" dygraph-axis-label-"+a:""),o.innerHTML=t,i.appendChild(o),i};h.save();var v=r.layout_,_=t.dygraph.plotter_.area,y=function(t){return function(e){return r.getOptionForAxis(e,t)}};if(r.getOptionForAxis("drawAxis","y")){if(v.yticks&&v.yticks.length>0){var x=r.numAxes(),m=[y("y"),y("y2")];v.yticks.forEach(function(t){if(void 0!==t.label){s=_.x;var e="y1",a=m[0];1==t.axis&&(s=_.x+_.w,-1,e="y2",a=m[1]);var n=a("axisLabelFontSize");l=_.y+t.pos*_.h,o=f(t.label,"y",2==x?e:null);var r=l-n/2;r<0&&(r=0),r+n+3>c?o.style.bottom="0":o.style.top=r+"px",0===t.axis?(o.style.left=_.x-a("axisLabelWidth")-a("axisTickSize")+"px",o.style.textAlign="right"):1==t.axis&&(o.style.left=_.x+_.w+a("axisTickSize")+"px",o.style.textAlign="left"),o.style.width=a("axisLabelWidth")+"px",u.appendChild(o),i.ylabels_.push(o)}});var b=this.ylabels_[0],w=r.getOptionForAxis("axisLabelFontSize","y");parseInt(b.style.top,10)+w>c-w&&(b.style.top=parseInt(b.style.top,10)-w/2+"px")}var A;if(r.getOption("drawAxesAtZero")){var O=r.toPercentXCoord(0);(O>1||O<0||isNaN(O))&&(O=0),A=e(_.x+O*_.w)}else A=e(_.x);h.strokeStyle=r.getOptionForAxis("axisLineColor","y"),h.lineWidth=r.getOptionForAxis("axisLineWidth","y"),h.beginPath(),h.moveTo(A,a(_.y)),h.lineTo(A,a(_.y+_.h)),h.closePath(),h.stroke(),2==r.numAxes()&&(h.strokeStyle=r.getOptionForAxis("axisLineColor","y2"),h.lineWidth=r.getOptionForAxis("axisLineWidth","y2"),h.beginPath(),h.moveTo(a(_.x+_.w),a(_.y)),h.lineTo(a(_.x+_.w),a(_.y+_.h)),h.closePath(),h.stroke())}if(r.getOptionForAxis("drawAxis","x")){if(v.xticks){var D=y("x");v.xticks.forEach(function(t){if(void 0!==t.label){s=_.x+t.pos*_.w,l=_.y+_.h,o=f(t.label,"x"),o.style.textAlign="center",o.style.top=l+D("axisTickSize")+"px";var e=s-D("axisLabelWidth")/2;e+D("axisLabelWidth")>d&&(e=d-D("axisLabelWidth"),o.style.textAlign="right"),e<0&&(e=0,o.style.textAlign="left"),o.style.left=e+"px",o.style.width=D("axisLabelWidth")+"px",u.appendChild(o),i.xlabels_.push(o)}})}h.strokeStyle=r.getOptionForAxis("axisLineColor","x"),h.lineWidth=r.getOptionForAxis("axisLineWidth","x"),h.beginPath();var E;if(r.getOption("drawAxesAtZero")){var O=r.toPercentYCoord(0,0);(O>1||O<0)&&(O=1),E=a(_.y+O*_.h)}else E=a(_.y+_.h);h.moveTo(e(_.x),E),h.lineTo(e(_.x+_.w),E),h.closePath(),h.stroke()}h.restore()}},a.default=r,e.exports=a.default},{"../dygraph-utils":17}],22:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};i.prototype.toString=function(){return"ChartLabels Plugin"},i.prototype.activate=function(t){return{layout:this.layout,didDrawChart:this.didDrawChart}};var n=function(t){var e=document.createElement("div");return e.style.position="absolute",e.style.left=t.x+"px",e.style.top=t.y+"px",e.style.width=t.w+"px",e.style.height=t.h+"px",e};i.prototype.detachLabels_=function(){for(var t=[this.title_div_,this.xlabel_div_,this.ylabel_div_,this.y2label_div_],e=0;e<t.length;e++){var a=t[e];a&&(a.parentNode&&a.parentNode.removeChild(a))}this.title_div_=null,this.xlabel_div_=null,this.ylabel_div_=null,this.y2label_div_=null};var r=function(t,e,a,i,n){var r=document.createElement("div");r.style.position="absolute",r.style.left=1==a?"0px":e.x+"px",r.style.top=e.y+"px",r.style.width=e.w+"px",r.style.height=e.h+"px",r.style.fontSize=t.getOption("yLabelWidth")-2+"px";var o=document.createElement("div");o.style.position="absolute",o.style.width=e.h+"px",o.style.height=e.w+"px",o.style.top=e.h/2-e.w/2+"px",o.style.left=e.w/2-e.h/2+"px",o.className="dygraph-label-rotate-"+(1==a?"right":"left");var s=document.createElement("div");return s.className=i,s.innerHTML=n,o.appendChild(s),r.appendChild(o),r};i.prototype.layout=function(t){this.detachLabels_();var e=t.dygraph,a=t.chart_div;if(e.getOption("title")){var i=t.reserveSpaceTop(e.getOption("titleHeight"));this.title_div_=n(i),this.title_div_.style.fontSize=e.getOption("titleHeight")-8+"px";var o=document.createElement("div");o.className="dygraph-label dygraph-title",o.innerHTML=e.getOption("title"),this.title_div_.appendChild(o),a.appendChild(this.title_div_)}if(e.getOption("xlabel")){var s=t.reserveSpaceBottom(e.getOption("xLabelHeight"));this.xlabel_div_=n(s),this.xlabel_div_.style.fontSize=e.getOption("xLabelHeight")-2+"px";var o=document.createElement("div");o.className="dygraph-label dygraph-xlabel",o.innerHTML=e.getOption("xlabel"),this.xlabel_div_.appendChild(o),a.appendChild(this.xlabel_div_)}if(e.getOption("ylabel")){var l=t.reserveSpaceLeft(0);this.ylabel_div_=r(e,l,1,"dygraph-label dygraph-ylabel",e.getOption("ylabel")),a.appendChild(this.ylabel_div_)}if(e.getOption("y2label")&&2==e.numAxes()){var h=t.reserveSpaceRight(0);this.y2label_div_=r(e,h,2,"dygraph-label dygraph-y2label",e.getOption("y2label")),a.appendChild(this.y2label_div_)}},i.prototype.didDrawChart=function(t){var e=t.dygraph;this.title_div_&&(this.title_div_.children[0].innerHTML=e.getOption("title")),this.xlabel_div_&&(this.xlabel_div_.children[0].innerHTML=e.getOption("xlabel")),this.ylabel_div_&&(this.ylabel_div_.children[0].children[0].innerHTML=e.getOption("ylabel")),this.y2label_div_&&(this.y2label_div_.children[0].children[0].innerHTML=e.getOption("y2label"))},i.prototype.clearChart=function(){},i.prototype.destroy=function(){this.detachLabels_()},a.default=i,e.exports=a.default},{}],23:[function(t,e,a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});var i=function(){};i.prototype.toString=function(){return"Gridline Plugin"},i.prototype.activate=function(t){return{willDrawChart:this.willDrawChart}},i.prototype.willDrawChart=function(t){function e(t){return Math.round(t)+.5}function a(t){return Math.round(t)-.5}var i,n,r,o,s=t.dygraph,l=t.drawingContext,h=s.layout_,u=t.dygraph.plotter_.area;if(s.getOptionForAxis("drawGrid","y")){for(var d=["y","y2"],c=[],p=[],g=[],f=[],v=[],r=0;r<d.length;r++)g[r]=s.getOptionForAxis("drawGrid",d[r]),g[r]&&(c[r]=s.getOptionForAxis("gridLineColor",d[r]),p[r]=s.getOptionForAxis("gridLineWidth",d[r]),v[r]=s.getOptionForAxis("gridLinePattern",d[r]),f[r]=v[r]&&v[r].length>=2);o=h.yticks,l.save(),o.forEach(function(t){if(t.has_tick){var r=t.axis;g[r]&&(l.save(),f[r]&&l.setLineDash&&l.setLineDash(v[r]),l.strokeStyle=c[r],l.lineWidth=p[r],i=e(u.x),n=a(u.y+t.pos*u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i+u.w,n),l.stroke(),l.restore())}}),l.restore()}if(s.getOptionForAxis("drawGrid","x")){o=h.xticks,l.save();var v=s.getOptionForAxis("gridLinePattern","x"),f=v&&v.length>=2;f&&l.setLineDash&&l.setLineDash(v),l.strokeStyle=s.getOptionForAxis("gridLineColor","x"),l.lineWidth=s.getOptionForAxis("gridLineWidth","x"),o.forEach(function(t){t.has_tick&&(i=e(u.x+t.pos*u.w),n=a(u.y+u.h),l.beginPath(),l.moveTo(i,n),l.lineTo(i,u.y),l.closePath(),l.stroke())}),f&&l.setLineDash&&l.setLineDash([]),l.restore()}},i.prototype.destroy=function(){},a.default=i,e.exports=a.default},{}],24:[function(t,e,a){"use strict";function i(t,e,a){if(!t||t.length<=1)return'<div class="dygraph-legend-line" style="border-bottom-color: '+e+';"></div>';var i,n,r,o,s,l=0,h=0,u=[];for(i=0;i<=t.length;i++)l+=t[i%t.length];if((s=Math.floor(a/(l-t[0])))>1){for(i=0;i<t.length;i++)u[i]=t[i]/a;h=u.length}else{for(s=1,i=0;i<t.length;i++)u[i]=t[i]/l;h=u.length+1}var d="";for(n=0;n<s;n++)for(i=0;i<h;i+=2)r=u[i%u.length],o=i<t.length?u[(i+1)%u.length]:0,d+='<div class="dygraph-legend-dash" style="margin-right: '+o+"em; padding-left: "+r+'em;"></div>';return d}Object.defineProperty(a,"__esModule",{value:!0});var n=t("../dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n),o=function(){this.legend_div_=null,this.is_generated_div_=!1};o.prototype.toString=function(){return"Legend Plugin"},o.prototype.activate=function(t){var e,a=t.getOption("labelsDiv");return a&&null!==a?e="string"==typeof a||a instanceof String?document.getElementById(a):a:(e=document.createElement("div"),e.className="dygraph-legend",t.graphDiv.appendChild(e),this.is_generated_div_=!0),this.legend_div_=e,this.one_em_width_=10,{select:this.select,deselect:this.deselect,predraw:this.predraw,didDrawChart:this.didDrawChart}};var s=function(t){var e=document.createElement("span");e.setAttribute("style","margin: 0; padding: 0 0 0 1em; border: 0;"),t.appendChild(e);var a=e.offsetWidth;return t.removeChild(e),a},l=function(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")};o.prototype.select=function(t){var e=t.selectedX,a=t.selectedPoints,i=t.selectedRow,n=t.dygraph.getOption("legend");if("never"===n)return void(this.legend_div_.style.display="none");if("follow"===n){var r=t.dygraph.plotter_.area,s=this.legend_div_.offsetWidth,l=t.dygraph.getOptionForAxis("axisLabelWidth","y"),h=a[0].x*r.w+50,u=a[0].y*r.h-50;h+s+1>r.w&&(h=h-100-s-(l-r.x)),t.dygraph.graphDiv.appendChild(this.legend_div_),this.legend_div_.style.left=l+h+"px",this.legend_div_.style.top=u+"px"}var d=o.generateLegendHTML(t.dygraph,e,a,this.one_em_width_,i);this.legend_div_.innerHTML=d,this.legend_div_.style.display=""},o.prototype.deselect=function(t){"always"!==t.dygraph.getOption("legend")&&(this.legend_div_.style.display="none");var e=s(this.legend_div_);this.one_em_width_=e;var a=o.generateLegendHTML(t.dygraph,void 0,void 0,e,null);this.legend_div_.innerHTML=a},o.prototype.didDrawChart=function(t){this.deselect(t)},o.prototype.predraw=function(t){if(this.is_generated_div_){t.dygraph.graphDiv.appendChild(this.legend_div_);var e=t.dygraph.getArea(),a=this.legend_div_.offsetWidth;this.legend_div_.style.left=e.x+e.w-a-1+"px",this.legend_div_.style.top=e.y+"px"}},o.prototype.destroy=function(){this.legend_div_=null},o.generateLegendHTML=function(t,e,a,n,s){var h={dygraph:t,x:e,series:[]},u={},d=t.getLabels();if(d)for(var c=1;c<d.length;c++){var p=t.getPropertiesForSeries(d[c]),g=t.getOption("strokePattern",d[c]),f={dashHTML:i(g,p.color,n),label:d[c],labelHTML:l(d[c]),isVisible:p.visible,color:p.color};h.series.push(f),u[d[c]]=f}if(void 0!==e){var v=t.optionsViewForAxis_("x"),_=v("valueFormatter");h.xHTML=_.call(t,e,v,d[0],t,s,0);for(var y=[],x=t.numAxes(),c=0;c<x;c++)y[c]=t.optionsViewForAxis_("y"+(c?1+c:""));var m=t.getOption("labelsShowZeroValues"),b=t.getHighlightSeries();for(c=0;c<a.length;c++){var w=a[c],f=u[w.name];if(f.y=w.yval,0===w.yval&&!m||isNaN(w.canvasy))f.isVisible=!1;else{var p=t.getPropertiesForSeries(w.name),A=y[p.axis-1],O=A("valueFormatter"),D=O.call(t,w.yval,A,w.name,t,s,d.indexOf(w.name));r.update(f,{yHTML:D}),w.name==b&&(f.isHighlighted=!0)}}}return(t.getOption("legendFormatter")||o.defaultFormatter).call(t,h)},o.defaultFormatter=function(t){var e=t.dygraph;if(!0!==e.getOption("showLabelsOnHighlight"))return"";var a,i=e.getOption("labelsSeparateLines");if(void 0===t.x){if("always"!=e.getOption("legend"))return"";a="";for(var n=0;n<t.series.length;n++){var r=t.series[n];r.isVisible&&(""!==a&&(a+=i?"<br/>":" "),a+="<span style='font-weight: bold; color: "+r.color+";'>"+r.dashHTML+" "+r.labelHTML+"</span>")}return a}a=t.xHTML+":";for(var n=0;n<t.series.length;n++){var r=t.series[n];if(r.isVisible){i&&(a+="<br>");a+="<span"+(r.isHighlighted?' class="highlight"':"")+"> <b><span style='color: "+r.color+";'>"+r.labelHTML+"</span></b>: "+r.yHTML+"</span>"}}return a},a.default=o,e.exports=a.default},{"../dygraph-utils":17}],25:[function(t,e,a){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}Object.defineProperty(a,"__esModule",{value:!0});var n=t("../dygraph-utils"),r=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(e[a]=t[a]);return e.default=t,e}(n),o=t("../dygraph-interaction-model"),s=i(o),l=t("../iframe-tarp"),h=i(l),u=function(){this.hasTouchInterface_="undefined"!=typeof TouchEvent,this.isMobileDevice_=/mobile|android/gi.test(navigator.appVersion),this.interfaceCreated_=!1};u.prototype.toString=function(){return"RangeSelector Plugin"},u.prototype.activate=function(t){return this.dygraph_=t,this.getOption_("showRangeSelector")&&this.createInterface_(),{layout:this.reserveSpace_,predraw:this.renderStaticLayer_,didDrawChart:this.renderInteractiveLayer_}},u.prototype.destroy=function(){this.bgcanvas_=null,this.fgcanvas_=null,this.leftZoomHandle_=null,this.rightZoomHandle_=null},u.prototype.getOption_=function(t,e){return this.dygraph_.getOption(t,e)},u.prototype.setDefaultOption_=function(t,e){this.dygraph_.attrs_[t]=e},u.prototype.createInterface_=function(){this.createCanvases_(),this.createZoomHandles_(),this.initInteraction_(),this.getOption_("animatedZooms")&&(console.warn("Animated zooms and range selector are not compatible; disabling animatedZooms."),this.dygraph_.updateOptions({animatedZooms:!1},!0)),this.interfaceCreated_=!0,this.addToGraph_()},u.prototype.addToGraph_=function(){var t=this.graphDiv_=this.dygraph_.graphDiv;t.appendChild(this.bgcanvas_),t.appendChild(this.fgcanvas_),t.appendChild(this.leftZoomHandle_),t.appendChild(this.rightZoomHandle_)},u.prototype.removeFromGraph_=function(){var t=this.graphDiv_;t.removeChild(this.bgcanvas_),t.removeChild(this.fgcanvas_),t.removeChild(this.leftZoomHandle_),t.removeChild(this.rightZoomHandle_),this.graphDiv_=null},u.prototype.reserveSpace_=function(t){this.getOption_("showRangeSelector")&&t.reserveSpaceBottom(this.getOption_("rangeSelectorHeight")+4)},u.prototype.renderStaticLayer_=function(){this.updateVisibility_()&&(this.resize_(),this.drawStaticLayer_())},u.prototype.renderInteractiveLayer_=function(){this.updateVisibility_()&&!this.isChangingRange_&&(this.placeZoomHandles_(),this.drawInteractiveLayer_())},u.prototype.updateVisibility_=function(){var t=this.getOption_("showRangeSelector");if(t)this.interfaceCreated_?this.graphDiv_&&this.graphDiv_.parentNode||this.addToGraph_():this.createInterface_();else if(this.graphDiv_){this.removeFromGraph_();var e=this.dygraph_;setTimeout(function(){e.width_=0,e.resize()},1)}return t},u.prototype.resize_=function(){function t(t,e,a,i){var n=i||r.getContextPixelRatio(e);t.style.top=a.y+"px",t.style.left=a.x+"px",t.width=a.w*n,t.height=a.h*n,t.style.width=a.w+"px",t.style.height=a.h+"px",1!=n&&e.scale(n,n)}var e=this.dygraph_.layout_.getPlotArea(),a=0;this.dygraph_.getOptionForAxis("drawAxis","x")&&(a=this.getOption_("xAxisHeight")||this.getOption_("axisLabelFontSize")+2*this.getOption_("axisTickSize")),this.canvasRect_={x:e.x,y:e.y+e.h+a+4,w:e.w,h:this.getOption_("rangeSelectorHeight")};var i=this.dygraph_.getNumericOption("pixelRatio");t(this.bgcanvas_,this.bgcanvas_ctx_,this.canvasRect_,i),t(this.fgcanvas_,this.fgcanvas_ctx_,this.canvasRect_,i)},u.prototype.createCanvases_=function(){this.bgcanvas_=r.createCanvas(),this.bgcanvas_.className="dygraph-rangesel-bgcanvas",this.bgcanvas_.style.position="absolute",this.bgcanvas_.style.zIndex=9,this.bgcanvas_ctx_=r.getContext(this.bgcanvas_),this.fgcanvas_=r.createCanvas(),this.fgcanvas_.className="dygraph-rangesel-fgcanvas",this.fgcanvas_.style.position="absolute",this.fgcanvas_.style.zIndex=9,this.fgcanvas_.style.cursor="default",this.fgcanvas_ctx_=r.getContext(this.fgcanvas_)},u.prototype.createZoomHandles_=function(){var t=new Image;t.className="dygraph-rangesel-zoomhandle",t.style.position="absolute",t.style.zIndex=10,t.style.visibility="hidden",t.style.cursor="col-resize",t.width=9,t.height=16,t.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAzwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7sqSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=",this.isMobileDevice_&&(t.width*=2,t.height*=2),this.leftZoomHandle_=t,this.rightZoomHandle_=t.cloneNode(!1)},u.prototype.initInteraction_=function(){var t,e,a,i,n,o,l,u,d,c,p,g,f,v,_=this,y=document,x=0,m=null,b=!1,w=!1,A=!this.isMobileDevice_,O=new h.default;t=function(t){var e=_.dygraph_.xAxisExtremes(),a=(e[1]-e[0])/_.canvasRect_.w;return[e[0]+(t.leftHandlePos-_.canvasRect_.x)*a,e[0]+(t.rightHandlePos-_.canvasRect_.x)*a]},e=function(t){return r.cancelEvent(t),b=!0,x=t.clientX,m=t.target?t.target:t.srcElement,"mousedown"!==t.type&&"dragstart"!==t.type||(r.addEvent(y,"mousemove",a),r.addEvent(y,"mouseup",i)),_.fgcanvas_.style.cursor="col-resize",O.cover(),!0},a=function(t){if(!b)return!1;r.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a,i=_.getZoomHandleStatus_();m==_.leftZoomHandle_?(a=i.leftHandlePos+e,a=Math.min(a,i.rightHandlePos-m.width-3),a=Math.max(a,_.canvasRect_.x)):(a=i.rightHandlePos+e,a=Math.min(a,_.canvasRect_.x+_.canvasRect_.w),a=Math.max(a,i.leftHandlePos+m.width+3));var o=m.width/2;return m.style.left=a-o+"px",_.drawInteractiveLayer_(),A&&n(),!0},i=function(t){return!!b&&(b=!1,O.uncover(),r.removeEvent(y,"mousemove",a),r.removeEvent(y,"mouseup",i),_.fgcanvas_.style.cursor="default",A||n(),!0)},n=function(){try{var e=_.getZoomHandleStatus_();if(_.isChangingRange_=!0,e.isZoomed){var a=t(e);_.dygraph_.doZoomXDates_(a[0],a[1])}else _.dygraph_.resetZoom()}finally{_.isChangingRange_=!1}},o=function(t){var e=_.leftZoomHandle_.getBoundingClientRect(),a=e.left+e.width/2;e=_.rightZoomHandle_.getBoundingClientRect();var i=e.left+e.width/2;return t.clientX>a&&t.clientX<i},l=function(t){return!(w||!o(t)||!_.getZoomHandleStatus_().isZoomed)&&(r.cancelEvent(t),w=!0,x=t.clientX,"mousedown"===t.type&&(r.addEvent(y,"mousemove",u),r.addEvent(y,"mouseup",d)),!0)},u=function(t){if(!w)return!1;r.cancelEvent(t);var e=t.clientX-x;if(Math.abs(e)<4)return!0;x=t.clientX;var a=_.getZoomHandleStatus_(),i=a.leftHandlePos,n=a.rightHandlePos,o=n-i;i+e<=_.canvasRect_.x?(i=_.canvasRect_.x,n=i+o):n+e>=_.canvasRect_.x+_.canvasRect_.w?(n=_.canvasRect_.x+_.canvasRect_.w,i=n-o):(i+=e,n+=e);var s=_.leftZoomHandle_.width/2;return _.leftZoomHandle_.style.left=i-s+"px",_.rightZoomHandle_.style.left=n-s+"px",_.drawInteractiveLayer_(),A&&c(),!0},d=function(t){return!!w&&(w=!1,r.removeEvent(y,"mousemove",u),r.removeEvent(y,"mouseup",d),A||c(),!0)},c=function(){try{_.isChangingRange_=!0,_.dygraph_.dateWindow_=t(_.getZoomHandleStatus_()),_.dygraph_.drawGraph_(!1)}finally{_.isChangingRange_=!1}},p=function(t){if(!b&&!w){var e=o(t)?"move":"default";e!=_.fgcanvas_.style.cursor&&(_.fgcanvas_.style.cursor=e)}},g=function(t){"touchstart"==t.type&&1==t.targetTouches.length?e(t.targetTouches[0])&&r.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?a(t.targetTouches[0])&&r.cancelEvent(t):i(t)},f=function(t){"touchstart"==t.type&&1==t.targetTouches.length?l(t.targetTouches[0])&&r.cancelEvent(t):"touchmove"==t.type&&1==t.targetTouches.length?u(t.targetTouches[0])&&r.cancelEvent(t):d(t)},v=function(t,e){for(var a=["touchstart","touchend","touchmove","touchcancel"],i=0;i<a.length;i++)_.dygraph_.addAndTrackEvent(t,a[i],e)},this.setDefaultOption_("interactionModel",s.default.dragIsPanInteractionModel),this.setDefaultOption_("panEdgeFraction",1e-4);var D=window.opera?"mousedown":"dragstart";this.dygraph_.addAndTrackEvent(this.leftZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.rightZoomHandle_,D,e),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousedown",l),this.dygraph_.addAndTrackEvent(this.fgcanvas_,"mousemove",p),this.hasTouchInterface_&&(v(this.leftZoomHandle_,g),v(this.rightZoomHandle_,g),v(this.fgcanvas_,f))},u.prototype.drawStaticLayer_=function(){var t=this.bgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);try{this.drawMiniPlot_()}catch(t){console.warn(t)}this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorBackgroundLineWidth"),t.strokeStyle=this.getOption_("rangeSelectorBackgroundStrokeColor"),t.beginPath(),t.moveTo(.5,.5),t.lineTo(.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,this.canvasRect_.h-.5),t.lineTo(this.canvasRect_.w-.5,.5),t.stroke()},u.prototype.drawMiniPlot_=function(){var t=this.getOption_("rangeSelectorPlotFillColor"),e=this.getOption_("rangeSelectorPlotFillGradientColor"),a=this.getOption_("rangeSelectorPlotStrokeColor");if(t||a){var i=this.getOption_("stepPlot"),n=this.computeCombinedSeriesAndLimits_(),r=n.yMax-n.yMin,o=this.bgcanvas_ctx_,s=this.dygraph_.xAxisExtremes(),l=Math.max(s[1]-s[0],1e-30),h=(this.canvasRect_.w-.5)/l,u=(this.canvasRect_.h-.5)/r,d=this.canvasRect_.w-.5,c=this.canvasRect_.h-.5,p=null,g=null;o.beginPath(),o.moveTo(.5,c);for(var f=0;f<n.data.length;f++){var v=n.data[f],_=null!==v[0]?(v[0]-s[0])*h:NaN,y=null!==v[1]?c-(v[1]-n.yMin)*u:NaN;(i||null===p||Math.round(_)!=Math.round(p))&&(isFinite(_)&&isFinite(y)?(null===p?o.lineTo(_,c):i&&o.lineTo(_,g),o.lineTo(_,y),p=_,g=y):(null!==p&&(i?(o.lineTo(_,g),o.lineTo(_,c)):o.lineTo(p,c)),p=g=null))}if(o.lineTo(d,c),o.closePath(),t){var x=this.bgcanvas_ctx_.createLinearGradient(0,0,0,c);e&&x.addColorStop(0,e),x.addColorStop(1,t),this.bgcanvas_ctx_.fillStyle=x,o.fill()}a&&(this.bgcanvas_ctx_.strokeStyle=a,this.bgcanvas_ctx_.lineWidth=this.getOption_("rangeSelectorPlotLineWidth"),o.stroke())}},u.prototype.computeCombinedSeriesAndLimits_=function(){var t,e=this.dygraph_,a=this.getOption_("logscale"),i=e.numColumns(),n=e.getLabels(),o=new Array(i),s=!1,l=e.visibility(),h=[];for(t=1;t<i;t++){var u=this.getOption_("showInRangeSelector",n[t]);h.push(u),null!==u&&(s=!0)}if(s)for(t=1;t<i;t++)o[t]=h[t-1];else for(t=1;t<i;t++)o[t]=l[t-1];var d=[],c=e.dataHandler_,p=e.attributes_;for(t=1;t<e.numColumns();t++)if(o[t]){var g=c.extractSeries(e.rawData_,t,p);e.rollPeriod()>1&&(g=c.rollingAverage(g,e.rollPeriod(),p)),d.push(g)}var f=[];for(t=0;t<d[0].length;t++){for(var v=0,_=0,y=0;y<d.length;y++){var x=d[y][t][1];null===x||isNaN(x)||(_++,v+=x)}f.push([d[0][t][0],v/_])}var m=Number.MAX_VALUE,b=-Number.MAX_VALUE;for(t=0;t<f.length;t++){var w=f[t][1];null!==w&&isFinite(w)&&(!a||w>0)&&(m=Math.min(m,w),b=Math.max(b,w))}if(a)for(b=r.log10(b),b+=.25*b,m=r.log10(m),t=0;t<f.length;t++)f[t][1]=r.log10(f[t][1]);else{var A,O=b-m;A=O<=Number.MIN_VALUE?.25*b:.25*O,b+=A,m-=A}return{data:f,yMin:m,yMax:b}},u.prototype.placeZoomHandles_=function(){var t=this.dygraph_.xAxisExtremes(),e=this.dygraph_.xAxisRange(),a=t[1]-t[0],i=Math.max(0,(e[0]-t[0])/a),n=Math.max(0,(t[1]-e[1])/a),r=this.canvasRect_.x+this.canvasRect_.w*i,o=this.canvasRect_.x+this.canvasRect_.w*(1-n),s=Math.max(this.canvasRect_.y,this.canvasRect_.y+(this.canvasRect_.h-this.leftZoomHandle_.height)/2),l=this.leftZoomHandle_.width/2;this.leftZoomHandle_.style.left=r-l+"px",this.leftZoomHandle_.style.top=s+"px",this.rightZoomHandle_.style.left=o-l+"px",this.rightZoomHandle_.style.top=this.leftZoomHandle_.style.top,this.leftZoomHandle_.style.visibility="visible",this.rightZoomHandle_.style.visibility="visible"},u.prototype.drawInteractiveLayer_=function(){var t=this.fgcanvas_ctx_;t.clearRect(0,0,this.canvasRect_.w,this.canvasRect_.h);var e=this.canvasRect_.w-1,a=this.canvasRect_.h-1,i=this.getZoomHandleStatus_();if(t.strokeStyle=this.getOption_("rangeSelectorForegroundStrokeColor"),t.lineWidth=this.getOption_("rangeSelectorForegroundLineWidth"),i.isZoomed){var n=Math.max(1,i.leftHandlePos-this.canvasRect_.x),r=Math.min(e,i.rightHandlePos-this.canvasRect_.x);t.fillStyle="rgba(240, 240, 240, "+this.getOption_("rangeSelectorAlpha").toString()+")",t.fillRect(0,0,n,this.canvasRect_.h),t.fillRect(r,0,this.canvasRect_.w-r,this.canvasRect_.h),t.beginPath(),t.moveTo(1,1),t.lineTo(n,1),t.lineTo(n,a),t.lineTo(r,a),t.lineTo(r,1),t.lineTo(e,1),t.stroke()}else t.beginPath(),t.moveTo(1,1),t.lineTo(1,a),t.lineTo(e,a),t.lineTo(e,1),t.stroke()},u.prototype.getZoomHandleStatus_=function(){var t=this.leftZoomHandle_.width/2,e=parseFloat(this.leftZoomHandle_.style.left)+t,a=parseFloat(this.rightZoomHandle_.style.left)+t;return{leftHandlePos:e,rightHandlePos:a,isZoomed:e-1>this.canvasRect_.x||a+1<this.canvasRect_.x+this.canvasRect_.w}},a.default=u,e.exports=a.default},{"../dygraph-interaction-model":12,"../dygraph-utils":17,"../iframe-tarp":19}]},{},[18])(18)}); +//# sourceMappingURL=dist/dygraph.min.js.map diff --git a/web/gui/lib/dygraph-smooth-plotter-c91c859.js b/web/gui/lib/dygraph-smooth-plotter-c91c859.js new file mode 100644 index 0000000..c0b76fb --- /dev/null +++ b/web/gui/lib/dygraph-smooth-plotter-c91c859.js @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +(function() { +"use strict"; + +var Dygraph; +if (window.Dygraph) { + Dygraph = window.Dygraph; +} else if (typeof(module) !== 'undefined') { + Dygraph = require('../dygraph'); +} + +/** + * Given three sequential points, p0, p1 and p2, find the left and right + * control points for p1. + * + * The three points are expected to have x and y properties. + * + * The alpha parameter controls the amount of smoothing. + * If α=0, then both control points will be the same as p1 (i.e. no smoothing). + * + * Returns [l1x, l1y, r1x, r1y] + * + * It's guaranteed that the line from (l1x, l1y)-(r1x, r1y) passes through p1. + * Unless allowFalseExtrema is set, then it's also guaranteed that: + * l1y ∈ [p0.y, p1.y] + * r1y ∈ [p1.y, p2.y] + * + * The basic algorithm is: + * 1. Put the control points l1 and r1 α of the way down (p0, p1) and (p1, p2). + * 2. Shift l1 and r2 so that the line l1–r1 passes through p1 + * 3. Adjust to prevent false extrema while keeping p1 on the l1–r1 line. + * + * This is loosely based on the HighCharts algorithm. + */ +function getControlPoints(p0, p1, p2, opt_alpha, opt_allowFalseExtrema) { + var alpha = (opt_alpha !== undefined) ? opt_alpha : 1/3; // 0=no smoothing, 1=crazy smoothing + var allowFalseExtrema = opt_allowFalseExtrema || false; + + if (!p2) { + return [p1.x, p1.y, null, null]; + } + + // Step 1: Position the control points along each line segment. + var l1x = (1 - alpha) * p1.x + alpha * p0.x, + l1y = (1 - alpha) * p1.y + alpha * p0.y, + r1x = (1 - alpha) * p1.x + alpha * p2.x, + r1y = (1 - alpha) * p1.y + alpha * p2.y; + + // Step 2: shift the points up so that p1 is on the l1–r1 line. + if (l1x != r1x) { + // This can be derived w/ some basic algebra. + var deltaY = p1.y - r1y - (p1.x - r1x) * (l1y - r1y) / (l1x - r1x); + l1y += deltaY; + r1y += deltaY; + } + + // Step 3: correct to avoid false extrema. + if (!allowFalseExtrema) { + if (l1y > p0.y && l1y > p1.y) { + l1y = Math.max(p0.y, p1.y); + r1y = 2 * p1.y - l1y; + } else if (l1y < p0.y && l1y < p1.y) { + l1y = Math.min(p0.y, p1.y); + r1y = 2 * p1.y - l1y; + } + + if (r1y > p1.y && r1y > p2.y) { + r1y = Math.max(p1.y, p2.y); + l1y = 2 * p1.y - r1y; + } else if (r1y < p1.y && r1y < p2.y) { + r1y = Math.min(p1.y, p2.y); + l1y = 2 * p1.y - r1y; + } + } + + return [l1x, l1y, r1x, r1y]; +} + +// i.e. is none of (null, undefined, NaN) +function isOK(x) { + return !!x && !isNaN(x); +}; + +// A plotter which uses splines to create a smooth curve. +// See tests/plotters.html for a demo. +// Can be controlled via smoothPlotter.smoothing +function smoothPlotter(e) { + var ctx = e.drawingContext, + points = e.points; + + ctx.beginPath(); + ctx.moveTo(points[0].canvasx, points[0].canvasy); + + // right control point for previous point + var lastRightX = points[0].canvasx, lastRightY = points[0].canvasy; + + for (var i = 1; i < points.length; i++) { + var p0 = points[i - 1], + p1 = points[i], + p2 = points[i + 1]; + p0 = p0 && isOK(p0.canvasy) ? p0 : null; + p1 = p1 && isOK(p1.canvasy) ? p1 : null; + p2 = p2 && isOK(p2.canvasy) ? p2 : null; + if (p0 && p1) { + var controls = getControlPoints({x: p0.canvasx, y: p0.canvasy}, + {x: p1.canvasx, y: p1.canvasy}, + p2 && {x: p2.canvasx, y: p2.canvasy}, + smoothPlotter.smoothing); + // Uncomment to show the control points: + // ctx.lineTo(lastRightX, lastRightY); + // ctx.lineTo(controls[0], controls[1]); + // ctx.lineTo(p1.canvasx, p1.canvasy); + lastRightX = (lastRightX !== null) ? lastRightX : p0.canvasx; + lastRightY = (lastRightY !== null) ? lastRightY : p0.canvasy; + ctx.bezierCurveTo(lastRightX, lastRightY, + controls[0], controls[1], + p1.canvasx, p1.canvasy); + lastRightX = controls[2]; + lastRightY = controls[3]; + } else if (p1) { + // We're starting again after a missing point. + ctx.moveTo(p1.canvasx, p1.canvasy); + lastRightX = p1.canvasx; + lastRightY = p1.canvasy; + } else { + lastRightX = lastRightY = null; + } + } + + ctx.stroke(); +} +smoothPlotter.smoothing = 1/3; +smoothPlotter._getControlPoints = getControlPoints; // for testing + +// older versions exported a global. +// This will be removed in the future. +// The preferred way to access smoothPlotter is via Dygraph.smoothPlotter. +window.smoothPlotter = smoothPlotter; +Dygraph.smoothPlotter = smoothPlotter; + +})(); diff --git a/web/gui/lib/fontawesome-all-5.0.1.min.js b/web/gui/lib/fontawesome-all-5.0.1.min.js new file mode 100644 index 0000000..d2775aa --- /dev/null +++ b/web/gui/lib/fontawesome-all-5.0.1.min.js @@ -0,0 +1,6 @@ +/*! + * Font Awesome Free 5.0.1 by @fontawesome - http://fontawesome.com + * License - http://fontawesome.com/license (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * SPDX-License-Identifier: MIT + */ +!function(){"use strict";function c(c){"function"==typeof s.hooks.addPack?s.hooks.addPack(c,m):s.styles[c]=r({},s.styles[c]||{},m)}var l={};try{"undefined"!=typeof window&&(l=window)}catch(c){}var h=(l.navigator||{}).userAgent,v=void 0===h?"":h,z=l,e=(~v.indexOf("MSIE")||v.indexOf("Trident/"),[1,2,3,4,5,6,7,8,9,10]),a=e.concat([11,12,13,14,15,16,17,18,19,20]),m=(["xs","sm","lg","fw","ul","li","border","pull-left","pull-right","spin","pulse","rotate-90","rotate-180","rotate-270","flip-horizontal","flip-vertical","stack","stack-1x","stack-2x","inverse","layers","layers-text","layers-counter"].concat(e.map(function(c){return c+"x"})).concat(a.map(function(c){return"w-"+c})),{"500px":[448,512,[],"f26e","M103.3 344.3c-6.5-14.2-6.9-18.3 7.4-23.1 25.6-8 8 9.2 43.2 49.2h.3v-93.9c1.2-50.2 44-92.2 97.7-92.2 53.9 0 97.7 43.5 97.7 96.8 0 63.4-60.8 113.2-128.5 93.3-10.5-4.2-2.1-31.7 8.5-28.6 53 0 89.4-10.1 89.4-64.4 0-61-77.1-89.6-116.9-44.6-23.5 26.4-17.6 42.1-17.6 157.6 50.7 31 118.3 22 160.4-20.1 24.8-24.8 38.5-58 38.5-93 0-35.2-13.8-68.2-38.8-93.3-24.8-24.8-57.8-38.5-93.3-38.5s-68.8 13.8-93.5 38.5c-.3.3-16 16.5-21.2 23.9l-.5.6c-3.3 4.7-6.3 9.1-20.1 6.1-6.9-1.7-14.3-5.8-14.3-11.8V20c0-5 3.9-10.5 10.5-10.5h241.3c8.3 0 8.3 11.6 8.3 15.1 0 3.9 0 15.1-8.3 15.1H130.3v132.9h.3c104.2-109.8 282.8-36 282.8 108.9 0 178.1-244.8 220.3-310.1 62.8zm63.3-260.8c-.5 4.2 4.6 24.5 14.6 20.6C306 56.6 384 144.5 390.6 144.5c4.8 0 22.8-15.3 14.3-22.8-93.2-89-234.5-57-238.3-38.2zM393 414.7C283 524.6 94 475.5 61 310.5c0-12.2-30.4-7.4-28.9 3.3 24 173.4 246 256.9 381.6 121.3 6.9-7.8-12.6-28.4-20.7-20.4zM213.6 306.6c0 4 4.3 7.3 5.5 8.5 3 3 6.1 4.4 8.5 4.4 3.8 0 2.6.2 22.3-19.5 19.6 19.3 19.1 19.5 22.3 19.5 5.4 0 18.5-10.4 10.7-18.2L265.6 284l18.2-18.2c6.3-6.8-10.1-21.8-16.2-15.7L249.7 268c-18.6-18.8-18.4-19.5-21.5-19.5-5 0-18 11.7-12.4 17.3L234 284c-18.1 17.9-20.4 19.2-20.4 22.6z"],"accessible-icon":[448,512,[],"f368","M423.9 255.8L411 413.1c-3.3 40.7-63.9 35.1-60.6-4.9l10-122.5-41.1 2.3c10.1 20.7 15.8 43.9 15.8 68.5 0 41.2-16.1 78.7-42.3 106.5l-39.3-39.3c57.9-63.7 13.1-167.2-74-167.2-25.9 0-49.5 9.9-67.2 26L73 243.2c22-20.7 50.1-35.1 81.4-40.2l75.3-85.7-42.6-24.8-51.6 46c-30 26.8-70.6-18.5-40.5-45.4l68-60.7c9.8-8.8 24.1-10.2 35.5-3.6 0 0 139.3 80.9 139.5 81.1 16.2 10.1 20.7 36 6.1 52.6L285.7 229l106.1-5.9c18.5-1.1 33.6 14.4 32.1 32.7zm-64.9-154c28.1 0 50.9-22.8 50.9-50.9C409.9 22.8 387.1 0 359 0c-28.1 0-50.9 22.8-50.9 50.9 0 28.1 22.8 50.9 50.9 50.9zM179.6 456.5c-80.6 0-127.4-90.6-82.7-156.1l-39.7-39.7C36.4 287 24 320.3 24 356.4c0 130.7 150.7 201.4 251.4 122.5l-39.7-39.7c-16 10.9-35.3 17.3-56.1 17.3z"],accusoft:[640,512,[],"f369","M482.2 372.1C476.5 365.2 250 75 242.3 65.5c-13.7-17.2 0-16.8 19.2-16.9 9.7-.1 106.3-.6 116.5-.6 24.1-.1 28.7.6 38.4 12.8 2.1 2.7 205.1 245.8 207.2 248.3 5.5 6.7 15.2 19.1 7.2 23.4-2.4 1.3-114.6 47.7-117.8 48.9-10.1 4-17.5 6.8-30.8-9.3m114.7-5.6s-115 50.4-117.5 51.6c-16 7.3-26.9-3.2-36.7-14.6l-57.1-74c-5.4-.9-60.4-9.6-65.3-9.3-3.1.2-9.6.8-14.4 2.9-4.9 2.1-145.2 52.8-150.2 54.7-5.1 2-11.4 3.6-11.1 7.6.2 2.5 2 2.6 4.6 3.5 2.7.8 300.9 67.6 308 69.1 15.6 3.3 38.5 10.5 53.6 1.7 2.1-1.2 123.8-76.4 125.8-77.8 5.4-4 4.3-6.8-1.7-8.2-2.3-.3-24.6-4.7-38-7.2m-326-181.3s-12 1.6-25 15.1c-9 9.3-242.1 239.1-243.4 240.9-7 10 1.6 6.8 15.7 1.7.8 0 114.5-36.6 114.5-36.6.5-.6-.1-.1.6-.6-.4-5.1-.8-26.2-1-27.7-.6-5.2 2.2-6.9 7-8.9l92.6-33.8c.6-.8 88.5-81.7 90.2-83.3v-1l-51.2-65.8"],adn:[496,512,[],"f170","M248 167.5l64.9 98.8H183.1l64.9-98.8zM496 256c0 136.9-111.1 248-248 248S0 392.9 0 256 111.1 8 248 8s248 111.1 248 248zm-99.8 82.7L248 115.5 99.8 338.7h30.4l33.6-51.7h168.6l33.6 51.7h30.2z"],adversal:[512,512,[],"f36a","M482.1 32H28.7C5.8 32 0 37.9 0 60.9v390.2C0 474.4 5.8 480 28.7 480h453.4c24.4 0 29.9-5.2 29.9-29.7V62.2c0-24.6-5.4-30.2-29.9-30.2zM178.4 220.3c-27.5-20.2-72.1-8.7-84.2 23.4-4.3 11.1-9.3 9.5-17.5 8.3-9.7-1.5-17.2-3.2-22.5-5.5-28.8-11.4 8.6-55.3 24.9-64.3 41.1-21.4 83.4-22.2 125.3-4.8 40.9 16.8 34.5 59.2 34.5 128.5 2.7 25.8-4.3 58.3 9.3 88.8 1.9 4.4.4 7.9-2.7 10.7-8.4 6.7-39.3 2.2-46.6-7.4-1.9-2.2-1.8-3.6-3.9-6.2-3.6-3.9-7.3-2.2-11.9 1-57.4 36.4-140.3 21.4-147-43.3-3.1-29.3 12.4-57.1 39.6-71 38.2-19.5 112.2-11.8 114-30.9 1.1-10.2-1.9-20.1-11.3-27.3zm286.7 222c0 15.1-11.1 9.9-17.8 9.9H52.4c-7.4 0-18.2 4.8-17.8-10.7.4-13.9 10.5-9.1 17.1-9.1 132.3-.4 264.5-.4 396.8 0 6.8 0 16.6-4.4 16.6 9.9zm3.8-340.5v291c0 5.7-.7 13.9-8.1 13.9-12.4-.4-27.5 7.1-36.1-5.6-5.8-8.7-7.8-4-12.4-1.2-53.4 29.7-128.1 7.1-144.4-85.2-6.1-33.4-.7-67.1 15.7-100 11.8-23.9 56.9-76.1 136.1-30.5v-71c0-26.2-.1-26.2 26-26.2 3.1 0 6.6.4 9.7 0 10.1-.8 13.6 4.4 13.6 14.3-.1.2-.1.3-.1.5zm-51.5 232.3c-19.5 47.6-72.9 43.3-90 5.2-15.1-33.3-15.5-68.2.4-101.5 16.3-34.1 59.7-35.7 81.5-4.8 20.6 28.8 14.9 84.6 8.1 101.1zm-294.8 35.3c-7.5-1.3-33-3.3-33.7-27.8-.4-13.9 7.8-23 19.8-25.8 24.4-5.9 49.3-9.9 73.7-14.7 8.9-2 7.4 4.4 7.8 9.5 1.4 33-26.1 59.2-67.6 58.8z"],affiliatetheme:[512,512,[],"f36b","M159.7 237.4C108.4 308.3 43.1 348.2 14 326.6-15.2 304.9 2.8 230 54.2 159.1c51.3-70.9 116.6-110.8 145.7-89.2 29.1 21.6 11.1 96.6-40.2 167.5zm351.2-57.3C437.1 303.5 319 367.8 246.4 323.7c-25-15.2-41.3-41.2-49-73.8-33.6 64.8-92.8 113.8-164.1 133.2 49.8 59.3 124.1 96.9 207 96.9 150 0 271.6-123.1 271.6-274.9.1-8.5-.3-16.8-1-25z"],algolia:[448,512,[],"f36c","M229.3 182.6c-49.3 0-89.2 39.9-89.2 89.2 0 49.3 39.9 89.2 89.2 89.2s89.2-39.9 89.2-89.2c0-49.3-40-89.2-89.2-89.2zm62.7 56.6l-58.9 30.6c-1.8.9-3.8-.4-3.8-2.3V201c0-1.5 1.3-2.7 2.7-2.6 26.2 1 48.9 15.7 61.1 37.1.7 1.3.2 3-1.1 3.7zM389.1 32H58.9C26.4 32 0 58.4 0 90.9V421c0 32.6 26.4 59 58.9 59H389c32.6 0 58.9-26.4 58.9-58.9V90.9C448 58.4 421.6 32 389.1 32zm-202.6 84.7c0-10.8 8.7-19.5 19.5-19.5h45.3c10.8 0 19.5 8.7 19.5 19.5v15.4c0 1.8-1.7 3-3.3 2.5-12.3-3.4-25.1-5.1-38.1-5.1-13.5 0-26.7 1.8-39.4 5.5-1.7.5-3.4-.8-3.4-2.5v-15.8zm-84.4 37l9.2-9.2c7.6-7.6 19.9-7.6 27.5 0l7.7 7.7c1.1 1.1 1 3-.3 4-6.2 4.5-12.1 9.4-17.6 14.9-5.4 5.4-10.4 11.3-14.8 17.4-1 1.3-2.9 1.5-4 .3l-7.7-7.7c-7.6-7.5-7.6-19.8 0-27.4zm127.2 244.8c-70 0-126.6-56.7-126.6-126.6s56.7-126.6 126.6-126.6c70 0 126.6 56.6 126.6 126.6 0 69.8-56.7 126.6-126.6 126.6z"],amazon:[448,512,[],"f270","M257.2 162.7c-48.7 1.8-169.5 15.5-169.5 117.5 0 109.5 138.3 114 183.5 43.2 6.5 10.2 35.4 37.5 45.3 46.8l56.8-56S341 288.9 341 261.4V114.3C341 89 316.5 32 228.7 32 140.7 32 94 87 94 136.3l73.5 6.8c16.3-49.5 54.2-49.5 54.2-49.5 40.7-.1 35.5 29.8 35.5 69.1zm0 86.8c0 80-84.2 68-84.2 17.2 0-47.2 50.5-56.7 84.2-57.8v40.6zm136 163.5c-7.7 10-70 67-174.5 67S34.2 408.5 9.7 379c-6.8-7.7 1-11.3 5.5-8.3C88.5 415.2 203 488.5 387.7 401c7.5-3.7 13.3 2 5.5 12zm39.8 2.2c-6.5 15.8-16 26.8-21.2 31-5.5 4.5-9.5 2.7-6.5-3.8s19.3-46.5 12.7-55c-6.5-8.3-37-4.3-48-3.2-10.8 1-13 2-14-.3-2.3-5.7 21.7-15.5 37.5-17.5 15.7-1.8 41-.8 46 5.7 3.7 5.1 0 27.1-6.5 43.1z"],amilia:[448,512,[],"f36d","M240.1 32c-61.9 0-131.5 16.9-184.2 55.4-5.1 3.1-9.1 9.2-7.2 19.4 1.1 5.1 5.1 27.4 10.2 39.6 4.1 10.2 14.2 10.2 20.3 6.1 32.5-22.3 96.5-47.7 152.3-47.7 57.9 0 58.9 28.4 58.9 73.1v38.5C203 227.7 78.2 251 46.7 264.2 11.2 280.5 16.3 357.7 16.3 376s15.2 104 124.9 104c47.8 0 113.7-20.7 153.3-42.1v25.4c0 3 2.1 8.2 6.1 9.1 3.1 1 50.7 2 59.9 2s62.5.3 66.5-.7c4.1-1 5.1-6.1 5.1-9.1V168c-.1-80.3-57.9-136-192-136zm-87.9 327.7c0-12.2-3-42.7 18.3-52.9 24.3-13.2 75.1-29.4 119.8-33.5V380c-21.4 13.2-48.7 24.4-79.1 24.4-52.8 0-58.9-33.5-59-44.7"],android:[448,512,[],"f17b","M89.6 204.5v115.8c0 15.4-12.1 27.7-27.5 27.7-15.3 0-30.1-12.4-30.1-27.7V204.5c0-15.1 14.8-27.5 30.1-27.5 15.1 0 27.5 12.4 27.5 27.5zm10.8 157c0 16.4 13.2 29.6 29.6 29.6h19.9l.3 61.1c0 36.9 55.2 36.6 55.2 0v-61.1h37.2v61.1c0 36.7 55.5 36.8 55.5 0v-61.1h20.2c16.2 0 29.4-13.2 29.4-29.6V182.1H100.4v179.4zm248-189.1H99.3c0-42.8 25.6-80 63.6-99.4l-19.1-35.3c-2.8-4.9 4.3-8 6.7-3.8l19.4 35.6c34.9-15.5 75-14.7 108.3 0L297.5 34c2.5-4.3 9.5-1.1 6.7 3.8L285.1 73c37.7 19.4 63.3 56.6 63.3 99.4zm-170.7-55.5c0-5.7-4.6-10.5-10.5-10.5-5.7 0-10.2 4.8-10.2 10.5s4.6 10.5 10.2 10.5c5.9 0 10.5-4.8 10.5-10.5zm113.4 0c0-5.7-4.6-10.5-10.2-10.5-5.9 0-10.5 4.8-10.5 10.5s4.6 10.5 10.5 10.5c5.6 0 10.2-4.8 10.2-10.5zm94.8 60.1c-15.1 0-27.5 12.1-27.5 27.5v115.8c0 15.4 12.4 27.7 27.5 27.7 15.4 0 30.1-12.4 30.1-27.7V204.5c0-15.4-14.8-27.5-30.1-27.5z"],angellist:[448,512,[],"f209","M347.1 215.4c11.7-32.6 45.4-126.9 45.4-157.1 0-26.6-15.7-48.9-43.7-48.9-44.6 0-84.6 131.7-97.1 163.1C242 144 196.6 0 156.6 0c-31.1 0-45.7 22.9-45.7 51.7 0 35.3 34.2 126.8 46.6 162-6.3-2.3-13.1-4.3-20-4.3-23.4 0-48.3 29.1-48.3 52.6 0 8.9 4.9 21.4 8 29.7-36.9 10-51.1 34.6-51.1 71.7C46 435.6 114.4 512 210.6 512c118 0 191.4-88.6 191.4-202.9 0-43.1-6.9-82-54.9-93.7zM311.7 108c4-12.3 21.1-64.3 37.1-64.3 8.6 0 10.9 8.9 10.9 16 0 19.1-38.6 124.6-47.1 148l-34-6 33.1-93.7zM142.3 48.3c0-11.9 14.5-45.7 46.3 47.1l34.6 100.3c-15.6-1.3-27.7-3-35.4 1.4-10.9-28.8-45.5-119.7-45.5-148.8zM140 244c29.3 0 67.1 94.6 67.1 107.4 0 5.1-4.9 11.4-10.6 11.4-20.9 0-76.9-76.9-76.9-97.7.1-7.7 12.7-21.1 20.4-21.1zm184.3 186.3c-29.1 32-66.3 48.6-109.7 48.6-59.4 0-106.3-32.6-128.9-88.3-17.1-43.4 3.8-68.3 20.6-68.3 11.4 0 54.3 60.3 54.3 73.1 0 4.9-7.7 8.3-11.7 8.3-16.1 0-22.4-15.5-51.1-51.4-29.7 29.7 20.5 86.9 58.3 86.9 26.1 0 43.1-24.2 38-42 3.7 0 8.3.3 11.7-.6 1.1 27.1 9.1 59.4 41.7 61.7 0-.9 2-7.1 2-7.4 0-17.4-10.6-32.6-10.6-50.3 0-28.3 21.7-55.7 43.7-71.7 8-6 17.7-9.7 27.1-13.1 9.7-3.7 20-8 27.4-15.4-1.1-11.2-5.7-21.1-16.9-21.1-27.7 0-120.6 4-120.6-39.7 0-6.7.1-13.1 17.4-13.1 32.3 0 114.3 8 138.3 29.1 18.1 16.1 24.3 113.2-31 174.7zm-98.6-126c9.7 3.1 19.7 4 29.7 6-7.4 5.4-14 12-20.3 19.1-2.8-8.5-6.2-16.8-9.4-25.1z"],angrycreative:[640,512,[],"f36e","M640 238.2l-3.2 28.2-34.5 2.3-2 18.1 34.5-2.3-3.2 28.2-34.4 2.2-2.3 20.1 34.4-2.2-3 26.1-64.7 4.1 12.7-113.2L527 365.2l-31.9 2-23.8-117.8 30.3-2 13.6 79.4 31.7-82.4 93.1-6.2zM426.8 371.5l28.3-1.8L468 249.6l-28.4 1.9-12.8 120zM162 388.1l-19.4-36-3.5 37.4-28.2 1.7 2.7-29.1c-11 18-32 34.3-56.9 35.8C23.9 399.9-3 377 .3 339.7c2.6-29.3 26.7-62.8 67.5-65.4 37.7-2.4 47.6 23.2 51.3 28.8l2.8-30.8 38.9-2.5c20.1-1.3 38.7 3.7 42.5 23.7l2.6-26.6 64.8-4.2-2.7 27.9-36.4 2.4-1.7 17.9 36.4-2.3-2.7 27.9-36.4 2.3-1.9 19.9 36.3-2.3-2.1 20.8 55-117.2 23.8-1.6L370.4 369l8.9-85.6-22.3 1.4 2.9-27.9 75-4.9-3 28-24.3 1.6-9.7 91.9-58 3.7-4.3-15.6-39.4 2.5-8 16.3-126.2 7.7zm-44.3-70.2l-26.4 1.7C84.6 307.2 76.9 303 65 303.8c-19 1.2-33.3 17.5-34.6 33.3-1.4 16 7.3 32.5 28.7 31.2 12.8-.8 21.3-8.6 28.9-18.9l27-1.7 2.7-29.8zm56.1-7.7c1.2-12.9-7.6-13.6-26.1-12.4l-2.7 28.5c14.2-.9 27.5-2.1 28.8-16.1zm21.1 70.8l5.8-60c-5 13.5-14.7 21.1-27.9 26.6l22.1 33.4zm135.4-45l-7.9-37.8-15.8 39.3 23.7-1.5zm-170.1-74.6l-4.3-17.5-39.6 2.6-8.1 18.2-31.9 2.1 57-121.9 23.9-1.6 30.7 102 9.9-104.7 27-1.8 37.8 63.6 6.5-66.6 28.5-1.9-4 41.2c7.4-13.5 22.9-44.7 63.6-47.5 40.5-2.8 52.4 29.3 53.4 30.3l3.3-32 39.3-2.7c12.7-.9 27.8.3 36.3 9.7l-4.4-11.9 32.2-2.2 12.9 43.2 23-45.7 31-2.2-43.6 78.4-4.8 44.3-28.4 1.9 4.8-44.3-15.8-43c1 22.3-9.2 40.1-32 49.6l25.2 38.8-36.4 2.4-19.2-36.8-4 38.3-28.4 1.9 3.3-31.5c-6.7 9.3-19.7 35.4-59.6 38-26.2 1.7-45.6-10.3-55.4-39.2l-4 40.3-25 1.6-37.6-63.3-6.3 66.2-56.8 3.7zm276.6-82.1c10.2-.7 17.5-2.1 21.6-4.3 4.5-2.4 7-6.4 7.6-12.1.6-5.3-.6-8.8-3.4-10.4-3.6-2.1-10.6-2.8-22.9-2l-2.9 28.8zM327.7 214c5.6 5.9 12.7 8.5 21.3 7.9 4.7-.3 9.1-1.8 13.3-4.1 5.5-3 10.6-8 15.1-14.3l-34.2 2.3 2.4-23.9 63.1-4.3 1.2-12-31.2 2.1c-4.1-3.7-7.8-6.6-11.1-8.1-4-1.7-8.1-2.8-12.2-2.5-8 .5-15.3 3.6-22 9.2-7.7 6.4-12 14.5-12.9 24.4-1.1 9.6 1.4 17.3 7.2 23.3zm-201.3 8.2l23.8-1.6-8.3-37.6-15.5 39.2z"],angular:[415,512,[],"f420","M169.7 268.1h76.2l-38.1-91.6-38.1 91.6zM207.8 32L0 106.4l31.8 275.7 176 97.9 176-97.9 31.8-275.7L207.8 32zM338 373.8h-48.6l-26.2-65.4H152.6l-26.2 65.4H77.7L207.8 81.5 338 373.8z"],"app-store":[512,512,[],"f36f","M255.9 120.9l9.1-15.7c5.6-9.8 18.1-13.1 27.9-7.5 9.8 5.6 13.1 18.1 7.5 27.9l-87.5 151.5h63.3c20.5 0 32 24.1 23.1 40.8H113.8c-11.3 0-20.4-9.1-20.4-20.4 0-11.3 9.1-20.4 20.4-20.4h52l66.6-115.4-20.8-36.1c-5.6-9.8-2.3-22.2 7.5-27.9 9.8-5.6 22.2-2.3 27.9 7.5l8.9 15.7zm-78.7 218l-19.6 34c-5.6 9.8-18.1 13.1-27.9 7.5-9.8-5.6-13.1-18.1-7.5-27.9l14.6-25.2c16.4-5.1 29.8-1.2 40.4 11.6zm168.9-61.7h53.1c11.3 0 20.4 9.1 20.4 20.4 0 11.3-9.1 20.4-20.4 20.4h-29.5l19.9 34.5c5.6 9.8 2.3 22.2-7.5 27.9-9.8 5.6-22.2 2.3-27.9-7.5-33.5-58.1-58.7-101.6-75.4-130.6-17.1-29.5-4.9-59.1 7.2-69.1 13.4 23 33.4 57.7 60.1 104zM256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm216 248c0 118.7-96.1 216-216 216-118.7 0-216-96.1-216-216 0-118.7 96.1-216 216-216 118.7 0 216 96.1 216 216z"],"app-store-ios":[448,512,[],"f370","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM127 384.5c-5.5 9.6-17.8 12.8-27.3 7.3-9.6-5.5-12.8-17.8-7.3-27.3l14.3-24.7c16.1-4.9 29.3-1.1 39.6 11.4L127 384.5zm138.9-53.9H84c-11 0-20-9-20-20s9-20 20-20h51l65.4-113.2-20.5-35.4c-5.5-9.6-2.2-21.8 7.3-27.3 9.6-5.5 21.8-2.2 27.3 7.3l8.9 15.4 8.9-15.4c5.5-9.6 17.8-12.8 27.3-7.3 9.6 5.5 12.8 17.8 7.3 27.3l-85.8 148.6h62.1c20.2 0 31.5 23.7 22.7 40zm98.1 0h-29l19.6 33.9c5.5 9.6 2.2 21.8-7.3 27.3-9.6 5.5-21.8 2.2-27.3-7.3-32.9-56.9-57.5-99.7-74-128.1-16.7-29-4.8-58 7.1-67.8 13.1 22.7 32.7 56.7 58.9 102h52c11 0 20 9 20 20 0 11.1-9 20-20 20z"],apper:[640,512,[],"f371","M42.1 239.1c22.2 0 29 2.8 33.5 14.6h.8v-22.9c0-11.3-4.8-15.4-17.9-15.4-11.3 0-14.4 2.5-15.1 12.8H4.8c.3-13.9 1.5-19.1 5.8-24.4C17.9 195 29.5 192 56.7 192c33 0 47.1 5 53.9 18.9 2 4.3 4 15.6 4 23.7v76.3H76.3l1.3-19.1h-1c-5.3 15.6-13.6 20.4-35.5 20.4-30.3 0-41.1-10.1-41.1-37.3 0-25.2 12.3-35.8 42.1-35.8zm17.1 48.1c13.1 0 16.9-3 16.9-13.4 0-9.1-4.3-11.6-19.6-11.6-13.1 0-17.9 3-17.9 12.1-.1 10.4 3.7 12.9 20.6 12.9zm77.8-94.9h38.3l-1.5 20.6h.8c9.1-17.1 15.9-20.9 37.5-20.9 14.4 0 24.7 3 31.5 9.1 9.8 8.6 12.8 20.4 12.8 48.1 0 30-3 43.1-12.1 52.9-6.8 7.3-16.4 10.1-33.2 10.1-20.4 0-29.2-5.5-33.8-21.2h-.8v70.3H137v-169zm80.9 60.7c0-27.5-3.3-32.5-20.7-32.5-16.9 0-20.7 5-20.7 28.7 0 28 3.5 33.5 21.2 33.5 16.4 0 20.2-5.6 20.2-29.7zm57.9-60.7h38.3l-1.5 20.6h.8c9.1-17.1 15.9-20.9 37.5-20.9 14.4 0 24.7 3 31.5 9.1 9.8 8.6 12.8 20.4 12.8 48.1 0 30-3 43.1-12.1 52.9-6.8 7.3-16.4 10.1-33.3 10.1-20.4 0-29.2-5.5-33.8-21.2h-.8v70.3h-39.5v-169zm80.9 60.7c0-27.5-3.3-32.5-20.7-32.5-16.9 0-20.7 5-20.7 28.7 0 28 3.5 33.5 21.2 33.5 16.4 0 20.2-5.6 20.2-29.7zm53.8-3.8c0-25.4 3.3-37.8 12.3-45.8 8.8-8.1 22.2-11.3 45.1-11.3 42.8 0 55.7 12.8 55.7 55.7v11.1h-75.3c-.3 2-.3 4-.3 4.8 0 16.9 4.5 21.9 20.1 21.9 13.9 0 17.9-3 17.9-13.9h37.5v2.3c0 9.8-2.5 18.9-6.8 24.7-7.3 9.8-19.6 13.6-44.3 13.6-27.5 0-41.6-3.3-50.6-12.3-8.5-8.5-11.3-21.3-11.3-50.8zm76.4-11.6c-.3-1.8-.3-3.3-.3-3.8 0-12.3-3.3-14.6-19.6-14.6-14.4 0-17.1 3-18.1 15.1l-.3 3.3h38.3zm55.6-45.3h38.3l-1.8 19.9h.7c6.8-14.9 14.4-20.2 29.7-20.2 10.8 0 19.1 3.3 23.4 9.3 5.3 7.3 6.8 14.4 6.8 34 0 1.5 0 5 .2 9.3h-35c.3-1.8.3-3.3.3-4 0-15.4-2-19.4-10.3-19.4-6.3 0-10.8 3.3-13.1 9.3-1 3-1 4.3-1 12.3v68h-38.3V192.3z"],apple:[448,512,[],"f179","M247.2 137.6c-6.2 1.9-15.3 3.5-27.9 4.6 1.1-56.7 29.9-96.6 88-110.1 9.3 41.6-26.1 94.1-60.1 105.5zm121.3 72.7c6.4-9.4 16.6-19.9 30.6-31.7-22.3-27.6-48.1-44.3-85.1-44.3-35.4 0-65.2 18.2-87 18.2-18.5 0-51.9-16.1-84.5-16.1-69.6 0-106.5 68.1-106.5 139C36 354.2 95.7 480 156.2 480c23.8 0 45.2-18 73.5-18 29.3 0 52.8 17.2 80.3 17.2 46 0 88.6-77.5 102-119.7-46.8-14.3-84.4-90.2-43.5-149.2z"],"apple-pay":[640,512,[],"f415","M116.9 158.5c-7.5 8.9-19.5 15.9-31.5 14.9-1.5-12 4.4-24.8 11.3-32.6 7.5-9.1 20.6-15.6 31.3-16.1 1.2 12.4-3.7 24.7-11.1 33.8m10.9 17.2c-17.4-1-32.3 9.9-40.5 9.9-8.4 0-21-9.4-34.8-9.1-17.9.3-34.5 10.4-43.6 26.5-18.8 32.3-4.9 80 13.3 106.3 8.9 13 19.5 27.3 33.5 26.8 13.3-.5 18.5-8.6 34.5-8.6 16.1 0 20.8 8.6 34.8 8.4 14.5-.3 23.6-13 32.5-26 10.1-14.8 14.3-29.1 14.5-29.9-.3-.3-28-10.9-28.3-42.9-.3-26.8 21.9-39.5 22.9-40.3-12.5-18.6-32-20.6-38.8-21.1m100.4-36.2v194.9h30.3v-66.6h41.9c38.3 0 65.1-26.3 65.1-64.3s-26.4-64-64.1-64h-73.2zm30.3 25.5h34.9c26.3 0 41.3 14 41.3 38.6s-15 38.8-41.4 38.8h-34.8V165zm162.2 170.9c19 0 36.6-9.6 44.6-24.9h.6v23.4h28v-97c0-28.1-22.5-46.3-57.1-46.3-32.1 0-55.9 18.4-56.8 43.6h27.3c2.3-12 13.4-19.9 28.6-19.9 18.5 0 28.9 8.6 28.9 24.5v10.8l-37.8 2.3c-35.1 2.1-54.1 16.5-54.1 41.5.1 25.2 19.7 42 47.8 42zm8.2-23.1c-16.1 0-26.4-7.8-26.4-19.6 0-12.3 9.9-19.4 28.8-20.5l33.6-2.1v11c0 18.2-15.5 31.2-36 31.2zm102.5 74.6c29.5 0 43.4-11.3 55.5-45.4L640 193h-30.8l-35.6 115.1h-.6L537.4 193h-31.6L557 334.9l-2.8 8.6c-4.6 14.6-12.1 20.3-25.5 20.3-2.4 0-7-.3-8.9-.5v23.4c1.8.4 9.3.7 11.6.7z"],asymmetrik:[576,512,[],"f372","M517.5 309.2c38.8-40 58.1-80 58.5-116.1.8-65.5-59.4-118.2-169.4-135C277.9 38.4 118.1 73.6 0 140.5 52 114 110.6 92.3 170.7 82.3c74.5-20.5 153-25.4 221.3-14.8C544.5 91.3 588.8 195 490.8 299.2c-10.2 10.8-22 21.1-35 30.6L304.9 103.4 114.7 388.9c-65.6-29.4-76.5-90.2-19.1-151.2 20.8-22.2 48.3-41.9 79.5-58.1 20-12.2 39.7-22.6 62-30.7-65.1 20.3-122.7 52.9-161.6 92.9-27.7 28.6-41.4 57.1-41.7 82.9-.5 35.1 23.4 65.1 68.4 83l-34.5 51.7h101.6l22-34.4c22.2 1 45.3 0 68.6-2.7l-22.8 37.1h135.5L340 406.3c18.6-5.3 36.9-11.5 54.5-18.7l45.9 71.8H542L468.6 349c18.5-12.1 35-25.5 48.9-39.8zm-187.6 80.5l-25-40.6-32.7 53.3c-23.4 3.5-46.7 5.1-69.2 4.4l101.9-159.3 78.7 123c-17.2 7.4-35.3 13.9-53.7 19.2z"],audible:[640,512,[],"f373","M640 199.9v54l-320 200L0 254v-54l320 200 320-200.1zm-194.5 72l47.1-29.4c-37.2-55.8-100.7-92.6-172.7-92.6-72 0-135.5 36.7-172.6 92.4h.3c2.5-2.3 5.1-4.5 7.7-6.7 89.7-74.4 219.4-58.1 290.2 36.3zm-220.1 18.8c16.9-11.9 36.5-18.7 57.4-18.7 34.4 0 65.2 18.4 86.4 47.6l45.4-28.4c-20.9-29.9-55.6-49.5-94.8-49.5-38.9 0-73.4 19.4-94.4 49zM103.6 161.1c131.8-104.3 318.2-76.4 417.5 62.1l.7 1 48.8-30.4C517.1 112.1 424.8 58.1 319.9 58.1c-103.5 0-196.6 53.5-250.5 135.6 9.9-10.5 22.7-23.5 34.2-32.6zm467 32.7z"],autoprefixer:[640,512,[],"f41c","M318.4 16l-161 480h77.5l25.4-81.4h119.5L405 496h77.5L318.4 16zm-40.3 341.9l41.2-130.4h1.5l40.9 130.4h-83.6zM640 405l-10-31.4L462.1 358l19.4 56.5L640 405zm-462.1-47L10 373.7 0 405l158.5 9.4 19.4-56.4z"],avianex:[512,512,[],"f374","M453.1 32h-312c-38.9 0-76.2 31.2-83.3 69.7L1.2 410.3C-5.9 448.8 19.9 480 58.9 480h312c38.9 0 76.2-31.2 83.3-69.7l56.7-308.5c7-38.6-18.8-69.8-57.8-69.8zm-58.2 347.3l-32 13.5-115.4-110c-14.7 10-29.2 19.5-41.7 27.1l22.1 64.2-17.9 12.7-40.6-61-52.4-48.1 15.7-15.4 58 31.1c9.3-10.5 20.8-22.6 32.8-34.9L203 228.9l-68.8-99.8 18.8-28.9 8.9-4.8L265 207.8l4.9 4.5c19.4-18.8 33.8-32.4 33.8-32.4 7.7-6.5 21.5-2.9 30.7 7.9 9 10.5 10.6 24.7 2.7 31.3-1.8 1.3-15.5 11.4-35.3 25.6l4.5 7.3 94.9 119.4-6.3 7.9z"],aviato:[640,512,[],"f421","M107.2 283.5l-19-41.8H36.1l-19 41.8H0l62.2-131.4 62.2 131.4h-17.2zm-45-98.1l-19.6 42.5h39.2l-19.6-42.5zm112.7 102.4l-62.2-131.4h17.1l45.1 96 45.1-96h17l-62.1 131.4zm80.6-4.3V156.4H271v127.1h-15.5zm209.1-115.6v115.6h-17.3V167.9h-41.2v-11.5h99.6v11.5h-41.1zM640 218.8c0 9.2-1.7 17.8-5.1 25.8-3.4 8-8.2 15.1-14.2 21.1-6 6-13.1 10.8-21.1 14.2-8 3.4-16.6 5.1-25.8 5.1s-17.8-1.7-25.8-5.1c-8-3.4-15.1-8.2-21.1-14.2-6-6-10.8-13-14.2-21.1-3.4-8-5.1-16.6-5.1-25.8s1.7-17.8 5.1-25.8c3.4-8 8.2-15.1 14.2-21.1 6-6 13-8.4 21.1-11.9 8-3.4 16.6-5.1 25.8-5.1s17.8 1.7 25.8 5.1c8 3.4 15.1 5.8 21.1 11.9 6 6 10.7 13.1 14.2 21.1 3.4 8 5.1 16.6 5.1 25.8zm-15.5 0c0-7.3-1.3-14-3.9-20.3-2.6-6.3-6.2-11.7-10.8-16.3-4.6-4.6-10-8.2-16.2-10.9-6.2-2.7-12.8-4-19.8-4s-13.6 1.3-19.8 4c-6.2 2.7-11.6 6.3-16.2 10.9-4.6 4.6-8.2 10-10.8 16.3-2.6 6.3-3.9 13.1-3.9 20.3 0 7.3 1.3 14 3.9 20.3 2.6 6.3 6.2 11.7 10.8 16.3 4.6 4.6 10 8.2 16.2 10.9 6.2 2.7 12.8 4 19.8 4s13.6-1.3 19.8-4c6.2-2.7 11.6-6.3 16.2-10.9 4.6-4.6 8.2-10 10.8-16.3 2.6-6.3 3.9-13.1 3.9-20.3zm-94.8 96.7v-6.3l88.9-10-242.9 13.4c.6-2.2 1.1-4.6 1.4-7.2.3-2 .5-4.2.6-6.5l64.8-8.1-64.9 1.9c0-.4-.1-.7-.1-1.1-2.8-17.2-25.5-23.7-25.5-23.7l-1.1-26.3h23.8l19 41.8h17.1L348.6 152l-62.2 131.4h17.1l19-41.8h23.6L345 268s-22.7 6.5-25.5 23.7c-.1.3-.1.7-.1 1.1l-64.9-1.9 64.8 8.1c.1 2.3.3 4.4.6 6.5.3 2.6.8 5 1.4 7.2L78.4 299.2l88.9 10v6.3c-5.9.9-10.5 6-10.5 12.2 0 6.8 5.6 12.4 12.4 12.4 6.8 0 12.4-5.6 12.4-12.4 0-6.2-4.6-11.3-10.5-12.2v-5.8l80.3 9v5.4c-5.7 1.1-9.9 6.2-9.9 12.1 0 6.8 5.6 10.2 12.4 10.2 6.8 0 12.4-3.4 12.4-10.2 0-6-4.3-11-9.9-12.1v-4.9l28.4 3.2v23.7h-5.9V360h5.9v-6.6h5v6.6h5.9v-13.8h-5.9V323l38.3 4.3c8.1 11.4 19 13.6 19 13.6l-.1 6.7-5.1.2-.1 12.1h4.1l.1-5h5.2l.1 5h4.1l-.1-12.1-5.1-.2-.1-6.7s10.9-2.1 19-13.6l38.3-4.3v23.2h-5.9V360h5.9v-6.6h5v6.6h5.9v-13.8h-5.9v-23.7l28.4-3.2v4.9c-5.7 1.1-9.9 6.2-9.9 12.1 0 6.8 5.6 10.2 12.4 10.2 6.8 0 12.4-3.4 12.4-10.2 0-6-4.3-11-9.9-12.1v-5.4l80.3-9v5.8c-5.9.9-10.5 6-10.5 12.2 0 6.8 5.6 12.4 12.4 12.4 6.8 0 12.4-5.6 12.4-12.4-.2-6.3-4.7-11.4-10.7-12.3zm-200.8-87.6l19.6-42.5 19.6 42.5h-17.9l-1.7-40.3-1.7 40.3h-17.9z"],aws:[512,512,[],"f375","M261.2 136.1c-14 57.5-13.1 54.4-25.8 107-1.6 6.5-4.1 8.4-10.7 8.5h-14.4c-5.8-.1-8.2-1.6-9.9-7.3-12.3-39.4-28.8-94.1-39.9-130.7-4.1-13.5-1.4-13.2 9.3-12.9 3.7.1 7.3 0 11 0 5.1.1 7.7 2 9.1 7.1 3.6 12.9 6 22.8 26.6 104.1.4 1.6.9 3.1 1.4 4.6h1.1c.5-2 1.1-3.9 1.6-5.9 7.8-32.9 15.5-65.9 23.3-98.8 2.4-10.2 6.7-11.2 17-11.2h7.6c6.9.1 9 1.5 10.7 8.3 6 23.4 23.5 101.8 26.7 110.4 5.1-18.3-1.8 7.9 28.5-109 2.1-8.1 4.1-9.7 12.3-9.7h12.7c5.4.1 7 1.8 5.7 7.1-2.4 9.5-2.9 9.9-41.3 132.9-3.1 9.9-4.2 10.8-14.6 10.8h-10.6c-7.3 0-9.2-1.3-11-8.4-4.3-16.2-23.3-95.7-26.4-106.9zM125.4 247.3c4.2 5.8 8.1 6.3 14.1 2.4l6.3-4.2c6.8-4.5 7.3-6.3 3.6-13.5-4.3-8.4-6.4-17.3-6.3-26.9 0-3.1.6-55.7-.9-66.8-2.7-19.3-12.5-32.8-31.7-38.7-10.7-3.4-21.7-3.3-32.7-3-15.1.4-29.4 4.6-42.8 11.4-1.8.9-3.7 3.1-4.1 4.9-.8 3.9-1.1 8.1-.7 12.1.6 5.9 2.6 7 8.2 5.1 5.1-1.7 10-3.9 15.1-5.4 14.5-4.4 29.2-6.4 44.1-1.7 7.1 2.2 11.7 6.9 14.3 13.8 3 7.9 2.4 16.1 2.4 24.2 0 5.5-.1 5.5-5.5 4.5-13.9-2.6-27.7-5-41.9-3.1-15.2 2.1-28.6 7.3-38.2 20-9.1 12-10 25.6-7.4 39.5 2.8 15 11.8 25.7 26.4 30.4 20.6 6.7 40.1 3.3 57.7-9.5 3.8-2.8 7.2-6.2 11.1-9.5 3.1 5 5.8 9.7 8.9 14zm-15.3-61.6c3 .4 4.5 1.9 4.3 5.1-.2 3.8.1 7.6-.3 11.4-1.2 11.7-7.7 19.7-17.9 24.9-8.2 4.2-16.9 5.8-26.1 5-15.2-1.3-21-13.1-19.6-26.3C51.8 193.2 59 186.2 72 184c13.8-2.4 16-1.1 38.1 1.7zm348.8 65.1c21.3-8.6 32.9-26.2 29.2-50-2.2-14.6-11.8-24.2-25.2-29.5-14.7-5.9-33.8-10.3-48.1-18.2-4.4-2.4-7.4-6.3-7.6-11.9-.4-11.1 4.2-17.2 15.4-19.8 9.3-2.1 18.8-2.2 28.1-.4 7.3 1.4 14.3 4.2 21.4 6.3 2.8.9 5.9 2.1 7.8-1.6 3.8-7.3.4-18.7-7.3-21.8-22.5-9-45.5-11.6-68.2-1.6-14.6 6.4-24.6 17.4-26 34.2-1.6 19.3 6.9 33.4 24.1 41.7 7.7 3.7 16.1 5.9 24.2 8.9 8.1 3 16.2 5.8 24.1 9.1 12.3 5.3 11.6 24.2 1.2 30-27.7 15.3-64.9-2.4-69.2-3.8-3.3-1.1-5.3.2-6.3 3.7-3 11.3.7 18.8 11.6 22.7 21.7 7.9 49.6 10.5 70.8 2zM296 413.5c50.8-5.8 98.7-20.8 142.7-47 8-4.7 15.5-10.3 23.1-15.7 7.3-5.2 3.2-18.4-11.3-12.2-54.4 23.2-111.2 36.1-170.2 38.9-30.5 1.5-60.8-.3-91.1-4.7-63.1-9.2-122.4-29.2-177.6-61.2-2.1-1.2-4.2-2.5-6.5-3-4.9-1.1-7.7 4.7-2.4 9.7 24 22.1 50.3 40.8 79.1 55.7 53.7 27.7 110.5 42.7 171.2 42 14.4-.8 28.8-.9 43-2.5zm174.7-92.2c14.8.8 19.4 5.9 15.7 20.2-3.8 14.8-9.3 29.2-13.9 43.8-.9 2.9-4.2 6.3-.8 8.8 3.7 2.6 6.5-1 9-3.3 10.2-9.5 17.4-21 22.5-33.8 5.4-13.4 9.3-27.2 8.7-41.9-.2-6.2-1.8-8.8-7.8-10.5-5.4-1.5-11-2.8-16.5-3.2-21.6-1.8-42.5.5-62 10.6-3.1 1.6-6 3.7-8.7 5.9-1.1.9-3.2 5.3 2.4 6.1 1.9.3 3.9-.1 5.9-.3 16.9-1.6 28.6-3.3 45.5-2.4z"],bandcamp:[496,512,[],"f2d5","M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm48.2 326.1h-181L199.9 178h181l-84.7 156.1z"],behance:[576,512,[],"f1b4","M232 237.2c31.8-15.2 48.4-38.2 48.4-74 0-70.6-52.6-87.8-113.3-87.8H0v354.4h171.8c64.4 0 124.9-30.9 124.9-102.9 0-44.5-21.1-77.4-64.7-89.7zM77.9 135.9H151c28.1 0 53.4 7.9 53.4 40.5 0 30.1-19.7 42.2-47.5 42.2h-79v-82.7zm83.3 233.7H77.9V272h84.9c34.3 0 56 14.3 56 50.6 0 35.8-25.9 47-57.6 47zm358.5-240.7H376V94h143.7v34.9zM576 305.2c0-75.9-44.4-139.2-124.9-139.2-78.2 0-131.3 58.8-131.3 135.8 0 79.9 50.3 134.7 131.3 134.7 61.3 0 101-27.6 120.1-86.3H509c-6.7 21.9-34.3 33.5-55.7 33.5-41.3 0-63-24.2-63-65.3h185.1c.3-4.2.6-8.7.6-13.2zM390.4 274c2.3-33.7 24.7-54.8 58.5-54.8 35.4 0 53.2 20.8 56.2 54.8H390.4z"],"behance-square":[512,512,[],"f1b5","M186.5 293c0 19.3-14 25.4-31.2 25.4h-45.1v-52.9h46c18.6.1 30.3 7.8 30.3 27.5zm-7.7-82.3c0-17.7-13.7-21.9-28.9-21.9h-39.6v44.8H153c15.1 0 25.8-6.6 25.8-22.9zm132.3 23.2c-18.3 0-30.5 11.4-31.7 29.7h62.2c-1.7-18.5-11.3-29.7-30.5-29.7zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zM271.7 185h77.8v-18.9h-77.8V185zm-43 110.3c0-24.1-11.4-44.9-35-51.6 17.2-8.2 26.2-17.7 26.2-37 0-38.2-28.5-47.5-61.4-47.5H68v192h93.1c34.9-.2 67.6-16.9 67.6-55.9zM380 280.5c0-41.1-24.1-75.4-67.6-75.4-42.4 0-71.1 31.8-71.1 73.6 0 43.3 27.3 73 71.1 73 33.2 0 54.7-14.9 65.1-46.8h-33.7c-3.7 11.9-18.6 18.1-30.2 18.1-22.4 0-34.1-13.1-34.1-35.3h100.2c.1-2.3.3-4.8.3-7.2z"],bimobject:[448,512,[],"f378","M416 32H32C14.4 32 0 46.4 0 64v384c0 17.6 14.4 32 32 32h384c17.6 0 32-14.4 32-32V64c0-17.6-14.4-32-32-32zm-64 257.4c0 49.4-11.4 82.6-103.8 82.6h-16.9c-44.1 0-62.4-14.9-70.4-38.8h-.9V368H96V136h64v74.7h1.1c4.6-30.5 39.7-38.8 69.7-38.8h17.3c92.4 0 103.8 33.1 103.8 82.5v35zm-64-28.9v22.9c0 21.7-3.4 33.8-38.4 33.8h-45.3c-28.9 0-44.1-6.5-44.1-35.7v-19c0-29.3 15.2-35.7 44.1-35.7h45.3c35-.2 38.4 12 38.4 33.7z"],bitbucket:[512,512,[],"f171","M23.1 32C14.2 31.9 7 38.9 6.9 47.8c0 .9.1 1.8.2 2.8L74.9 462c1.7 10.4 10.7 18 21.2 18.1h325.1c7.9.1 14.7-5.6 16-13.4l67.8-416c1.4-8.7-4.5-16.9-13.2-18.3-.9-.1-1.8-.2-2.8-.2L23.1 32zm285.3 297.3H204.6l-28.1-146.8h157l-25.1 146.8z"],bitcoin:[512,512,[],"f379","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-141.651-35.33c4.937-32.999-20.191-50.739-54.55-62.573l11.146-44.702-27.213-6.781-10.851 43.524c-7.154-1.783-14.502-3.464-21.803-5.13l10.929-43.81-27.198-6.781-11.153 44.686c-5.922-1.349-11.735-2.682-17.377-4.084l.031-.14-37.53-9.37-7.239 29.062s20.191 4.627 19.765 4.913c11.022 2.751 13.014 10.044 12.68 15.825l-12.696 50.925c.76.194 1.744.473 2.829.907-.907-.225-1.876-.473-2.876-.713l-17.796 71.338c-1.349 3.348-4.767 8.37-12.471 6.464.271.395-19.78-4.937-19.78-4.937l-13.51 31.147 35.414 8.827c6.588 1.651 13.045 3.379 19.4 5.006l-11.262 45.213 27.182 6.781 11.153-44.733a1038.209 1038.209 0 0 0 21.687 5.627l-11.115 44.523 27.213 6.781 11.262-45.128c46.404 8.781 81.299 5.239 95.986-36.727 11.836-33.79-.589-53.281-25.004-65.991 17.78-4.098 31.174-15.792 34.747-39.949zm-62.177 87.179c-8.41 33.79-65.308 15.523-83.755 10.943l14.944-59.899c18.446 4.603 77.6 13.717 68.811 48.956zm8.417-87.667c-7.673 30.736-55.031 15.12-70.393 11.292l13.548-54.327c15.363 3.828 64.836 10.973 56.845 43.035z"],bity:[496,512,[],"f37a","M78.4 67.2C173.8-22 324.5-24 421.5 71c14.3 14.1-6.4 37.1-22.4 21.5-84.8-82.4-215.8-80.3-298.9-3.2-16.3 15.1-36.5-8.3-21.8-22.1zm98.9 418.6c19.3 5.7 29.3-23.6 7.9-30C73 421.9 9.4 306.1 37.7 194.8c5-19.6-24.9-28.1-30.2-7.1-32.1 127.4 41.1 259.8 169.8 298.1zm148.1-2c121.9-40.2 192.9-166.9 164.4-291-4.5-19.7-34.9-13.8-30 7.9 24.2 107.7-37.1 217.9-143.2 253.4-21.2 7-10.4 36 8.8 29.7zm-62.9-79l.2-71.8c0-8.2-6.6-14.8-14.8-14.8-8.2 0-14.8 6.7-14.8 14.8l-.2 71.8c0 8.2 6.6 14.8 14.8 14.8s14.8-6.6 14.8-14.8zm71-269c2.1 90.9 4.7 131.9-85.5 132.5-92.5-.7-86.9-44.3-85.5-132.5 0-21.8-32.5-19.6-32.5 0v71.6c0 69.3 60.7 90.9 118 90.1 57.3.8 118-20.8 118-90.1v-71.6c0-19.6-32.5-21.8-32.5 0z"],"black-tie":[448,512,[],"f27e","M0 32v448h448V32H0zm316.5 325.2L224 445.9l-92.5-88.7 64.5-184-64.5-86.6h184.9L252 173.2l64.5 184z"],blackberry:[512,512,[],"f37b","M166 116.9c0 23.4-16.4 49.1-72.5 49.1H23.4l21-88.8h67.8c42.1 0 53.8 23.3 53.8 39.7zm126.2-39.7h-67.8L205.7 166h70.1c53.8 0 70.1-25.7 70.1-49.1.1-16.4-11.6-39.7-53.7-39.7zM88.8 208.1H21L0 296.9h70.1c56.1 0 72.5-23.4 72.5-49.1 0-16.3-11.7-39.7-53.8-39.7zm180.1 0h-67.8l-18.7 88.8h70.1c53.8 0 70.1-23.4 70.1-49.1 0-16.3-11.7-39.7-53.7-39.7zm189.3-53.8h-67.8l-18.7 88.8h70.1c53.8 0 70.1-23.4 70.1-49.1.1-16.3-11.6-39.7-53.7-39.7zm-28 137.9h-67.8L343.7 381h70.1c56.1 0 70.1-23.4 70.1-49.1 0-16.3-11.6-39.7-53.7-39.7zM240.8 346H173l-18.7 88.8h70.1c56.1 0 70.1-25.7 70.1-49.1.1-16.3-11.6-39.7-53.7-39.7z"],blogger:[448,512,[],"f37c","M162.4 196c4.8-4.9 6.2-5.1 36.4-5.1 27.2 0 28.1.1 32.1 2.1 5.8 2.9 8.3 7 8.3 13.6 0 5.9-2.4 10-7.6 13.4-2.8 1.8-4.5 1.9-31.1 2.1-16.4.1-29.5-.2-31.5-.8-10.3-2.9-14.1-17.7-6.6-25.3zm61.4 94.5c-53.9 0-55.8.2-60.2 4.1-3.5 3.1-5.7 9.4-5.1 13.9.7 4.7 4.8 10.1 9.2 12 2.2 1 14.1 1.7 56.3 1.2l47.9-.6 9.2-1.5c9-5.1 10.5-17.4 3.1-24.4-5.3-4.7-5-4.7-60.4-4.7zm223.4 130.1c-3.5 28.4-23 50.4-51.1 57.5-7.2 1.8-9.7 1.9-172.9 1.8-157.8 0-165.9-.1-172-1.8-8.4-2.2-15.6-5.5-22.3-10-5.6-3.8-13.9-11.8-17-16.4-3.8-5.6-8.2-15.3-10-22C.1 423 0 420.3 0 256.3 0 93.2 0 89.7 1.8 82.6 8.1 57.9 27.7 39 53 33.4c7.3-1.6 332.1-1.9 340-.3 21.2 4.3 37.9 17.1 47.6 36.4 7.7 15.3 7-1.5 7.3 180.6.2 115.8 0 164.5-.7 170.5zm-85.4-185.2c-1.1-5-4.2-9.6-7.7-11.5-1.1-.6-8-1.3-15.5-1.7-12.4-.6-13.8-.8-17.8-3.1-6.2-3.6-7.9-7.6-8-18.3 0-20.4-8.5-39.4-25.3-56.5-12-12.2-25.3-20.5-40.6-25.1-3.6-1.1-11.8-1.5-39.2-1.8-42.9-.5-52.5.4-67.1 6.2-27 10.7-46.3 33.4-53.4 62.4-1.3 5.4-1.6 14.2-1.9 64.3-.4 62.8 0 72.1 4 84.5 9.7 30.7 37.1 53.4 64.6 58.4 9.2 1.7 122.2 2.1 133.7.5 20.1-2.7 35.9-10.8 50.7-25.9 10.7-10.9 17.4-22.8 21.8-38.5 3.2-10.9 2.9-88.4 1.7-93.9z"],"blogger-b":[448,512,[],"f37d","M446.6 222.7c-1.8-8-6.8-15.4-12.5-18.5-1.8-1-13-2.2-25-2.7-20.1-.9-22.3-1.3-28.7-5-10.1-5.9-12.8-12.3-12.9-29.5-.1-33-13.8-63.7-40.9-91.3-19.3-19.7-40.9-33-65.5-40.5-5.9-1.8-19.1-2.4-63.3-2.9-69.4-.8-84.8.6-108.4 10C45.9 59.5 14.7 96.1 3.3 142.9 1.2 151.7.7 165.8.2 246.8c-.6 101.5.1 116.4 6.4 136.5 15.6 49.6 59.9 86.3 104.4 94.3 14.8 2.7 197.3 3.3 216 .8 32.5-4.4 58-17.5 81.9-41.9 17.3-17.7 28.1-36.8 35.2-62.1 4.9-17.6 4.5-142.8 2.5-151.7zm-322.1-63.6c7.8-7.9 10-8.2 58.8-8.2 43.9 0 45.4.1 51.8 3.4 9.3 4.7 13.4 11.3 13.4 21.9 0 9.5-3.8 16.2-12.3 21.6-4.6 2.9-7.3 3.1-50.3 3.3-26.5.2-47.7-.4-50.8-1.2-16.6-4.7-22.8-28.5-10.6-40.8zm191.8 199.8l-14.9 2.4-77.5.9c-68.1.8-87.3-.4-90.9-2-7.1-3.1-13.8-11.7-14.9-19.4-1.1-7.3 2.6-17.3 8.2-22.4 7.1-6.4 10.2-6.6 97.3-6.7 89.6-.1 89.1-.1 97.6 7.8 12.1 11.3 9.5 31.2-4.9 39.4z"],bluetooth:[448,512,[],"f293","M292.6 171.1L249.7 214l-.3-86 43.2 43.1m-43.2 219.8l43.1-43.1-42.9-42.9-.2 86zM416 259.4C416 465 344.1 512 230.9 512S32 465 32 259.4 115.4 0 228.6 0 416 53.9 416 259.4zm-158.5 0l79.4-88.6L211.8 36.5v176.9L138 139.6l-27 26.9 92.7 93-92.7 93 26.9 26.9 73.8-73.8 2.3 170 127.4-127.5-83.9-88.7z"],"bluetooth-b":[320,512,[],"f294","M196.48 260.023l92.626-103.333L143.125 0v206.33l-86.111-86.111-31.406 31.405 108.061 108.399L25.608 368.422l31.406 31.405 86.111-86.111L145.84 512l148.552-148.644-97.912-103.333zm40.86-102.996l-49.977 49.978-.338-100.295 50.315 50.317zM187.363 313.04l49.977 49.978-50.315 50.316.338-100.294z"],btc:[384,512,[],"f15a","M310.204 242.638c27.73-14.18 45.377-39.39 41.28-81.3-5.358-57.351-52.458-76.573-114.85-81.929V0h-48.528v77.203c-12.605 0-25.525.315-38.444.63V0h-48.528v79.409c-17.842.539-38.622.276-97.37 0v51.678c38.314-.678 58.417-3.14 63.023 21.427v217.429c-2.925 19.492-18.524 16.685-53.255 16.071L3.765 443.68c88.481 0 97.37.315 97.37.315V512h48.528v-67.06c13.234.315 26.154.315 38.444.315V512h48.528v-68.005c81.299-4.412 135.647-24.894 142.895-101.467 5.671-61.446-23.32-88.862-69.326-99.89zM150.608 134.553c27.415 0 113.126-8.507 113.126 48.528 0 54.515-85.71 48.212-113.126 48.212v-96.74zm0 251.776V279.821c32.772 0 133.127-9.138 133.127 53.255-.001 60.186-100.355 53.253-133.127 53.253z"],buromobelexperte:[448,512,[],"f37f","M0 32v128h128V32H0zm120 120H8V40h112v112zm40-120v128h128V32H160zm120 120H168V40h112v112zm40-120v128h128V32H320zm120 120H328V40h112v112zM0 192v128h128V192H0zm120 120H8V200h112v112zm40-120v128h128V192H160zm120 120H168V200h112v112zm40-120v128h128V192H320zm120 120H328V200h112v112zM0 352v128h128V352H0zm120 120H8V360h112v112zm40-120v128h128V352H160zm120 120H168V360h112v112zm40-120v128h128V352H320z"],buysellads:[448,512,[],"f20d","M224 150.7l42.9 160.7h-85.8L224 150.7zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-65.3 325.3l-94.5-298.7H159.8L65.3 405.3H156l111.7-91.6 24.2 91.6h90.8z"],"cc-amex":[576,512,[],"f1f3","M576 255.4c-37.9-.2-44.2-.9-54.5 5v-5c-45.3 0-53.5-1.7-64.9 5.2v-5.2h-78.2v5.1c-11.4-6.5-21.4-5.1-75.7-5.1v5.6c-6.3-3.7-14.5-5.6-24.3-5.6h-58c-3.5 3.8-12.5 13.7-15.7 17.2-12.7-14.1-10.5-11.6-15.5-17.2h-83.1v92.3h82c3.3-3.5 12.9-13.9 16.1-17.4 12.7 14.3 10.3 11.7 15.4 17.4h48.9c0-14.7.1-8.3.1-23 11.5.2 24.3-.2 34.3-6.2 0 13.9-.1 17.1-.1 29.2h39.6c0-18.5.1-7.4.1-25.3 6.2 0 7.7 0 9.4.1.1 1.3 0 0 0 25.2 152.8 0 145.9 1.1 156.7-4.5v4.5c34.8 0 54.8 2.2 67.5-6.1V432c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V228.3h26.6c4.2-10.1 2.2-5.3 6.4-15.3h19.2c4.2 10 2.2 5.2 6.4 15.3h52.9v-11.4c2.2 5 1.1 2.5 5.1 11.4h29.5c2.4-5.5 2.6-5.8 5.1-11.4v11.4h135.5v-25.1c6.4 0 8-.1 9.8.2 0 0-.2 10.9.1 24.8h66.5v-8.9c7.4 5.9 17.4 8.9 29.7 8.9h26.8c4.2-10.1 2.2-5.3 6.4-15.3h19c6.5 15 .2.5 6.6 15.3h52.8v-21.9c11.8 19.7 7.8 12.9 13.2 21.9h41.6v-92h-39.9v18.4c-12.2-20.2-6.3-10.4-11.2-18.4h-43.3v20.6c-6.2-14.6-4.6-10.8-8.8-20.6h-32.4c-.4 0-2.3.2-2.3-.3h-27.6c-12.8 0-23.1 3.2-30.7 9.3v-9.3h-39.9v5.3c-10.8-6.1-20.7-5.1-64.4-5.3-.1 0-11.6-.1-11.6 0h-103c-2.5 6.1-6.8 16.4-12.6 30-2.8-6-11-23.8-13.9-30h-46V157c-7.4-17.4-4.7-11-9-21.1H22.9c-3.4 7.9-13.7 32-23.1 53.9V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48v175.4zm-186.6-80.6c-.3.2-1.4 2.2-1.4 7.6 0 6 .9 7.7 1.1 7.9.2.1 1.1.5 3.4.5l7.3-16.9c-1.1 0-2.1-.1-3.1-.1-5.6 0-7 .7-7.3 1zm-19.9 130.9c9.2 3.3 11 9.5 11 18.4l-.1 13.8h-16.6l.1-11.5c0-11.8-3.8-13.8-14.8-13.8h-17.6l-.1 25.3h-16.6l.1-69.3h39.4c13 0 27.1 2.3 27.1 18.7-.1 7.6-4.2 15.3-11.9 18.4zm-6.3-15.4c0-6.4-5.6-7.4-10.7-7.4h-21v15.6h20.7c5.6 0 11-1.3 11-8.2zm181.7-7.1H575v-14.6h-32.9c-12.8 0-23.8 6.6-23.8 20.7 0 33 42.7 12.8 42.7 27.4 0 5.1-4.3 6.4-8.4 6.4h-32l-.1 14.8h32c8.4 0 17.6-1.8 22.5-8.9v-25.8c-10.5-13.8-39.3-1.3-39.3-13.5 0-5.8 4.6-6.5 9.2-6.5zm-99.2-.3v-14.3h-55.2l-.1 69.3h55.2l.1-14.3-38.6-.3v-13.8H445v-14.1h-37.8v-12.5h38.5zm42.2 40.1h-32.2l-.1 14.8h32.2c14.8 0 26.2-5.6 26.2-22 0-33.2-42.9-11.2-42.9-26.3 0-5.6 4.9-6.4 9.2-6.4h30.4v-14.6h-33.2c-12.8 0-23.5 6.6-23.5 20.7 0 33 42.7 12.5 42.7 27.4-.1 5.4-4.7 6.4-8.8 6.4zm-78.1-158.7c-17.4-.3-33.2-4.1-33.2 19.7 0 11.8 2.8 19.9 16.1 19.9h7.4l23.5-54.5h24.8l27.9 65.4v-65.4h25.3l29.1 48.1v-48.1h16.9v69H524l-31.2-51.9v51.9h-33.7l-6.6-15.3h-34.3l-6.4 15.3h-19.2c-22.8 0-33-11.8-33-34 0-23.3 10.5-35.3 34-35.3h16.1v15.2zm14.3 24.5h22.8l-11.2-27.6-11.6 27.6zm-72.6-39.6h-16.9v69.3h16.9v-69.3zm-38.1 37.3c9.5 3.3 11 9.2 11 18.4v13.5h-16.6c-.3-14.8 3.6-25.1-14.8-25.1h-18v25.1h-16.4v-69.3l39.1.3c13.3 0 27.4 2 27.4 18.4.1 8-4.3 15.7-11.7 18.7zm-6.7-15.3c0-6.4-5.6-7.4-10.7-7.4h-21v15.3h20.7c5.7 0 11-1.3 11-7.9zm-59.5-7.4v-14.6h-55.5v69.3h55.5v-14.3h-38.9v-13.8h37.8v-14.1h-37.8v-12.5h38.9zm-84.6 54.7v-54.2l-24 54.2H124l-24-54.2v54.2H66.2l-6.4-15.3H25.3l-6.4 15.3H1l29.7-69.3h24.5l28.1 65.7v-65.7h27.1l21.7 47 19.7-47h27.6v69.3h-16.8zM53.9 188.8l-11.5-27.6-11.2 27.6h22.7zm253 102.5c0 27.9-30.4 23.3-49.3 23.3l-.1 23.3h-32.2l-20.4-23-21.3 23h-65.4l.1-69.3h66.5l20.5 22.8 21-22.8H279c15.6 0 27.9 5.4 27.9 22.7zm-112.7 11.8l-17.9-20.2h-41.7v12.5h36.3v14.1h-36.3v13.8h40.6l19-20.2zM241 276l-25.3 27.4 25.3 28.1V276zm48.3 15.3c0-6.1-4.6-8.4-10.2-8.4h-21.5v17.6h21.2c5.9 0 10.5-2.8 10.5-9.2z"],"cc-apple-pay":[576,512,[],"f416","M302.2 218.4c0 17.2-10.5 27.1-29 27.1h-24.3v-54.2h24.4c18.4 0 28.9 9.8 28.9 27.1zm47.5 62.6c0 8.3 7.2 13.7 18.5 13.7 14.4 0 25.2-9.1 25.2-21.9v-7.7l-23.5 1.5c-13.3.9-20.2 5.8-20.2 14.4zM576 79v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM127.8 197.2c8.4.7 16.8-4.2 22.1-10.4 5.2-6.4 8.6-15 7.7-23.7-7.4.3-16.6 4.9-21.9 11.3-4.8 5.5-8.9 14.4-7.9 22.8zm60.6 74.5c-.2-.2-19.6-7.6-19.8-30-.2-18.7 15.3-27.7 16-28.2-8.8-13-22.4-14.4-27.1-14.7-12.2-.7-22.6 6.9-28.4 6.9-5.9 0-14.7-6.6-24.3-6.4-12.5.2-24.2 7.3-30.5 18.6-13.1 22.6-3.4 56 9.3 74.4 6.2 9.1 13.7 19.1 23.5 18.7 9.3-.4 13-6 24.2-6 11.3 0 14.5 6 24.3 5.9 10.2-.2 16.5-9.1 22.8-18.2 6.9-10.4 9.8-20.4 10-21zm135.4-53.4c0-26.6-18.5-44.8-44.9-44.8h-51.2v136.4h21.2v-46.6h29.3c26.8 0 45.6-18.4 45.6-45zm90 23.7c0-19.7-15.8-32.4-40-32.4-22.5 0-39.1 12.9-39.7 30.5h19.1c1.6-8.4 9.4-13.9 20-13.9 13 0 20.2 6 20.2 17.2v7.5l-26.4 1.6c-24.6 1.5-37.9 11.6-37.9 29.1 0 17.7 13.7 29.4 33.4 29.4 13.3 0 25.6-6.7 31.2-17.4h.4V310h19.6v-68zM516 210.9h-21.5l-24.9 80.6h-.4l-24.9-80.6H422l35.9 99.3-1.9 6c-3.2 10.2-8.5 14.2-17.9 14.2-1.7 0-4.9-.2-6.2-.3v16.4c1.2.4 6.5.5 8.1.5 20.7 0 30.4-7.9 38.9-31.8L516 210.9z"],"cc-diners-club":[576,512,[],"f24c","M239.7 79.9c-96.9 0-175.8 78.6-175.8 175.8 0 96.9 78.9 175.8 175.8 175.8 97.2 0 175.8-78.9 175.8-175.8 0-97.2-78.6-175.8-175.8-175.8zm-39.9 279.6c-41.7-15.9-71.4-56.4-71.4-103.8s29.7-87.9 71.4-104.1v207.9zm79.8.3V151.6c41.7 16.2 71.4 56.7 71.4 104.1s-29.7 87.9-71.4 104.1zM528 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM329.7 448h-90.3c-106.2 0-193.8-85.5-193.8-190.2C45.6 143.2 133.2 64 239.4 64h90.3c105 0 200.7 79.2 200.7 193.8 0 104.7-95.7 190.2-200.7 190.2z"],"cc-discover":[576,512,[],"f1f2","M83 212.1c0 7.9-3.2 15.5-8.9 20.7-4.9 4.4-11.6 6.4-21.9 6.4H48V185h4.2c10.3 0 16.7 1.7 21.9 6.6 5.7 5 8.9 12.6 8.9 20.5zM504.8 184h-4.9v24.9h4.7c10.3 0 15.8-4.4 15.8-12.8 0-7.9-5.5-12.1-15.6-12.1zM576 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM428 253h45.3v-13.8H444V217h28.3v-13.8H444V185h29.3v-14H428v82zm-86.2-82l35 84.2h8.6l35.5-84.2h-17.5l-22.2 55.2-21.9-55.2h-17.5zm-83 41.6c0 24.6 19.9 44.6 44.6 44.6 24.6 0 44.6-19.9 44.6-44.6 0-24.6-19.9-44.6-44.6-44.6-24.6 0-44.6 19.9-44.6 44.6zm-68-.5c0 32.5 33.6 52.5 63.3 38.2v-19c-19.3 19.3-46.8 5.8-46.8-19.2 0-23.7 26.7-39.1 46.8-19v-19c-30.2-15-63.3 6.8-63.3 38zm-33.9 28.3c-7.6 0-13.8-3.7-17.5-10.8l-10.3 9.9c17.8 26.1 56.6 18.2 56.6-11.3 0-13.1-5.4-19-23.6-25.6-9.6-3.4-12.3-5.9-12.3-10.3 0-8.7 14.5-14.1 24.9-2.5l8.4-10.8c-19.1-17.1-49.7-8.9-49.7 14.3 0 11.3 5.2 17.2 20.2 22.7 25.7 9.1 14.7 24.4 3.3 24.4zm-57.4-28.3c0-24.1-18-41.1-44.1-41.1H32v82h23.4c30.9 0 44.1-22.4 44.1-40.9zm23.4-41.1h-16v82h16v-82zM544 288c-33.3 20.8-226.4 124.4-416 160h401c8.2 0 15-6.8 15-15V288zm0-35l-25.9-34.5c12.1-2.5 18.7-10.6 18.7-23.2 0-28.5-30.3-24.4-52.9-24.4v82h16v-32.8h2.2l22.2 32.8H544z"],"cc-jcb":[576,512,[],"f24b","M431.5 244.3V212c41.2 0 38.5.2 38.5.2 7.3 1.3 13.3 7.3 13.3 16 0 8.8-6 14.5-13.3 15.8-1.2.4-3.3.3-38.5.3zm42.8 20.2c-2.8-.7-3.3-.5-42.8-.5v35c39.6 0 40 .2 42.8-.5 7.5-1.5 13.5-8 13.5-17 0-8.7-6-15.5-13.5-17zM576 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM182 192.3h-57c0 67.1 10.7 109.7-35.8 109.7-19.5 0-38.8-5.7-57.2-14.8v28c30 8.3 68 8.3 68 8.3 97.9 0 82-47.7 82-131.2zm178.5 4.5c-63.4-16-165-14.9-165 59.3 0 77.1 108.2 73.6 165 59.2V287C312.9 311.7 253 309 253 256s59.8-55.6 107.5-31.2v-28zM544 286.5c0-18.5-16.5-30.5-38-32v-.8c19.5-2.7 30.3-15.5 30.3-30.2 0-19-15.7-30-37-31 0 0 6.3-.3-120.3-.3v127.5h122.7c24.3.1 42.3-12.9 42.3-33.2z"],"cc-mastercard":[576,512,[],"f1f1","M482.9 410.3c0 6.8-4.6 11.7-11.2 11.7-6.8 0-11.2-5.2-11.2-11.7 0-6.5 4.4-11.7 11.2-11.7 6.6 0 11.2 5.2 11.2 11.7zm-310.8-11.7c-7.1 0-11.2 5.2-11.2 11.7 0 6.5 4.1 11.7 11.2 11.7 6.5 0 10.9-4.9 10.9-11.7-.1-6.5-4.4-11.7-10.9-11.7zm117.5-.3c-5.4 0-8.7 3.5-9.5 8.7h19.1c-.9-5.7-4.4-8.7-9.6-8.7zm107.8.3c-6.8 0-10.9 5.2-10.9 11.7 0 6.5 4.1 11.7 10.9 11.7 6.8 0 11.2-4.9 11.2-11.7 0-6.5-4.4-11.7-11.2-11.7zm105.9 26.1c0 .3.3.5.3 1.1 0 .3-.3.5-.3 1.1-.3.3-.3.5-.5.8-.3.3-.5.5-1.1.5-.3.3-.5.3-1.1.3-.3 0-.5 0-1.1-.3-.3 0-.5-.3-.8-.5-.3-.3-.5-.5-.5-.8-.3-.5-.3-.8-.3-1.1 0-.5 0-.8.3-1.1 0-.5.3-.8.5-1.1.3-.3.5-.3.8-.5.5-.3.8-.3 1.1-.3.5 0 .8 0 1.1.3.5.3.8.3 1.1.5s.2.6.5 1.1zm-2.2 1.4c.5 0 .5-.3.8-.3.3-.3.3-.5.3-.8 0-.3 0-.5-.3-.8-.3 0-.5-.3-1.1-.3h-1.6v3.5h.8V426h.3l1.1 1.4h.8l-1.1-1.3zM576 81v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V81c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM64 220.6c0 76.5 62.1 138.5 138.5 138.5 27.2 0 53.9-8.2 76.5-23.1-72.9-59.3-72.4-171.2 0-230.5-22.6-15-49.3-23.1-76.5-23.1-76.4-.1-138.5 62-138.5 138.2zm224 108.8c70.5-55 70.2-162.2 0-217.5-70.2 55.3-70.5 162.6 0 217.5zm-142.3 76.3c0-8.7-5.7-14.4-14.7-14.7-4.6 0-9.5 1.4-12.8 6.5-2.4-4.1-6.5-6.5-12.2-6.5-3.8 0-7.6 1.4-10.6 5.4V392h-8.2v36.7h8.2c0-18.9-2.5-30.2 9-30.2 10.2 0 8.2 10.2 8.2 30.2h7.9c0-18.3-2.5-30.2 9-30.2 10.2 0 8.2 10 8.2 30.2h8.2v-23zm44.9-13.7h-7.9v4.4c-2.7-3.3-6.5-5.4-11.7-5.4-10.3 0-18.2 8.2-18.2 19.3 0 11.2 7.9 19.3 18.2 19.3 5.2 0 9-1.9 11.7-5.4v4.6h7.9V392zm40.5 25.6c0-15-22.9-8.2-22.9-15.2 0-5.7 11.9-4.8 18.5-1.1l3.3-6.5c-9.4-6.1-30.2-6-30.2 8.2 0 14.3 22.9 8.3 22.9 15 0 6.3-13.5 5.8-20.7.8l-3.5 6.3c11.2 7.6 32.6 6 32.6-7.5zm35.4 9.3l-2.2-6.8c-3.8 2.1-12.2 4.4-12.2-4.1v-16.6h13.1V392h-13.1v-11.2h-8.2V392h-7.6v7.3h7.6V416c0 17.6 17.3 14.4 22.6 10.9zm13.3-13.4h27.5c0-16.2-7.4-22.6-17.4-22.6-10.6 0-18.2 7.9-18.2 19.3 0 20.5 22.6 23.9 33.8 14.2l-3.8-6c-7.8 6.4-19.6 5.8-21.9-4.9zm59.1-21.5c-4.6-2-11.6-1.8-15.2 4.4V392h-8.2v36.7h8.2V408c0-11.6 9.5-10.1 12.8-8.4l2.4-7.6zm10.6 18.3c0-11.4 11.6-15.1 20.7-8.4l3.8-6.5c-11.6-9.1-32.7-4.1-32.7 15 0 19.8 22.4 23.8 32.7 15l-3.8-6.5c-9.2 6.5-20.7 2.6-20.7-8.6zm66.7-18.3H408v4.4c-8.3-11-29.9-4.8-29.9 13.9 0 19.2 22.4 24.7 29.9 13.9v4.6h8.2V392zm33.7 0c-2.4-1.2-11-2.9-15.2 4.4V392h-7.9v36.7h7.9V408c0-11 9-10.3 12.8-8.4l2.4-7.6zm40.3-14.9h-7.9v19.3c-8.2-10.9-29.9-5.1-29.9 13.9 0 19.4 22.5 24.6 29.9 13.9v4.6h7.9v-51.7zm7.6-75.1v4.6h.8V302h1.9v-.8h-4.6v.8h1.9zm6.6 123.8c0-.5 0-1.1-.3-1.6-.3-.3-.5-.8-.8-1.1-.3-.3-.8-.5-1.1-.8-.5 0-1.1-.3-1.6-.3-.3 0-.8.3-1.4.3-.5.3-.8.5-1.1.8-.5.3-.8.8-.8 1.1-.3.5-.3 1.1-.3 1.6 0 .3 0 .8.3 1.4 0 .3.3.8.8 1.1.3.3.5.5 1.1.8.5.3 1.1.3 1.4.3.5 0 1.1 0 1.6-.3.3-.3.8-.5 1.1-.8.3-.3.5-.8.8-1.1.3-.6.3-1.1.3-1.4zm3.2-124.7h-1.4l-1.6 3.5-1.6-3.5h-1.4v5.4h.8v-4.1l1.6 3.5h1.1l1.4-3.5v4.1h1.1v-5.4zm4.4-80.5c0-76.2-62.1-138.3-138.5-138.3-27.2 0-53.9 8.2-76.5 23.1 72.1 59.3 73.2 171.5 0 230.5 22.6 15 49.5 23.1 76.5 23.1 76.4.1 138.5-61.9 138.5-138.4z"],"cc-paypal":[576,512,[],"f1f4","M186.3 258.2c0 12.2-9.7 21.5-22 21.5-9.2 0-16-5.2-16-15 0-12.2 9.5-22 21.7-22 9.3 0 16.3 5.7 16.3 15.5zM80.5 209.7h-4.7c-1.5 0-3 1-3.2 2.7l-4.3 26.7 8.2-.3c11 0 19.5-1.5 21.5-14.2 2.3-13.4-6.2-14.9-17.5-14.9zm284 0H360c-1.8 0-3 1-3.2 2.7l-4.2 26.7 8-.3c13 0 22-3 22-18-.1-10.6-9.6-11.1-18.1-11.1zM576 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM128.3 215.4c0-21-16.2-28-34.7-28h-40c-2.5 0-5 2-5.2 4.7L32 294.2c-.3 2 1.2 4 3.2 4h19c2.7 0 5.2-2.9 5.5-5.7l4.5-26.6c1-7.2 13.2-4.7 18-4.7 28.6 0 46.1-17 46.1-45.8zm84.2 8.8h-19c-3.8 0-4 5.5-4.2 8.2-5.8-8.5-14.2-10-23.7-10-24.5 0-43.2 21.5-43.2 45.2 0 19.5 12.2 32.2 31.7 32.2 9 0 20.2-4.9 26.5-11.9-.5 1.5-1 4.7-1 6.2 0 2.3 1 4 3.2 4H200c2.7 0 5-2.9 5.5-5.7l10.2-64.3c.3-1.9-1.2-3.9-3.2-3.9zm40.5 97.9l63.7-92.6c.5-.5.5-1 .5-1.7 0-1.7-1.5-3.5-3.2-3.5h-19.2c-1.7 0-3.5 1-4.5 2.5l-26.5 39-11-37.5c-.8-2.2-3-4-5.5-4h-18.7c-1.7 0-3.2 1.8-3.2 3.5 0 1.2 19.5 56.8 21.2 62.1-2.7 3.8-20.5 28.6-20.5 31.6 0 1.8 1.5 3.2 3.2 3.2h19.2c1.8-.1 3.5-1.1 4.5-2.6zm159.3-106.7c0-21-16.2-28-34.7-28h-39.7c-2.7 0-5.2 2-5.5 4.7l-16.2 102c-.2 2 1.3 4 3.2 4h20.5c2 0 3.5-1.5 4-3.2l4.5-29c1-7.2 13.2-4.7 18-4.7 28.4 0 45.9-17 45.9-45.8zm84.2 8.8h-19c-3.8 0-4 5.5-4.3 8.2-5.5-8.5-14-10-23.7-10-24.5 0-43.2 21.5-43.2 45.2 0 19.5 12.2 32.2 31.7 32.2 9.3 0 20.5-4.9 26.5-11.9-.3 1.5-1 4.7-1 6.2 0 2.3 1 4 3.2 4H484c2.7 0 5-2.9 5.5-5.7l10.2-64.3c.3-1.9-1.2-3.9-3.2-3.9zm47.5-33.3c0-2-1.5-3.5-3.2-3.5h-18.5c-1.5 0-3 1.2-3.2 2.7l-16.2 104-.3.5c0 1.8 1.5 3.5 3.5 3.5h16.5c2.5 0 5-2.9 5.2-5.7L544 191.2v-.3zm-90 51.8c-12.2 0-21.7 9.7-21.7 22 0 9.7 7 15 16.2 15 12 0 21.7-9.2 21.7-21.5.1-9.8-6.9-15.5-16.2-15.5z"],"cc-stripe":[576,512,[],"f1f5","M396.9 256.5c0 19.1-8.8 33.4-21.9 33.4-8.3 0-13.3-3-16.8-6.7l-.2-52.8c3.7-4.1 8.8-7 17-7 12.9-.1 21.9 14.5 21.9 33.1zM576 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM122.2 281.1c0-42.3-54.3-34.7-54.3-50.7 0-5.5 4.6-7.7 12.1-7.7 10.8 0 24.5 3.3 35.3 9.1v-33.4c-11.8-4.7-23.5-6.5-35.3-6.5-28.8 0-48 15-48 40.2 0 39.3 54 32.9 54 49.9 0 6.6-5.7 8.7-13.6 8.7-11.8 0-26.9-4.9-38.9-11.3v33.9c13.2 5.7 26.6 8.1 38.8 8.1 29.6-.2 49.9-14.7 49.9-40.3zm68.9-86.9h-27v-30.8l-34.7 7.4-.2 113.9c0 21 15.8 36.5 36.9 36.5 11.6 0 20.2-2.1 24.9-4.7v-28.9c-4.5 1.8-27 8.3-27-12.6v-50.5h27v-30.3zm73.8 0c-4.7-1.7-21.3-4.8-29.6 10.5l-2.2-10.5h-30.7v124.5h35.5v-84.4c8.4-11 22.6-8.9 27.1-7.4v-32.7zm44.2 0h-35.7v124.5h35.7V194.2zm0-47.3l-35.7 7.6v28.9l35.7-7.6v-28.9zm122.7 108.8c0-41.3-23.5-63.8-48.4-63.8-13.9 0-22.9 6.6-27.8 11.1l-1.8-8.8h-31.3V360l35.5-7.5.1-40.2c5.1 3.7 12.7 9 25.1 9 25.4-.1 48.6-20.5 48.6-65.6zm112.2 1.2c0-36.4-17.6-65.1-51.3-65.1-33.8 0-54.3 28.7-54.3 64.9 0 42.8 24.2 64.5 58.8 64.5 17 0 29.7-3.9 39.4-9.2v-28.6c-9.7 4.9-20.8 7.9-34.9 7.9-13.8 0-26-4.9-27.6-21.5h69.5c.1-2 .4-9.4.4-12.9zm-51.6-36.1c-8.9 0-18.7 6.7-18.7 22.7h36.7c0-16-9.3-22.7-18-22.7z"],"cc-visa":[576,512,[],"f1f0","M470.1 231.3s7.6 37.2 9.3 45H446c3.3-8.9 16-43.5 16-43.5-.2.3 3.3-9.1 5.3-14.9l2.8 13.4zM576 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48zM152.5 331.2L215.7 176h-42.5l-39.3 106-4.3-21.5-14-71.4c-2.3-9.9-9.4-12.7-18.2-13.1H32.7l-.7 3.1c15.8 4 29.9 9.8 42.2 17.1l35.8 135h42.5zm94.4.2L272.1 176h-40.2l-25.1 155.4h40.1zm139.9-50.8c.2-17.7-10.6-31.2-33.7-42.3-14.1-7.1-22.7-11.9-22.7-19.2.2-6.6 7.3-13.4 23.1-13.4 13.1-.3 22.7 2.8 29.9 5.9l3.6 1.7 5.5-33.6c-7.9-3.1-20.5-6.6-36-6.6-39.7 0-67.6 21.2-67.8 51.4-.3 22.3 20 34.7 35.2 42.2 15.5 7.6 20.8 12.6 20.8 19.3-.2 10.4-12.6 15.2-24.1 15.2-16 0-24.6-2.5-37.7-8.3l-5.3-2.5-5.6 34.9c9.4 4.3 26.8 8.1 44.8 8.3 42.2.1 69.7-20.8 70-53zM528 331.4L495.6 176h-31.1c-9.6 0-16.9 2.8-21 12.9l-59.7 142.5H426s6.9-19.2 8.4-23.3H486c1.2 5.5 4.8 23.3 4.8 23.3H528z"],centercode:[512,512,[],"f380","M329.2 268.6c-3.8 35.2-35.4 60.6-70.6 56.8-35.2-3.8-60.6-35.4-56.8-70.6 3.8-35.2 35.4-60.6 70.6-56.8 35.1 3.8 60.6 35.4 56.8 70.6zm-85.8 235.1C96.7 496-8.2 365.5 10.1 224.3c11.2-86.6 65.8-156.9 139.1-192 161-77.1 349.7 37.4 354.7 216.6 4.1 147-118.4 262.2-260.5 254.8zm179.9-180c27.9-118-160.5-205.9-237.2-234.2-57.5 56.3-69.1 188.6-33.8 344.4 68.8 15.8 169.1-26.4 271-110.2z"],chrome:[496,512,[],"f268","M131.5 217.5L55.1 100.1c47.6-59.2 119-91.8 192-92.1 42.3-.3 85.5 10.5 124.8 33.2 43.4 25.2 76.4 61.4 97.4 103L264 133.4c-58.1-3.4-113.4 29.3-132.5 84.1zm32.9 38.5c0 46.2 37.4 83.6 83.6 83.6s83.6-37.4 83.6-83.6-37.4-83.6-83.6-83.6-83.6 37.3-83.6 83.6zm314.9-89.2L339.6 174c37.9 44.3 38.5 108.2 6.6 157.2L234.1 503.6c46.5 2.5 94.4-7.7 137.8-32.9 107.4-62 150.9-192 107.4-303.9zM133.7 303.6L40.4 120.1C14.9 159.1 0 205.9 0 256c0 124 90.8 226.7 209.5 244.9l63.7-124.8c-57.6 10.8-113.2-20.8-139.5-72.5z"],cloudscale:[448,512,[],"f383","M318.1 154l-9.4 7.6c-22.5-19.3-51.5-33.6-83.3-33.6C153.8 128 96 188.8 96 260.3c0 6.6.4 13.1 1.4 19.4-2-56 41.8-97.4 92.6-97.4 24.2 0 46.2 9.4 62.6 24.7l-25.2 20.4c-8.3-.9-16.8 1.8-23.1 8.1-11.1 11-11.1 28.9 0 40 11.1 11 28.9 11 40 0 6.3-6.3 9-14.9 8.1-23.1l75.2-88.8c6.3-6.5-3.3-15.9-9.5-9.6zm-83.8 111.5c-5.6 5.5-14.6 5.5-20.2 0-5.6-5.6-5.6-14.6 0-20.2s14.6-5.6 20.2 0 5.6 14.7 0 20.2zM224 32C100.5 32 0 132.5 0 256s100.5 224 224 224 224-100.5 224-224S347.5 32 224 32zm0 384c-88.2 0-160-71.8-160-160S135.8 96 224 96s160 71.8 160 160-71.8 160-160 160z"],cloudsmith:[332,512,[],"f384","M332.5 419.9c0 46.4-37.6 84.1-84 84.1s-84-37.7-84-84.1 37.6-84 84-84 84 37.6 84 84zm-84-243.9c46.4 0 80-37.6 80-84s-33.6-84-80-84-88 37.6-88 84-29.6 76-76 76-84 41.6-84 88 37.6 80 84 80 84-33.6 84-80 33.6-80 80-80z"],cloudversify:[616,512,[],"f385","M148.6 304c8.2 68.5 67.4 115.5 146 111.3 51.2 43.3 136.8 45.8 186.4-5.6 69.2 1.1 118.5-44.6 131.5-99.5 14.8-62.5-18.2-132.5-92.1-155.1-33-88.1-131.4-101.5-186.5-85-57.3 17.3-84.3 53.2-99.3 109.7-7.8 2.7-26.5 8.9-45 24.1 11.7 0 15.2 8.9 15.2 19.5v20.4c0 10.7-8.7 19.5-19.5 19.5h-20.2c-10.7 0-19.5-6-19.5-16.7V240H98.8C95 240 88 244.3 88 251.9v40.4c0 6.4 5.3 11.8 11.7 11.8h48.9zm227.4 8c-10.7 46.3 21.7 72.4 55.3 86.8C324.1 432.6 259.7 348 296 288c-33.2 21.6-33.7 71.2-29.2 92.9-17.9-12.4-53.8-32.4-57.4-79.8-3-39.9 21.5-75.7 57-93.9C297 191.4 369.9 198.7 400 248c-14.1-48-53.8-70.1-101.8-74.8 30.9-30.7 64.4-50.3 114.2-43.7 69.8 9.3 133.2 82.8 67.7 150.5 35-16.3 48.7-54.4 47.5-76.9l10.5 19.6c11.8 22 15.2 47.6 9.4 72-9.2 39-40.6 68.8-79.7 76.5-32.1 6.3-83.1-5.1-91.8-59.2zM128 208H88.2c-8.9 0-16.2-7.3-16.2-16.2v-39.6c0-8.9 7.3-16.2 16.2-16.2H128c8.9 0 16.2 7.3 16.2 16.2v39.6c0 8.9-7.3 16.2-16.2 16.2zM10.1 168C4.5 168 0 163.5 0 157.9v-27.8c0-5.6 4.5-10.1 10.1-10.1h27.7c5.5 0 10.1 4.5 10.1 10.1v27.8c0 5.6-4.5 10.1-10.1 10.1H10.1zM168 142.7v-21.4c0-5.1 4.2-9.3 9.3-9.3h21.4c5.1 0 9.3 4.2 9.3 9.3v21.4c0 5.1-4.2 9.3-9.3 9.3h-21.4c-5.1 0-9.3-4.2-9.3-9.3zM56 235.5v25c0 6.3-5.1 11.5-11.4 11.5H19.4C13.1 272 8 266.8 8 260.5v-25c0-6.3 5.1-11.5 11.4-11.5h25.1c6.4 0 11.5 5.2 11.5 11.5z"],codepen:[512,512,[],"f1cb","M502.285 159.704l-234-156c-7.987-4.915-16.511-4.96-24.571 0l-234 156C3.714 163.703 0 170.847 0 177.989v155.999c0 7.143 3.714 14.286 9.715 18.286l234 156.022c7.987 4.915 16.511 4.96 24.571 0l234-156.022c6-3.999 9.715-11.143 9.715-18.286V177.989c-.001-7.142-3.715-14.286-9.716-18.285zM278 63.131l172.286 114.858-76.857 51.429L278 165.703V63.131zm-44 0v102.572l-95.429 63.715-76.857-51.429L234 63.131zM44 219.132l55.143 36.857L44 292.846v-73.714zm190 229.715L61.714 333.989l76.857-51.429L234 346.275v102.572zm22-140.858l-77.715-52 77.715-52 77.715 52-77.715 52zm22 140.858V346.275l95.429-63.715 76.857 51.429L278 448.847zm190-156.001l-55.143-36.857L468 219.132v73.714z"],codiepie:[472,512,[],"f284","M422.5 202.9c30.7 0 33.5 53.1-.3 53.1h-10.8v44.3h-26.6v-97.4h37.7zM472 352.6C429.9 444.5 350.4 504 248 504 111 504 0 393 0 256S111 8 248 8c97.4 0 172.8 53.7 218.2 138.4l-186 108.8L472 352.6zm-38.5 12.5l-60.3-30.7c-27.1 44.3-70.4 71.4-122.4 71.4-82.5 0-149.2-66.7-149.2-148.9 0-82.5 66.7-149.2 149.2-149.2 48.4 0 88.9 23.5 116.9 63.4l59.5-34.6c-40.7-62.6-104.7-100-179.2-100-121.2 0-219.5 98.3-219.5 219.5S126.8 475.5 248 475.5c78.6 0 146.5-42.1 185.5-110.4z"],connectdevelop:[576,512,[],"f20e","M550.5 241l-50.089-86.786c1.071-2.142 1.875-4.553 1.875-7.232 0-8.036-6.696-14.733-14.732-15.001l-55.447-95.893c.536-1.607 1.071-3.214 1.071-4.821 0-8.571-6.964-15.268-15.268-15.268-4.821 0-8.839 2.143-11.786 5.625H299.518C296.839 18.143 292.821 16 288 16s-8.839 2.143-11.518 5.625H170.411C167.464 18.143 163.447 16 158.625 16c-8.303 0-15.268 6.696-15.268 15.268 0 1.607.536 3.482 1.072 4.821l-55.983 97.233c-5.356 2.41-9.107 7.5-9.107 13.661 0 .535.268 1.071.268 1.607l-53.304 92.143c-7.232 1.339-12.59 7.5-12.59 15 0 7.232 5.089 13.393 12.054 15l55.179 95.358c-.536 1.607-.804 2.946-.804 4.821 0 7.232 5.089 13.393 12.054 14.732l51.697 89.732c-.536 1.607-1.071 3.482-1.071 5.357 0 8.571 6.964 15.268 15.268 15.268 4.821 0 8.839-2.143 11.518-5.357h106.875C279.161 493.857 283.447 496 288 496s8.839-2.143 11.518-5.357h107.143c2.678 2.946 6.696 4.821 10.982 4.821 8.571 0 15.268-6.964 15.268-15.268 0-1.607-.267-2.946-.803-4.285l51.697-90.268c6.964-1.339 12.054-7.5 12.054-14.732 0-1.607-.268-3.214-.804-4.821l54.911-95.358c6.964-1.339 12.322-7.5 12.322-15-.002-7.232-5.092-13.393-11.788-14.732zM153.535 450.732l-43.66-75.803h43.66v75.803zm0-83.839h-43.66c-.268-1.071-.804-2.142-1.339-3.214l44.999-47.41v50.624zm0-62.411l-50.357 53.304c-1.339-.536-2.679-1.34-4.018-1.607L43.447 259.75c.535-1.339.535-2.679.535-4.018s0-2.41-.268-3.482l51.965-90c2.679-.268 5.357-1.072 7.768-2.679l50.089 51.965v92.946zm0-102.322l-45.803-47.41c1.339-2.143 2.143-4.821 2.143-7.767 0-.268-.268-.804-.268-1.072l43.928-15.804v72.053zm0-80.625l-43.66 15.804 43.66-75.536v59.732zm326.519 39.108l.804 1.339L445.5 329.125l-63.75-67.232 98.036-101.518.268.268zM291.75 355.107l11.518 11.786H280.5l11.25-11.786zm-.268-11.25l-83.303-85.446 79.553-84.375 83.036 87.589-79.286 82.232zm5.357 5.893l79.286-82.232 67.5 71.25-5.892 28.125H313.714l-16.875-17.143zM410.411 44.393c1.071.536 2.142 1.072 3.482 1.34l57.857 100.714v.536c0 2.946.803 5.624 2.143 7.767L376.393 256l-83.035-87.589L410.411 44.393zm-9.107-2.143L287.732 162.518l-57.054-60.268 166.339-60h4.287zm-123.483 0c2.678 2.678 6.16 4.285 10.179 4.285s7.5-1.607 10.179-4.285h75L224.786 95.821 173.893 42.25h103.928zm-116.249 5.625l1.071-2.142a33.834 33.834 0 0 0 2.679-.804l51.161 53.84-54.911 19.821V47.875zm0 79.286l60.803-21.964 59.732 63.214-79.553 84.107-40.982-42.053v-83.304zm0 92.678L198 257.607l-36.428 38.304v-76.072zm0 87.858l42.053-44.464 82.768 85.982-17.143 17.678H161.572v-59.196zm6.964 162.053c-1.607-1.607-3.482-2.678-5.893-3.482l-1.071-1.607v-89.732h99.91l-91.607 94.821h-1.339zm129.911 0c-2.679-2.41-6.428-4.285-10.447-4.285s-7.767 1.875-10.447 4.285h-96.429l91.607-94.821h38.304l91.607 94.821H298.447zm120-11.786l-4.286 7.5c-1.339.268-2.41.803-3.482 1.339l-89.196-91.875h114.376l-17.412 83.036zm12.856-22.232l12.858-60.803h21.964l-34.822 60.803zm34.822-68.839h-20.357l4.553-21.16 17.143 18.214c-.535.803-1.071 1.874-1.339 2.946zm66.161-107.411l-55.447 96.697c-1.339.535-2.679 1.071-4.018 1.874l-20.625-21.964 34.554-163.928 45.803 79.286c-.267 1.339-.803 2.678-.803 4.285 0 1.339.268 2.411.536 3.75z"],contao:[512,512,[],"f26d","M45.4 305c14.4 67.1 26.4 129 68.2 175H34c-18.7 0-34-15.2-34-34V66c0-18.7 15.2-34 34-34h57.7C77.9 44.6 65.6 59.2 54.8 75.6c-45.4 70-27 146.8-9.4 229.4zM478 32h-90.2c21.4 21.4 39.2 49.5 52.7 84.1l-137.1 29.3c-14.9-29-37.8-53.3-82.6-43.9-24.6 5.3-41 19.3-48.3 34.6-8.8 18.7-13.2 39.8 8.2 140.3 21.1 100.2 33.7 117.7 49.5 131.2 12.9 11.1 33.4 17 58.3 11.7 44.5-9.4 55.7-40.7 57.4-73.2l137.4-29.6c3.2 71.5-18.7 125.2-57.4 163.6H478c18.7 0 34-15.2 34-34V66c0-18.8-15.2-34-34-34z"],cpanel:[640,512,[],"f388","M52.9 213.7h40l-6.2 23.6c-1.9 6.5-7.4 10.9-14.3 10.9H53.8c-24.9 0-24.7 37.4 0 37.4h11.3c4.2 0 7.6 3.9 6.4 8.3L64.4 320H52c-33.5 0-59-31.4-50.3-65.2 7.3-27 28.3-41.1 51.2-41.1M73.1 320L108 189.9c1.8-6.4 7.2-10.9 14.3-10.9h37c24.1 0 45.4 16.4 51 41.2 6.6 29.1-14.5 65.3-51.7 65.3h-32l6.4-23.8c1.8-6.2 7.3-10.8 14.3-10.8h10.3c12.4 0 20.8-11.7 18.3-22.6-2.1-9.2-9.9-14.8-18.3-14.8h-19.8L112 309.2c-1.9 6.2-7.4 10.7-14.2 10.7l-24.7.1m220.6-69.4c.3-1 1.9-5.3-2.1-5.3h-57.5c-9.7 0-16.6-8.9-14.2-18.5l3.5-13.4h77.9c18.8 0 33.3 17.6 28.5 36.8l-14 51.8c-2.8 10.6-12.2 17.8-23.4 17.8l-57.5-.2c-42.9 0-38.5-63.8.7-63.8H284l-3.5 13.2c-1.9 6.2-7.4 10.8-14.2 10.8h-21.6c-5.3 0-5.3 7.9 0 7.9h34.9c4.6 0 5.1-3.9 5.5-5.3l8.6-31.8m103.1-36.9c34.4 0 59.3 32.3 50.3 65.4l-8.8 33.1c-1.2 4.9-5.7 7.8-10.3 7.8h-19.1c-4.5 0-7.6-4-6.4-8.3l10.6-40c3.3-11.6-5.6-23.4-18.1-23.4h-19.8l-17.2 64c-1.2 4.8-5.6 7.8-10.4 7.8h-18.9c-4.2 0-7.6-3.9-6.4-8.3l26.2-98h48.3M498 251.6l-8 30c-.9 3.3 1.5 6.7 5.1 6.7h73.3l-5.7 21c-1.9 6.2-7.4 10.7-14.2 10.7h-66.7c-20 0-33.3-19-28.3-36.7l10.8-40c4.8-17.6 20.7-29.6 38.6-29.6h47.3c19 0 33.2 17.7 28.3 36.8l-3.2 12c-2.9 11-12.7 17.6-23.2 17.6h-53.4l3.5-13c1.6-6.2 7.2-10.8 14.2-10.8H538c2 0 3.3-1 3.9-3l.7-2.6c.7-2.7-1.3-5.1-3.9-5.1h-32.9c-4.1 0-6.9 2.1-7.8 6zm70.2 68.4l35.6-133.1c1.2-4.7 5.5-7.9 10.4-7.9h18.9c4.5 0 7.7 4 6.5 8.3l-26.5 98.2c-5.1 20.7-24.2 34.5-44.9 34.5"],"creative-commons":[512,512,[],"f25e","M255.547 8C392.884 8 504 114.439 504 256.004 504 405.979 381.106 504 255.562 504 122.319 504 8 394.557 8 256.004 8 124.825 113.486 8 255.547 8zm.899 44.734c-120.341 0-203.727 100.568-203.727 203.278 0 106.515 88.984 202.394 203.727 202.394 101.528 0 202.821-79.442 202.821-202.387-.001-114.773-91.773-203.285-202.821-203.285zm-3.108 162.093l-33.225 17.275c-5.395-11.203-15.25-19.926-27.459-19.926-22.134 0-33.217 14.609-33.217 43.842 0 23.842 9.446 43.842 33.217 43.842 14.469 0 24.653-7.091 30.566-21.259l30.551 15.5c-12.813 23.899-36.887 38.975-65.101 38.975-43.162 0-73.959-27.272-73.959-77.052 0-49.541 32.706-77.059 72.634-77.059 30.714-.013 52.701 11.946 65.993 35.862zm143.044 0l-32.775 17.275c-5.517-11.482-15.324-19.926-27.9-19.926-22.142 0-33.225 14.609-33.225 43.842 0 23.906 9.502 43.842 33.225 43.842 14.454 0 24.645-7.091 30.543-21.259l31 15.5c-13.363 23.869-37.451 38.975-65.086 38.975-43.439 0-73.959-26.988-73.959-77.052 0-49.523 32.698-77.059 72.626-77.059 30.706-.013 52.569 11.946 65.551 35.862z"],css3:[512,512,[],"f13c","M480 32l-64 368-223.3 80L0 400l19.6-94.8h82l-8 40.6L210 390.2l134.1-44.4 18.8-97.1H29.5l16-82h333.7l10.5-52.7H56.3l16.3-82H480z"],"css3-alt":[384,512,[],"f38b","M0 32l34.9 395.8L192 480l157.1-52.2L384 32H0zm313.1 80l-4.8 47.3L193 208.6l-.3.1h111.5l-12.8 146.6-98.2 28.7-98.8-29.2-6.4-73.9h48.9l3.2 38.3 52.6 13.3 54.7-15.4 3.7-61.6-166.3-.5v-.1l-.2.1-3.6-46.3L193.1 162l6.5-2.7H76.7L70.9 112h242.2z"],cuttlefish:[440,512,[],"f38c","M344 305.5c-17.5 31.6-57.4 54.5-96 54.5-56.6 0-104-47.4-104-104s47.4-104 104-104c38.6 0 78.5 22.9 96 54.5 13.7-50.9 41.7-93.3 87-117.8C385.7 39.1 320.5 8 248 8 111 8 0 119 0 256s111 248 248 248c72.5 0 137.7-31.1 183-80.7-45.3-24.5-73.3-66.9-87-117.8z"],"d-and-d":[576,512,[],"f38d","M82.5 98.9c-.6-17.2 2-33.8 12.7-48.2.3 7.4 1.2 14.5 4.2 21.6 5.9-27.5 19.7-49.3 42.3-65.5-1.9 5.9-3.5 11.8-3 17.7 8.7-7.4 18.8-17.8 44.4-22.7 14.7-2.8 29.7-2 42.1 1 38.5 9.3 61 34.3 69.7 72.3 5.3 23.1.7 45-8.3 66.4-5.2 12.4-12 24.4-20.7 35.1-2-1.9-3.9-3.8-5.8-5.6-42.8-40.8-26.8-25.2-37.4-37.4-1.1-1.2-1-2.2-.1-3.6 8.3-13.5 11.8-28.2 10-44-1.1-9.8-4.3-18.9-11.3-26.2-14.5-15.3-39.2-15-53.5.6-11.4 12.5-14.1 27.4-10.9 43.6.2 1.3.4 2.7 0 3.9-3.4 13.7-4.6 27.6-2.5 41.6.1.5.1 1.1.1 1.6 0 .3-.1.5-.2 1.1-21.8-11-36-28.3-43.2-52.2-8.3 17.8-11.1 35.5-6.6 54.1-15.6-15.2-21.3-34.3-22-55.2zm469.6 123.2c-11.6-11.6-25-20.4-40.1-26.6-12.8-5.2-26-7.9-39.9-7.1-10 .6-19.6 3.1-29 6.4-2.5.9-5.1 1.6-7.7 2.2-4.9 1.2-7.3-3.1-4.7-6.8 3.2-4.6 3.4-4.2 15-12 .6-.4 1.2-.8 2.2-1.5h-2.5c-.6 0-1.2.2-1.9.3-19.3 3.3-30.7 15.5-48.9 29.6-10.4 8.1-13.8 3.8-12-.5 1.4-3.5 3.3-6.7 5.1-10 1-1.8 2.3-3.4 3.5-5.1-.2-.2-.5-.3-.7-.5-27 18.3-46.7 42.4-57.7 73.3.3.3.7.6 1 .9.3-.6.5-1.2.9-1.7 10.4-12.1 22.8-21.8 36.6-29.8 18.2-10.6 37.5-18.3 58.7-20.2 4.3-.4 8.7-.1 13.1-.1-1.8.7-3.5.9-5.3 1.1-18.5 2.4-35.5 9-51.5 18.5-30.2 17.9-54.5 42.2-75.1 70.4-.3.4-.4.9-.7 1.3 14.5 5.3 24 17.3 36.1 25.6.2-.1.3-.2.4-.4l1.2-2.7c12.2-26.9 27-52.3 46.7-74.5 16.7-18.8 38-25.3 62.5-20 5.9 1.3 11.4 4.4 17.2 6.8 2.3-1.4 5.1-3.2 8-4.7 8.4-4.3 17.4-7 26.7-9 14.7-3.1 29.5-4.9 44.5-1.3v-.5c-.5-.4-1.2-.8-1.7-1.4zM316.7 397.6c-39.4-33-22.8-19.5-42.7-35.6-.8.9 0-.2-1.9 3-11.2 19.1-25.5 35.3-44 47.6-10.3 6.8-21.5 11.8-34.1 11.8-21.6 0-38.2-9.5-49.4-27.8-12-19.5-13.3-40.7-8.2-62.6 7.8-33.8 30.1-55.2 38.6-64.3-18.7-6.2-33 1.7-46.4 13.9.8-13.9 4.3-26.2 11.8-37.3-24.3 10.6-45.9 25-64.8 43.9-.3-5.8 5.4-43.7 5.6-44.7.3-2.7-.6-5.3-3-7.4-24.2 24.7-44.5 51.8-56.1 84.6 7.4-5.9 14.9-11.4 23.6-16.2-8.3 22.3-19.6 52.8-7.8 101.1 4.6 19 11.9 36.8 24.1 52.3 2.9 3.7 6.3 6.9 9.5 10.3.2-.2.4-.3.6-.5-1.4-7-2.2-14.1-1.5-21.9 2.2 3.2 3.9 6 5.9 8.6 12.6 16 28.7 27.4 47.2 35.6 25 11.3 51.1 13.3 77.9 8.6 54.9-9.7 90.7-48.6 116-98.8 1-1.8.6-2.9-.9-4.2zm172-46.4c-9.5-3.1-22.2-4.2-28.7-2.9 9.9 4 14.1 6.6 18.8 12 12.6 14.4 10.4 34.7-5.4 45.6-11.7 8.1-24.9 10.5-38.9 9.1-1.2-.1-2.3-.4-3-.6 2.8-3.7 6-7 8.1-10.8 9.4-16.8 5.4-42.1-8.7-56.1-2.1-2.1-4.6-3.9-7-5.9-.3 1.3-.1 2.1.1 2.8 4.2 16.6-8.1 32.4-24.8 31.8-7.6-.3-13.9-3.8-19.6-8.5-19.5-16.1-39.1-32.1-58.5-48.3-5.9-4.9-12.5-8.1-20.1-8.7-4.6-.4-9.3-.6-13.9-.9-5.9-.4-8.8-2.8-10.4-8.4-.9-3.4-1.5-6.8-2.2-10.2-1.5-8.1-6.2-13-14.3-14.2-4.4-.7-8.9-1-13.3-1.5-13-1.4-19.8-7.4-22.6-20.3-5 11-1.6 22.4 7.3 29.9 4.5 3.8 9.3 7.3 13.8 11.2 4.6 3.8 7.4 8.7 7.9 14.8.4 4.7.8 9.5 1.8 14.1 2.2 10.6 8.9 18.4 17 25.1 16.5 13.7 33 27.3 49.5 41.1 17.9 15 13.9 32.8 13 56-.9 22.9 12.2 42.9 33.5 51.2 1 .4 2 .6 3.6 1.1-15.7-18.2-10.1-44.1.7-52.3.3 2.2.4 4.3.9 6.4 9.4 44.1 45.4 64.2 85 56.9 16-2.9 30.6-8.9 42.9-19.8 2-1.8 3.7-4.1 5.9-6.5-19.3 4.6-35.8.1-50.9-10.6.7-.3 1.3-.3 1.9-.3 21.3 1.8 40.6-3.4 57-17.4 19.5-16.6 26.6-42.9 17.4-66-8.3-20.1-23.6-32.3-43.8-38.9zM99.4 179.3c-5.3-9.2-13.2-15.6-22.1-21.3 13.7-.5 26.6.2 39.6 3.7-7-12.2-8.5-24.7-5-38.7 5.3 11.9 13.7 20.1 23.6 26.8 19.7 13.2 35.7 19.6 46.7 30.2 3.4 3.3 6.3 7.1 9.6 10.9-.8-2.1-1.4-4.1-2.2-6-5-10.6-13-18.6-22.6-25-1.8-1.2-2.8-2.5-3.4-4.5-3.3-12.5-3-25.1-.7-37.6 1-5.5 2.8-10.9 4.5-16.3.8-2.4 2.3-4.6 4-6.6.6 6.9 0 25.5 19.6 46 10.8 11.3 22.4 21.9 33.9 32.7 9 8.5 18.3 16.7 25.5 26.8 1.1 1.6 2.2 3.3 3.8 4.7-5-13-14.2-24.1-24.2-33.8-9.6-9.3-19.4-18.4-29.2-27.4-3.3-3-4.6-6.7-5.1-10.9-1.2-10.4 0-20.6 4.3-30.2.5-1 1.1-2 1.9-3.3.5 4.2.6 7.9 1.4 11.6 4.8 23.1 20.4 36.3 49.3 63.5 10 9.4 19.3 19.2 25.6 31.6 4.8 9.3 7.3 19 5.7 29.6-.1.6.5 1.7 1.1 2 6.2 2.6 10 6.9 9.7 14.3 7.7-2.6 12.5-8 16.4-14.5 4.2 20.2-9.1 50.3-27.2 58.7.4-4.5 5-23.4-16.5-27.7-6.8-1.3-12.8-1.3-22.9-2.1 4.7-9 10.4-20.6.5-22.4-24.9-4.6-52.8 1.9-57.8 4.6 8.2.4 16.3 1 23.5 3.3-2 6.5-4 12.7-5.8 18.9-1.9 6.5 2.1 14.6 9.3 9.6 1.2-.9 2.3-1.9 3.3-2.7-3.1 17.9-2.9 15.9-2.8 18.3.3 10.2 9.5 7.8 15.7 7.3-2.5 11.8-29.5 27.3-45.4 25.8 7-4.7 12.7-10.3 15.9-17.9-6.5.8-12.9 1.6-19.2 2.4l-.3-.9c4.7-3.4 8-7.8 10.2-13.1 8.7-21.1-3.6-38-25-39.9-9.1-.8-17.8.8-25.9 5.5 6.2-15.6 17.2-26.6 32.6-34.5-15.2-4.3-8.9-2.7-24.6-6.3 14.6-9.3 30.2-13.2 46.5-14.6-5.2-3.2-48.1-3.6-70.2 20.9 7.9 1.4 15.5 2.8 23.2 4.2-23.8 7-44 19.7-62.4 35.6 1.1-4.8 2.7-9.5 3.3-14.3.6-4.5.8-9.2.1-13.6-1.5-9.4-8.9-15.1-19.7-16.3-7.9-.9-15.6.1-23.3 1.3-.9.1-1.7.3-2.9 0 15.8-14.8 36-21.7 53.1-33.5 6-4.5 6.8-8.2 3-14.9zm128.4 26.8c3.3 16 12.6 25.5 23.8 24.3-4.6-11.3-12.1-19.5-23.8-24.3z"],dashcube:[384,512,[],"f210","M288.1 97.5H85.5C37.6 97.5 0 138.1 0 185.2v215.1C0 447.7 37.6 480 85.5 480h213c47.9 0 85.5-32.3 85.5-79.7V0l-95.9 97.5zm-161.9 293c-16.6 0-30.4-14.2-30.4-30.8v-134c0-16.6 13.8-30.5 30.4-30.5h131.9c16.6 0 30 13.9 30 30.5v115.7l47.9 49H126.2z"],delicious:[448,512,[],"f1a5","M446.5 68c-.4-1.5-.9-3-1.4-4.5-.9-2.5-2-4.8-3.3-7.1-1.4-2.4-3-4.8-4.7-6.9-2.1-2.5-4.4-4.8-6.9-6.8-1.1-.9-2.2-1.7-3.3-2.5-1.3-.9-2.6-1.7-4-2.4-1.8-1-3.6-1.8-5.5-2.5-1.7-.7-3.5-1.3-5.4-1.7-3.8-1-7.9-1.5-12-1.5H48C21.5 32 0 53.5 0 80v352c0 4.1.5 8.2 1.5 12 2 7.7 5.8 14.6 11 20.3 1 1.1 2.1 2.2 3.3 3.3 5.7 5.2 12.6 9 20.3 11 3.8 1 7.9 1.5 12 1.5h352c26.5 0 48-21.5 48-48V80c-.1-4.1-.6-8.2-1.6-12zM416 432c0 8.8-7.2 16-16 16H224V256H32V80c0-8.8 7.2-16 16-16h176v192h192v176z"],deploydog:[512,512,[],"f38e","M382.2 136h51.7v239.6h-51.7v-20.7c-19.8 24.8-52.8 24.1-73.8 14.7-26.2-11.7-44.3-38.1-44.3-71.8 0-29.8 14.8-57.9 43.3-70.8 20.2-9.1 52.7-10.6 74.8 12.9V136zm-64.7 161.8c0 18.2 13.6 33.5 33.2 33.5 19.8 0 33.2-16.4 33.2-32.9 0-17.1-13.7-33.2-33.2-33.2-19.6 0-33.2 16.4-33.2 32.6zM188.5 136h51.7v239.6h-51.7v-20.7c-19.8 24.8-52.8 24.1-73.8 14.7-26.2-11.7-44.3-38.1-44.3-71.8 0-29.8 14.8-57.9 43.3-70.8 20.2-9.1 52.7-10.6 74.8 12.9V136zm-64.7 161.8c0 18.2 13.6 33.5 33.2 33.5 19.8 0 33.2-16.4 33.2-32.9 0-17.1-13.7-33.2-33.2-33.2-19.7 0-33.2 16.4-33.2 32.6zM448 96c17.5 0 32 14.4 32 32v256c0 17.5-14.4 32-32 32H64c-17.5 0-32-14.4-32-32V128c0-17.5 14.4-32 32-32h384m0-32H64C28.8 64 0 92.8 0 128v256c0 35.2 28.8 64 64 64h384c35.2 0 64-28.8 64-64V128c0-35.2-28.8-64-64-64z"],deskpro:[480,512,[],"f38f","M205.9 512l31.1-38.4c12.3-.2 25.6-1.4 36.5-6.6 38.9-18.6 38.4-61.9 38.3-63.8-.1-5-.8-4.4-28.9-37.4H362c-.2 50.1-7.3 68.5-10.2 75.7-9.4 23.7-43.9 62.8-95.2 69.4-8.7 1.1-32.8 1.2-50.7 1.1zm200.4-167.7c38.6 0 58.5-13.6 73.7-30.9l-175.5-.3-17.4 31.3 119.2-.1zm-43.6-223.9v168.3h-73.5l-32.7 55.5H250c-52.3 0-58.1-56.5-58.3-58.9-1.2-13.2-21.3-11.6-20.1 1.8 1.4 15.8 8.8 40 26.4 57.1h-91c-25.5 0-110.8-26.8-107-114V16.9C0 .9 9.7.3 15 .1h82c.2 0 .3.1.5.1 4.3-.4 50.1-2.1 50.1 43.7 0 13.3 20.2 13.4 20.2 0 0-18.2-5.5-32.8-15.8-43.7h84.2c108.7-.4 126.5 79.4 126.5 120.2zm-132.5 56l64 29.3c13.3-45.5-42.2-71.7-64-29.3z"],deviantart:[320,512,[],"f1bd","M320 93.2l-98.2 179.1 7.4 9.5H320v127.7H159.1l-13.5 9.2-43.7 84c-.3 0-8.6 8.6-9.2 9.2H0v-93.2l93.2-179.4-7.4-9.2H0V102.5h156l13.5-9.2 43.7-84c.3 0 8.6-8.6 9.2-9.2H320v93.1z"],digg:[512,512,[],"f1a6","M81.7 172.3H0v174.4h132.7V96h-51v76.3zm0 133.4H50.9v-92.3h30.8v92.3zm297.2-133.4v174.4h81.8v28.5h-81.8V416H512V172.3H378.9zm81.8 133.4h-30.8v-92.3h30.8v92.3zm-235.6 41h82.1v28.5h-82.1V416h133.3V172.3H225.1v174.4zm51.2-133.3h30.8v92.3h-30.8v-92.3zM153.3 96h51.3v51h-51.3V96zm0 76.3h51.3v174.4h-51.3V172.3z"],"digital-ocean":[512,512,[],"f391","M256 504v-96.1c101.8 0 180.8-100.9 141.7-208-14.3-39.6-46.1-71.4-85.8-85.7-107.1-38.8-208.1 39.9-208.1 141.7H8C8 93.7 164.9-32.8 335 20.3c74.2 23.3 133.6 82.4 156.6 156.6C544.8 347.2 418.6 504 256 504zm.3-191.4h-95.6v95.6h95.6v-95.6zm-95.6 95.6H87v73.6h73.7v-73.6zM87 346.6H25.4v61.6H87v-61.6z"],discord:[448,512,[],"f392","M297.216 243.2c0 15.616-11.52 28.416-26.112 28.416-14.336 0-26.112-12.8-26.112-28.416s11.52-28.416 26.112-28.416c14.592 0 26.112 12.8 26.112 28.416zm-119.552-28.416c-14.592 0-26.112 12.8-26.112 28.416s11.776 28.416 26.112 28.416c14.592 0 26.112-12.8 26.112-28.416.256-15.616-11.52-28.416-26.112-28.416zM448 52.736V512c-64.494-56.994-43.868-38.128-118.784-107.776l13.568 47.36H52.48C23.552 451.584 0 428.032 0 398.848V52.736C0 23.552 23.552 0 52.48 0h343.04C424.448 0 448 23.552 448 52.736zm-72.96 242.688c0-82.432-36.864-149.248-36.864-149.248-36.864-27.648-71.936-26.88-71.936-26.88l-3.584 4.096c43.52 13.312 63.744 32.512 63.744 32.512-60.811-33.329-132.244-33.335-191.232-7.424-9.472 4.352-15.104 7.424-15.104 7.424s21.248-20.224 67.328-33.536l-2.56-3.072s-35.072-.768-71.936 26.88c0 0-36.864 66.816-36.864 149.248 0 0 21.504 37.12 78.08 38.912 0 0 9.472-11.52 17.152-21.248-32.512-9.728-44.8-30.208-44.8-30.208 3.766 2.636 9.976 6.053 10.496 6.4 43.21 24.198 104.588 32.126 159.744 8.96 8.96-3.328 18.944-8.192 29.44-15.104 0 0-12.8 20.992-46.336 30.464 7.68 9.728 16.896 20.736 16.896 20.736 56.576-1.792 78.336-38.912 78.336-38.912z"],discourse:[448,512,[],"f393","M225.9 32C103.3 32 0 130.5 0 252.1 0 256 .1 480 .1 480l225.8-.2c122.7 0 222.1-102.3 222.1-223.9C448 134.3 348.6 32 225.9 32zM224 384c-19.4 0-37.9-4.3-54.4-12.1L88.5 392l22.9-75c-9.8-18.1-15.4-38.9-15.4-61 0-70.7 57.3-128 128-128s128 57.3 128 128-57.3 128-128 128z"],dochub:[416,512,[],"f394","M397.9 160H256V19.6L397.9 160zM304 192v130c0 66.8-36.5 100.1-113.3 100.1H96V84.8h94.7c12 0 23.1.8 33.1 2.5v-84C212.9 1.1 201.4 0 189.2 0H0v512h189.2C329.7 512 400 447.4 400 318.1V192h-96z"],docker:[640,512,[],"f395","M349.9 236.3h-66.1v-59.4h66.1v59.4zm0-204.3h-66.1v60.7h66.1V32zm78.2 144.8H362v59.4h66.1v-59.4zm-156.3-72.1h-66.1v60.1h66.1v-60.1zm78.1 0h-66.1v60.1h66.1v-60.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1l-13.3-8.9zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm-78.1-72.1h-66.1v60.1h66.1v-60.1z"],draft2digital:[480,512,[],"f396","M369.9 425.4V371l47.1 27.2-47.1 27.2zM82.4 380.6c25.5-27.3 97.7-104.7 150.9-170 35.1-43.1 40.3-82.4 28.4-112.7-7.4-18.8-17.5-30.2-24.3-35.7 45.3 2.1 68 23.4 82.2 38.3 0 0 42.4 48.2 5.8 113.3-37 65.9-110.9 147.5-128.5 166.7H82.4zm51.8-219.2c0 12.4-10 22.4-22.4 22.4-12.4 0-22.4-10-22.4-22.4 0-12.4 10-22.4 22.4-22.4 12.4 0 22.4 10.1 22.4 22.4M336 315.9v64.7h-91.3c30.8-35 81.8-95.9 111.8-149.3 35.2-62.6 16.1-123.4-12.8-153.3-4.4-4.6-62.2-62.9-166-41.2-59.1 12.4-89.4 43.4-104.3 67.3-13.1 20.9-17 39.8-18.2 47.7-5.5 33 19.4 67.1 56.7 67.1 31.7 0 57.3-25.7 57.3-57.4 0-27.1-19.7-52.1-48-56.8 1.8-7.3 17.7-21.1 26.3-24.7 41.1-17.3 78 5.2 83.3 33.5 8.3 44.3-37.1 90.4-69.7 127.6C84.5 328.1 18.3 396.8 0 415.9l336-.1V480l144-81.9-144-82.2z"],dribbble:[512,512,[],"f17d","M256 8C119.252 8 8 119.252 8 256s111.252 248 248 248 248-111.252 248-248S392.748 8 256 8zm163.97 114.366c29.503 36.046 47.369 81.957 47.835 131.955-6.984-1.477-77.018-15.682-147.502-6.818-5.752-14.041-11.181-26.393-18.617-41.614 78.321-31.977 113.818-77.482 118.284-83.523zM396.421 97.87c-3.81 5.427-35.697 48.286-111.021 76.519-34.712-63.776-73.185-116.168-79.04-124.008 67.176-16.193 137.966 1.27 190.061 47.489zm-230.48-33.25c5.585 7.659 43.438 60.116 78.537 122.509-99.087 26.313-186.36 25.934-195.834 25.809C62.38 147.205 106.678 92.573 165.941 64.62zM44.17 256.323c0-2.166.043-4.322.108-6.473 9.268.19 111.92 1.513 217.706-30.146 6.064 11.868 11.857 23.915 17.174 35.949-76.599 21.575-146.194 83.527-180.531 142.306C64.794 360.405 44.17 310.73 44.17 256.323zm81.807 167.113c22.127-45.233 82.178-103.622 167.579-132.756 29.74 77.283 42.039 142.053 45.189 160.638-68.112 29.013-150.015 21.053-212.768-27.882zm248.38 8.489c-2.171-12.886-13.446-74.897-41.152-151.033 66.38-10.626 124.7 6.768 131.947 9.055-9.442 58.941-43.273 109.844-90.795 141.978z"],"dribbble-square":[448,512,[],"f397","M90.2 228.2c8.9-42.4 37.4-77.7 75.7-95.7 3.6 4.9 28 38.8 50.7 79-64 17-120.3 16.8-126.4 16.7zM314.6 154c-33.6-29.8-79.3-41.1-122.6-30.6 3.8 5.1 28.6 38.9 51 80 48.6-18.3 69.1-45.9 71.6-49.4zM140.1 364c40.5 31.6 93.3 36.7 137.3 18-2-12-10-53.8-29.2-103.6-55.1 18.8-93.8 56.4-108.1 85.6zm98.8-108.2c-3.4-7.8-7.2-15.5-11.1-23.2C159.6 253 93.4 252.2 87.4 252c0 1.4-.1 2.8-.1 4.2 0 35.1 13.3 67.1 35.1 91.4 22.2-37.9 67.1-77.9 116.5-91.8zm34.9 16.3c17.9 49.1 25.1 89.1 26.5 97.4 30.7-20.7 52.5-53.6 58.6-91.6-4.6-1.5-42.3-12.7-85.1-5.8zm-20.3-48.4c4.8 9.8 8.3 17.8 12 26.8 45.5-5.7 90.7 3.4 95.2 4.4-.3-32.3-11.8-61.9-30.9-85.1-2.9 3.9-25.8 33.2-76.3 53.9zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-64 176c0-88.2-71.8-160-160-160S64 167.8 64 256s71.8 160 160 160 160-71.8 160-160z"],dropbox:[528,512,[],"f16b","M264.4 116.3l-132 84.3 132 84.3-132 84.3L0 284.1l132.3-84.3L0 116.3 132.3 32l132.1 84.3zM131.6 395.7l132-84.3 132 84.3-132 84.3-132-84.3zm132.8-111.6l132-84.3-132-83.6L395.7 32 528 116.3l-132.3 84.3L528 284.8l-132.3 84.3-131.3-85z"],drupal:[448,512,[],"f1a9","M319.5 114.7c-22.2-14-43.5-19.5-64.7-33.5-13-8.8-31.3-30-46.5-48.3-2.7 29.3-11.5 41.2-22 49.5-21.3 17-34.8 22.2-53.5 32.3C117 123 32 181.5 32 290.5 32 399.7 123.8 480 225.8 480 327.5 480 416 406 416 294c0-112.3-83-171-96.5-179.3zm2.5 325.6c-20.1 20.1-90.1 28.7-116.7 4.2-4.8-4.8.3-12 6.5-12 0 0 17 13.3 51.5 13.3 27 0 46-7.7 54.5-14 6.1-4.6 8.4 4.3 4.2 8.5zm-54.5-52.6c8.7-3.6 29-3.8 36.8 1.3 4.1 2.8 16.1 18.8 6.2 23.7-8.4 4.2-1.2-15.7-26.5-15.7-14.7 0-19.5 5.2-26.7 11-7 6-9.8 8-12.2 4.7-6-8.2 15.9-22.3 22.4-25zM360 405c-15.2-1-45.5-48.8-65-49.5-30.9-.9-104.1 80.7-161.3 42-38.8-26.6-14.6-104.8 51.8-105.2 49.5-.5 83.8 49 108.5 48.5 21.3-.3 61.8-41.8 81.8-41.8 48.7 0 23.3 109.3-15.8 106z"],dyalog:[416,512,[],"f399","M0 32v119.2h64V96h107.2C284.6 96 352 176.2 352 255.9 352 332 293.4 416 171.2 416H0v64h171.2C331.9 480 416 367.3 416 255.9c0-58.7-22.1-113.4-62.3-154.3C308.9 56 245.7 32 171.2 32H0z"],earlybirds:[480,512,[],"f39a","M313.2 47.5c1.2-13 21.3-14 36.6-8.7.9.3 26.2 9.7 19 15.2-27.9-7.4-56.4 18.2-55.6-6.5zm-201 6.9c30.7-8.1 62 20 61.1-7.1-1.3-14.2-23.4-15.3-40.2-9.6-1 .3-28.7 10.5-20.9 16.7zM319.4 160c-8.8 0-16 7.2-16 16s7.2 16 16 16 16-7.2 16-16-7.2-16-16-16zm-159.7 0c-8.8 0-16 7.2-16 16s7.2 16 16 16 16-7.2 16-16-7.2-16-16-16zm318.5 163.2c-9.9 24-40.7 11-63.9-1.2-13.5 69.1-58.1 111.4-126.3 124.2.3.9-2-.1 24 1 33.6 1.4 63.8-3.1 97.4-8-19.8-13.8-11.4-37.1-9.8-38.1 1.4-.9 14.7 1.7 21.6 11.5 8.6-12.5 28.4-14.8 30.2-13.6 1.6 1.1 6.6 20.9-6.9 34.6 4.7-.9 8.2-1.6 9.8-2.1 2.6-.8 17.7 11.3 3.1 13.3-14.3 2.3-22.6 5.1-47.1 10.8-45.9 10.7-85.9 11.8-117.7 12.8l1 11.6c3.8 18.1-23.4 24.3-27.6 6.2.8 17.9-27.1 21.8-28.4-1l-.5 5.3c-.7 18.4-28.4 17.9-28.3-.6-7.5 13.5-28.1 6.8-26.4-8.5l1.2-12.4c-36.7.9-59.7 3.1-61.8 3.1-20.9 0-20.9-31.6 0-31.6 2.4 0 27.7 1.3 63.2 2.8-61.1-15.5-103.7-55-114.9-118.2-25 12.8-57.5 26.8-68.2.8-10.5-25.4 21.5-42.6 66.8-73.4.7-6.6 1.6-13.3 2.7-19.8-14.4-19.6-11.6-36.3-16.1-60.4-16.8 2.4-23.2-9.1-23.6-23.1.3-7.3 2.1-14.9 2.4-15.4 1.1-1.8 10.1-2 12.7-2.6 6-31.7 50.6-33.2 90.9-34.5 19.7-21.8 45.2-41.5 80.9-48.3C203.3 29 215.2 8.5 216.2 8c1.7-.8 21.2 4.3 26.3 23.2 5.2-8.8 18.3-11.4 19.6-10.7 1.1.6 6.4 15-4.9 25.9 40.3 3.5 72.2 24.7 96 50.7 36.1 1.5 71.8 5.9 77.1 34 2.7.6 11.6.8 12.7 2.6.3.5 2.1 8.1 2.4 15.4-.5 13.9-6.8 25.4-23.6 23.1-3.2 17.3-2.7 32.9-8.7 47.7 2.4 11.7 4 23.8 4.8 36.4 37 25.4 70.3 42.5 60.3 66.9zM207.4 159.9c.9-44-37.9-42.2-78.6-40.3-21.7 1-38.9 1.9-45.5 13.9-11.4 20.9 5.9 92.9 23.2 101.2 9.8 4.7 73.4 7.9 86.3-7.1 8.2-9.4 15-49.4 14.6-67.7zm52 58.3c-4.3-12.4-6-30.1-15.3-32.7-2-.5-9-.5-11 0-10 2.8-10.8 22.1-17 37.2 15.4 0 19.3 9.7 23.7 9.7 4.3 0 6.3-11.3 19.6-14.2zm135.7-84.7c-6.6-12.1-24.8-12.9-46.5-13.9-40.2-1.9-78.2-3.8-77.3 40.3-.5 18.3 5 58.3 13.2 67.8 13 14.9 76.6 11.8 86.3 7.1 15.8-7.6 36.5-78.9 24.3-101.3z"],edge:[512,512,[],"f282","M25.714 228.163c.111-.162.23-.323.342-.485-.021.162-.045.323-.065.485h-.277zm460.572 15.508c0-44.032-7.754-84.465-28.801-122.405C416.498 47.879 343.912 8.001 258.893 8.001 118.962 7.724 40.617 113.214 26.056 227.679c42.429-61.312 117.073-121.376 220.375-124.966 0 0 109.666 0 99.419 104.957H169.997c6.369-37.386 18.554-58.986 34.339-78.926-75.048 34.893-121.85 96.096-120.742 188.315.83 71.448 50.124 144.836 120.743 171.976 83.357 31.847 192.776 7.2 240.132-21.324V363.307c-80.864 56.494-270.871 60.925-272.255-67.572h314.073v-52.064z"],ember:[640,512,[],"f423","M639.9 311.7c-1.1-10.7-10.7-6.8-10.7-6.8s-15.6 12.1-29.3 10.7c-13.7-1.3-9.4-32-9.4-32s3-28.1-5.1-30.4c-8.1-2.4-18 7.3-18 7.3s-12.4 13.7-18.3 31.2l-1.6.5s1.9-30.6-.3-37.6c-1.6-3.5-16.4-3.2-18.8 3-2.4 6.2-14.2 49.2-15 67.2 0 0-23.1 19.6-43.3 22.8-20.2 3.2-25-9.4-25-9.4s54.8-15.3 52.9-59.1c-1.9-43.8-44.2-27.6-49-24-4.6 3.5-29.4 18.4-36.6 59.7-.2 1.4-.7 7.5-.7 7.5s-21.2 14.2-33 18c0 0 33-55.6-7.3-80.9-18.3-11-32.8 12.1-32.8 12.1s54.5-60.7 42.5-112c-5.8-24.4-18-27.1-29.2-23.1-17 6.7-23.5 16.7-23.5 16.7s-22 32-27.1 79.5-12.6 105.1-12.6 105.1-10.5 10.2-20.2 10.7-5.4-28.7-5.4-28.7 7.5-44.6 7-52.1-1.1-11.6-9.9-14.2c-8.9-2.7-18.5 8.6-18.5 8.6s-25.5 38.7-27.7 44.6l-1.3 2.4-1.3-1.6s18-52.7.8-53.5-28.5 18.8-28.5 18.8-19.6 32.8-20.4 36.5l-1.3-1.6s8.1-38.2 6.4-47.6c-1.6-9.4-10.5-7.5-10.5-7.5s-11.3-1.3-14.2 5.9c-3 7.3-13.7 55.3-15 70.7 0 0-28.2 20.2-46.8 20.4s-16.7-11.8-16.7-11.8 68-23.3 49.4-69.2c-8.3-11.8-18-15.5-31.7-15.3-13.7.3-30.3 8.6-41.3 33.3-5.3 11.8-6.8 23-7.8 31.5 0 0-12.3 2.4-18.8-2.9-6.4-5.4-10 0-10 0s-11.2 13.9-.1 18.2c11 4.3 28.1 6.1 28.1 6.1 1.6 7.5 6.2 19.5 19.6 29.7 20.2 15.3 58.8-1.3 58.8-1.3l15.9-8.8s.5 14.6 12.1 16.7c11.6 2.1 16.4 1 36.5-47.9 11.8-25 12.6-23.6 12.6-23.6l1.3-.3s-9.1 46.8-5.6 59.7c3.5 12.9 18.8 11.6 18.8 11.6s8.3 2.4 15-21.2c6.7-23.6 19.6-49.9 19.6-49.9h1.6s-5.6 48.1 3 63.7c8.6 15.6 30.9 5.3 30.9 5.3s15.6-7.8 18-10.2c0 0 18.5 15.8 44.6 12.9 58.3-11.5 79.1-25.9 79.1-25.9s10 24.4 41.1 26.7c35.5 2.7 54.8-18.6 54.8-18.6s-.3 13.5 12.1 18.6c12.4 5.1 20.7-22.8 20.7-22.8l20.7-57.2h1.9s1.1 37.3 21.5 43.2c20.4 5.9 47-13.7 47-13.7s6.4-3.7 5.3-14.4zm-578 5.3c.8-32 21.8-45.9 29-39 7.3 7 4.6 22-9.1 31.4-13.7 9.5-19.9 7.6-19.9 7.6zm272.8-123.9s19.1-49.7 23.6-25.5-40 96.2-40 96.2c.5-16.1 16.4-70.7 16.4-70.7zm22.8 138.4c-12.6 33-43.3 19.6-43.3 19.6s-3.5-11.8 6.4-44.9 33.3-20.2 33.3-20.2 16.2 12.5 3.6 45.5zm84.6-14.5s-3-10.5 8.1-30.6c11-20.2 19.6-9.1 19.6-9.1s9.4 10.2-1.3 25.5c-10.8 15.3-26.4 14.2-26.4 14.2z"],empire:[496,512,[],"f1d1","M287.6 54.2c-10.8-2.2-22.1-3.3-33.5-3.6V32.4c78.1 2.2 146.1 44 184.6 106.6l-15.8 9.1c-6.1-9.7-12.7-18.8-20.2-27.1l-18 15.5c-26-29.6-61.4-50.7-101.9-58.4l4.8-23.9zM53.4 322.4l23-7.7c-6.4-18.3-10-38.2-10-58.7s3.3-40.4 9.7-58.7l-22.7-7.7c3.6-10.8 8.3-21.3 13.6-31l-15.8-9.1C34 181 24.1 217.5 24.1 256s10 75 27.1 106.6l15.8-9.1c-5.3-10-9.7-20.3-13.6-31.1zM213.1 434c-40.4-8-75.8-29.1-101.9-58.7l-18 15.8c-7.5-8.6-14.4-17.7-20.2-27.4l-16 9.4c38.5 62.3 106.8 104.3 184.9 106.6v-18.3c-11.3-.3-22.7-1.7-33.5-3.6l4.7-23.8zM93.3 120.9l18 15.5c26-29.6 61.4-50.7 101.9-58.4l-4.7-23.8c10.8-2.2 22.1-3.3 33.5-3.6V32.4C163.9 34.6 95.9 76.4 57.4 139l15.8 9.1c6-9.7 12.6-18.9 20.1-27.2zm309.4 270.2l-18-15.8c-26 29.6-61.4 50.7-101.9 58.7l4.7 23.8c-10.8 1.9-22.1 3.3-33.5 3.6v18.3c78.1-2.2 146.4-44.3 184.9-106.6l-16.1-9.4c-5.7 9.7-12.6 18.8-20.1 27.4zM496 256c0 137-111 248-248 248S0 393 0 256 111 8 248 8s248 111 248 248zm-12.2 0c0-130.1-105.7-235.8-235.8-235.8S12.2 125.9 12.2 256 117.9 491.8 248 491.8 483.8 386.1 483.8 256zm-39-106.6l-15.8 9.1c5.3 9.7 10 20.2 13.6 31l-22.7 7.7c6.4 18.3 9.7 38.2 9.7 58.7s-3.6 40.4-10 58.7l23 7.7c-3.9 10.8-8.3 21-13.6 31l15.8 9.1C462 331 471.9 294.5 471.9 256s-9.9-75-27.1-106.6zm-183 177.7c16.3-3.3 30.4-11.6 40.7-23.5l51.2 44.8c11.9-13.6 21.3-29.3 27.1-46.8l-64.2-22.1c2.5-7.5 3.9-15.2 3.9-23.5s-1.4-16.1-3.9-23.5l64.5-22.1c-6.1-17.4-15.5-33.2-27.4-46.8l-51.2 44.8c-10.2-11.9-24.4-20.5-40.7-23.8l13.3-66.4c-8.6-1.9-17.7-2.8-27.1-2.8-9.4 0-18.5.8-27.1 2.8l13.3 66.4c-16.3 3.3-30.4 11.9-40.7 23.8l-51.2-44.8c-11.9 13.6-21.3 29.3-27.4 46.8l64.5 22.1c-2.5 7.5-3.9 15.2-3.9 23.5s1.4 16.1 3.9 23.5l-64.2 22.1c5.8 17.4 15.2 33.2 27.1 46.8l51.2-44.8c10.2 11.9 24.4 20.2 40.7 23.5l-13.3 66.7c8.6 1.7 17.7 2.8 27.1 2.8 9.4 0 18.5-1.1 27.1-2.8l-13.3-66.7z"],envira:[448,512,[],"f299","M0 32c477.6 0 366.6 317.3 367.1 366.3L448 480h-26l-70.4-71.2c-39 4.2-124.4 34.5-214.4-37C47 300.3 52 214.7 0 32zm79.7 46c-49.7-23.5-5.2 9.2-5.2 9.2 45.2 31.2 66 73.7 90.2 119.9 31.5 60.2 79 139.7 144.2 167.7 65 28 34.2 12.5 6-8.5-28.2-21.2-68.2-87-91-130.2-31.7-60-61-118.6-144.2-158.1z"],erlang:[640,512,[],"f39d","M21.7 193c-.1 86.8 29 159.5 78.7 212.1H0V.1h87.2C45.7 50.3 21.6 116.2 21.7 193zM640 .1h-83.6c31.4 42.7 48.7 97.5 46.2 162.7.5 6 .5 11.7 0 24.1H230.2c-.2 109.7 38.9 194.9 138.6 195.3 68.5-.3 118-51 151.9-106.1l96.4 48.2c-17.4 30.9-36.5 57.8-57.9 80.8H640V.1zm-80.8 405h-.2.2zM556.1.1h.3l-.1-.1-.2.1zM325.4 9.8c-45.9.1-85.1 33.5-89.2 83.2h169.9C405 43.3 371.6 9.9 325.4 9.8z"],etsy:[384,512,[],"f2d7","M384 348c-1.75 10.75-13.75 110-15.5 132-117.879-4.299-219.895-4.743-368.5 0v-25.5c45.457-8.948 60.627-8.019 61-35.25 1.793-72.322 3.524-244.143 0-322-1.029-28.46-12.13-26.765-61-36v-25.5c73.886 2.358 255.933 8.551 362.999-3.75-3.5 38.25-7.75 126.5-7.75 126.5H332C320.947 115.665 313.241 68 277.25 68h-137c-10.25 0-10.75 3.5-10.75 9.75V241.5c58 .5 88.5-2.5 88.5-2.5 29.77-.951 27.56-8.502 40.75-65.251h25.75c-4.407 101.351-3.91 61.829-1.75 160.25H257c-9.155-40.086-9.065-61.045-39.501-61.5 0 0-21.5-2-88-2v139c0 26 14.25 38.25 44.25 38.25H263c63.636 0 66.564-24.996 98.751-99.75H384z"],expeditedssl:[496,512,[],"f23e","M248 43.4C130.6 43.4 35.4 138.6 35.4 256S130.6 468.6 248 468.6 460.6 373.4 460.6 256 365.4 43.4 248 43.4zm-97.4 132.9c0-53.7 43.7-97.4 97.4-97.4s97.4 43.7 97.4 97.4v26.6c0 5-3.9 8.9-8.9 8.9h-17.7c-5 0-8.9-3.9-8.9-8.9v-26.6c0-82.1-124-82.1-124 0v26.6c0 5-3.9 8.9-8.9 8.9h-17.7c-5 0-8.9-3.9-8.9-8.9v-26.6zM389.7 380c0 9.7-8 17.7-17.7 17.7H124c-9.7 0-17.7-8-17.7-17.7V238.3c0-9.7 8-17.7 17.7-17.7h248c9.7 0 17.7 8 17.7 17.7V380zm-248-137.3v132.9c0 2.5-1.9 4.4-4.4 4.4h-8.9c-2.5 0-4.4-1.9-4.4-4.4V242.7c0-2.5 1.9-4.4 4.4-4.4h8.9c2.5 0 4.4 1.9 4.4 4.4zm141.7 48.7c0 13-7.2 24.4-17.7 30.4v31.6c0 5-3.9 8.9-8.9 8.9h-17.7c-5 0-8.9-3.9-8.9-8.9v-31.6c-10.5-6.1-17.7-17.4-17.7-30.4 0-19.7 15.8-35.4 35.4-35.4s35.5 15.8 35.5 35.4zM248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 478.3C121 486.3 17.7 383 17.7 256S121 25.7 248 25.7 478.3 129 478.3 256 375 486.3 248 486.3z"],facebook:[448,512,[],"f09a","M448 56.7v398.5c0 13.7-11.1 24.7-24.7 24.7H309.1V306.5h58.2l8.7-67.6h-67v-43.2c0-19.6 5.4-32.9 33.5-32.9h35.8v-60.5c-6.2-.8-27.4-2.7-52.2-2.7-51.6 0-87 31.5-87 89.4v49.9h-58.4v67.6h58.4V480H24.7C11.1 480 0 468.9 0 455.3V56.7C0 43.1 11.1 32 24.7 32h398.5c13.7 0 24.8 11.1 24.8 24.7z"],"facebook-f":[264,512,[],"f39e","M76.7 512V283H0v-91h76.7v-71.7C76.7 42.4 124.3 0 193.8 0c33.3 0 61.9 2.5 70.2 3.6V85h-48.2c-37.8 0-45.1 18-45.1 44.3V192H256l-11.7 91h-73.6v229"],"facebook-messenger":[448,512,[],"f39f","M224 32C15.9 32-77.5 278 84.6 400.6V480l75.7-42c142.2 39.8 285.4-59.9 285.4-198.7C445.8 124.8 346.5 32 224 32zm23.4 278.1L190 250.5 79.6 311.6l121.1-128.5 57.4 59.6 110.4-61.1-121.1 128.5z"],"facebook-square":[448,512,[],"f082","M448 80v352c0 26.5-21.5 48-48 48h-85.3V302.8h60.6l8.7-67.6h-69.3V192c0-19.6 5.4-32.9 33.5-32.9H384V98.7c-6.2-.8-27.4-2.7-52.2-2.7-51.6 0-87 31.5-87 89.4v49.9H184v67.6h60.9V480H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48z"],firefox:[480,512,[],"f269","M478.1 235.3c-.7-4.5-1.4-7.1-1.4-7.1s-1.8 2-4.7 5.9c-.9-10.7-2.8-21.2-5.8-31.6-3.7-12.9-8.5-25.4-14.5-37.4-3.8-8-8.2-15.6-13.3-22.8-1.8-2.7-3.7-5.4-5.6-7.9-8.8-14.4-19-23.3-30.7-40-7.6-12.8-12.9-26.9-15.4-41.6-3.2 8.9-5.7 18-7.4 27.3-12.1-12.2-22.5-20.8-28.9-26.7C319.4 24.2 323 9.1 323 9.1S264.7 74.2 289.9 142c8.7 23 23.8 43.1 43.4 57.9 24.4 20.2 50.8 36 64.7 76.6-11.2-21.3-28.1-39.2-48.8-51.5 6.2 14.7 9.4 30.6 9.3 46.5 0 61-49.6 110.5-110.6 110.4-8.3 0-16.5-.9-24.5-2.8-9.5-1.8-18.7-4.9-27.4-9.3-12.9-7.8-24-18.1-32.8-30.3l-.2-.3 2 .7c4.6 1.6 9.2 2.8 14 3.7 18.7 4 38.3 1.7 55.6-6.6 17.5-9.7 28-16.9 36.6-14h.2c8.4 2.7 15-5.5 9-14-10.4-13.4-27.4-20-44.2-17-17.5 2.5-33.5 15-56.4 2.9-1.5-.8-2.9-1.6-4.3-2.5-1.6-.9 4.9 1.3 3.4.3-5-2.5-9.8-5.4-14.4-8.6-.3-.3 3.5 1.1 3.1.8-5.9-4-11-9.2-15-15.2-4.1-7.4-4.5-16.4-1-24.1 2.1-3.8 5.4-6.9 9.3-8.7 3 1.5 4.8 2.6 4.8 2.6s-1.3-2.5-2.1-3.8c.3-.1.5 0 .8-.2 2.6 1.1 8.3 4 11.4 5.8 2.1 1.1 3.8 2.7 5.2 4.7 0 0 1-.5.3-2.7-1.1-2.7-2.9-5-5.4-6.6h.2c2.3 1.2 4.5 2.6 6.6 4.1 1.9-4.4 2.8-9.2 2.6-14 .2-2.6-.2-5.3-1.1-7.8-.8-1.6.5-2.2 1.9-.5-.2-1.3-.7-2.5-1.2-3.7v-.1s.8-1.1 1.2-1.5c1-1 2.1-1.9 3.4-2.7 7.2-4.5 14.8-8.4 22.7-11.6 6.4-2.8 11.7-4.9 12.8-5.6 1.6-1 3.1-2.2 4.5-3.5 5.3-4.5 9-10.8 10.2-17.7.1-.9.2-1.8.3-2.8v-1.5c-.9-3.5-6.9-6.1-38.4-9.1-11.1-1.8-20-10.1-22.5-21.1v.1c-.4 1.1-.9 2.3-1.3 3.5.4-1.2.8-2.3 1.3-3.5v-.2c6-15.7 16.8-29.1 30.8-38.3.8-.7-3.2.2-2.4-.5 2.7-1.3 5.4-2.5 8.2-3.5 1.4-.6-6-3.4-12.6-2.7-4 .2-8 1.2-11.7 2.8 1.6-1.3 6.2-3.1 5.1-3.1-8.4 1.6-16.5 4.7-23.9 9 0-.8.1-1.5.5-2.2-5.9 2.5-11 6.5-15 11.5.1-.9.2-1.8.2-2.7-2.7 2-5.2 4.3-7.3 6.9l-.1.1c-17.4-6.7-36.3-8.3-54.6-4.7l-.2-.1h.2c-3.8-3.1-7.1-6.7-9.7-10.9l-.2.1-.4-.2c-1.2-1.8-2.4-3.8-3.7-6-.9-1.6-1.8-3.4-2.7-5.2 0-.1-.1-.2-.2-.2-.4 0-.6 1.7-.9 1.3v-.1c-3.2-8.3-4.7-17.2-4.4-26.2l-.2.1c-5.1 3.5-9 8.6-11.1 14.5-.9 2.1-1.6 3.3-2.2 4.5v-.5c.1-1.1.6-3.3.5-3.1-.1.2-.2.3-.3.4-1.5 1.7-2.9 3.7-3.9 5.8-.9 1.9-1.7 3.9-2.3 5.9-.1.3 0-.3 0-1s.1-2 0-1.7l-.3.7c-6.7 14.9-10.9 30.8-12.4 47.1-.4 2.8-.6 5.6-.5 8.3v.2c-4.8 5.2-9 11-12.7 17.1-12.1 20.4-21.1 42.5-26.8 65.6 4-8.8 8.8-17.2 14.3-25.1C5.5 228.5 0 257.4 0 286.6c1.8-8.6 4.2-17 7-25.3-1.7 34.5 4.9 68.9 19.4 100.3 19.4 43.5 51.6 80 92.3 104.7 16.6 11.2 34.7 19.9 53.8 25.8 2.5.9 5.1 1.8 7.7 2.7-.8-.3-1.6-.7-2.4-1 22.6 6.8 46.2 10.3 69.8 10.3 83.7 0 111.3-31.9 113.8-35 4.1-3.7 7.5-8.2 9.9-13.3 1.6-.7 3.2-1.4 4.9-2.1l1-.5 1.9-.9c12.6-5.9 24.5-13.4 35.3-22.1 16.3-11.7 27.9-28.7 32.9-48.1 3-7.1 3.1-15 .4-22.2.9-1.4 1.7-2.8 2.7-4.3 18-28.9 28.2-61.9 29.6-95.9v-2.8c0-7.3-.6-14.5-1.9-21.6z"],"first-order":[448,512,[],"f2b0","M12.9 229.2c.1-.1.2-.3.3-.4 0 .1 0 .3-.1.4h-.2zM224 96.6c-7.1 0-14.6.6-21.4 1.7l3.7 67.4-22-64c-14.3 3.7-27.7 9.4-40 16.6l29.4 61.4-45.1-50.9c-11.4 8.9-21.7 19.1-30.6 30.9l50.6 45.4-61.1-29.7c-7.1 12.3-12.9 25.7-16.6 40l64.3 22.6-68-4c-.9 7.1-1.4 14.6-1.4 22s.6 14.6 1.4 21.7l67.7-4-64 22.6c3.7 14.3 9.4 27.7 16.6 40.3l61.1-29.7L97.7 352c8.9 11.7 19.1 22.3 30.9 30.9l44.9-50.9-29.5 61.4c12.3 7.4 25.7 13.1 40 16.9l22.3-64.6-4 68c7.1 1.1 14.6 1.7 21.7 1.7 7.4 0 14.6-.6 21.7-1.7l-4-68.6 22.6 65.1c14.3-4 27.7-9.4 40-16.9L274.9 332l44.9 50.9c11.7-8.9 22-19.1 30.6-30.9l-50.6-45.1 61.1 29.4c7.1-12.3 12.9-25.7 16.6-40.3l-64-22.3 67.4 4c1.1-7.1 1.4-14.3 1.4-21.7s-.3-14.9-1.4-22l-67.7 4 64-22.3c-3.7-14.3-9.1-28-16.6-40.3l-60.9 29.7 50.6-45.4c-8.9-11.7-19.1-22-30.6-30.9l-45.1 50.9 29.4-61.1c-12.3-7.4-25.7-13.1-40-16.9L241.7 166l4-67.7c-7.1-1.2-14.3-1.7-21.7-1.7zM443.4 128v256L224 512 4.6 384V128L224 0l219.4 128zm-17.1 10.3L224 20.9 21.7 138.3v235.1L224 491.1l202.3-117.7V138.3zM224 37.1l187.7 109.4v218.9L224 474.9 36.3 365.4V146.6L224 37.1zm0 50.9c-92.3 0-166.9 75.1-166.9 168 0 92.6 74.6 167.7 166.9 167.7 92 0 166.9-75.1 166.9-167.7 0-92.9-74.9-168-166.9-168z"],firstdraft:[384,512,[],"f3a1","M384 192h-64v128H192v128H0v-25.6h166.4v-128h128v-128H384V192zm-25.6 38.4v128h-128v128H64V512h192V384h128V230.4h-25.6zm25.6 192h-89.6V512H320v-64h64v-25.6zM0 0v384h128V256h128V128h128V0H0z"],flickr:[448,512,[],"f16e","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM144.5 319c-35.1 0-63.5-28.4-63.5-63.5s28.4-63.5 63.5-63.5 63.5 28.4 63.5 63.5-28.4 63.5-63.5 63.5zm159 0c-35.1 0-63.5-28.4-63.5-63.5s28.4-63.5 63.5-63.5 63.5 28.4 63.5 63.5-28.4 63.5-63.5 63.5z"],fly:[384,512,[],"f417","M197.8 427.8c12.9 11.7 33.7 33.3 33.2 50.7 0 .8-.1 1.6-.1 2.5-1.8 19.8-18.8 31.1-39.1 31-25-.1-39.9-16.8-38.7-35.8 1-16.2 20.5-36.7 32.4-47.6 2.3-2.1 2.7-2.7 5.6-3.6 3.4 0 3.9.3 6.7 2.8zM331.9 67.3c-16.3-25.7-38.6-40.6-63.3-52.1C243.1 4.5 214-.2 192 0c-44.1 0-71.2 13.2-81.1 17.3C57.3 45.2 26.5 87.2 28 158.6c7.1 82.2 97 176 155.8 233.8 1.7 1.6 4.5 4.5 6.2 5.1l3.3.1c2.1-.7 1.8-.5 3.5-2.1 52.3-49.2 140.7-145.8 155.9-215.7 7-39.2 3.1-72.5-20.8-112.5zM186.8 351.9c-28-51.1-65.2-130.7-69.3-189-3.4-47.5 11.4-131.2 69.3-136.7v325.7zM328.7 180c-16.4 56.8-77.3 128-118.9 170.3C237.6 298.4 275 217 277 158.4c1.6-45.9-9.8-105.8-48-131.4 88.8 18.3 115.5 98.1 99.7 153z"],"font-awesome":[448,512,[],"f2b4","M397.8 32H50.2C22.7 32 0 54.7 0 82.2v347.6C0 457.3 22.7 480 50.2 480h347.6c27.5 0 50.2-22.7 50.2-50.2V82.2c0-27.5-22.7-50.2-50.2-50.2zm-45.4 284.3c0 4.2-3.6 6-7.8 7.8-16.7 7.2-34.6 13.7-53.8 13.7-26.9 0-39.4-16.7-71.7-16.7-23.3 0-47.8 8.4-67.5 17.3-1.2.6-2.4.6-3.6 1.2V385c0 1.8 0 3.6-.6 4.8v1.2c-2.4 8.4-10.2 14.3-19.1 14.3-11.3 0-20.3-9-20.3-20.3V166.4c-7.8-6-13.1-15.5-13.1-26.3 0-18.5 14.9-33.5 33.5-33.5 18.5 0 33.5 14.9 33.5 33.5 0 10.8-4.8 20.3-13.1 26.3v18.5c1.8-.6 3.6-1.2 5.4-2.4 18.5-7.8 40.6-14.3 61.5-14.3 22.7 0 40.6 6 60.9 13.7 4.2 1.8 8.4 2.4 13.1 2.4 22.7 0 47.8-16.1 53.8-16.1 4.8 0 9 3.6 9 7.8v140.3z"],"font-awesome-alt":[448,512,[],"f35c","M397.8 67.8c7.8 0 14.3 6.6 14.3 14.3v347.6c0 7.8-6.6 14.3-14.3 14.3H50.2c-7.8 0-14.3-6.6-14.3-14.3V82.2c0-7.8 6.6-14.3 14.3-14.3h347.6m0-35.9H50.2C22.7 32 0 54.7 0 82.2v347.6C0 457.3 22.7 480 50.2 480h347.6c27.5 0 50.2-22.7 50.2-50.2V82.2c0-27.5-22.7-50.2-50.2-50.2zm-58.5 139.2c-6 0-29.9 15.5-52.6 15.5-4.2 0-8.4-.6-12.5-2.4-19.7-7.8-37-13.7-59.1-13.7-20.3 0-41.8 6.6-59.7 13.7-1.8.6-3.6 1.2-4.8 1.8v-17.9c7.8-6 12.5-14.9 12.5-25.7 0-17.9-14.3-32.3-32.3-32.3s-32.3 14.3-32.3 32.3c0 10.2 4.8 19.7 12.5 25.7v212.1c0 10.8 9 19.7 19.7 19.7 9 0 16.1-6 18.5-13.7V385c.6-1.8.6-3 .6-4.8V336c1.2 0 2.4-.6 3-1.2 19.7-8.4 43-16.7 65.7-16.7 31.1 0 43 16.1 69.3 16.1 18.5 0 36.4-6.6 52-13.7 4.2-1.8 7.2-3.6 7.2-7.8V178.3c1.8-4.1-2.3-7.1-7.7-7.1z"],"font-awesome-flag":[448,512,[],"f425","M444.373 359.424c0 7.168-6.144 10.24-13.312 13.312-28.672 12.288-59.392 23.552-92.16 23.552-46.08 0-67.584-28.672-122.88-28.672-39.936 0-81.92 14.336-115.712 29.696-2.048 1.024-4.096 1.024-6.144 2.048v77.824c0 21.405-16.122 34.816-33.792 34.816-19.456 0-34.816-15.36-34.816-34.816V102.4C12.245 92.16 3.029 75.776 3.029 57.344 3.029 25.6 28.629 0 60.373 0s57.344 25.6 57.344 57.344c0 18.432-8.192 34.816-22.528 45.056v31.744c4.124-1.374 58.768-28.672 114.688-28.672 65.27 0 97.676 27.648 126.976 27.648 38.912 0 81.92-27.648 92.16-27.648 8.192 0 15.36 6.144 15.36 13.312v240.64z"],fonticons:[448,512,[],"f280","M0 32v448h448V32H0zm167.4 196h67.4l-11.1 37.3H168v112.9c0 5.8-2 6.7 3.2 7.3l43.5 4.1v25.1H84V389l21.3-2c5.2-.6 6.7-2.3 6.7-7.9V267.7c0-2.3-2.9-2.3-5.8-2.3H84V228h28v-21c0-49.6 26.5-70 77.3-70 34.1 0 64.7 8.2 64.7 52.8l-50.7 6.1c.3-18.7-4.4-23-16.3-23-18.4 0-19 9.9-19 27.4v23.3c0 2.4-3.5 4.4-.6 4.4zM364 414.7H261.3v-25.1l20.4-2.6c5.2-.6 7.6-1.7 7.6-7.3V271.8c0-4.1-2.9-6.7-6.7-7.9l-24.2-6.4 6.7-29.5h80.2v151.7c0 5.8-2.6 6.4 2.9 7.3l15.7 2.6v25.1zm-21.9-255.5l9 33.2-7.3 7.3-31.2-16.6-31.2 16.6-7.3-7.3 9-33.2-21.8-24.2 3.5-9.6h27.7l15.5-28h9.3l15.5 28h27.7l3.5 9.6-21.9 24.2z"],"fonticons-fi":[384,512,[],"f3a2","M114.4 224h92.4l-15.2 51.2h-76.4V433c0 8-2.8 9.2 4.4 10l59.6 5.6V483H0v-35.2l29.2-2.8c7.2-.8 9.2-3.2 9.2-10.8V278.4c0-3.2-4-3.2-8-3.2H0V224h38.4v-28.8c0-68 36.4-96 106-96 46.8 0 88.8 11.2 88.8 72.4l-69.6 8.4c.4-25.6-6-31.6-22.4-31.6-25.2 0-26 13.6-26 37.6v32c0 3.2-4.8 6-.8 6zM384 483H243.2v-34.4l28-3.6c7.2-.8 10.4-2.4 10.4-10V287c0-5.6-4-9.2-9.2-10.8l-33.2-8.8 9.2-40.4h110v208c0 8-3.6 8.8 4 10l21.6 3.6V483zm-30-347.2l12.4 45.6-10 10-42.8-22.8-42.8 22.8-10-10 12.4-45.6-30-36.4 4.8-10h38L307.2 51H320l21.2 38.4h38l4.8 13.2-30 33.2z"],"fort-awesome":[448,512,[],"f286","M412 284h-24c-2.25 0-4 1.75-4 4v28h-32V160c0-2.25-1.75-4-4-4h-24c-2.25 0-4 1.75-4 4v28h-32v-28c0-2.25-1.75-4-4-4h-24c-2.25 0-4 1.75-4 4v28h-32v-28c0-5.25-7-4-10.25-4v-33.25c7.25-1.75 15-3 22.5-3 9.501 0 18.251 3.75 27.5 3.75 4 0 24.25-1 24.25-7V64c0-2.25-1.75-4-4-4-4.5 0-13.25 3.75-21 3.75-8.499 0-18.25-3.75-28.501-3.75-7 0-14 1-20.75 2.5v-4.25c4.75-2.25 8-7.25 8-12.5 0-18.149-27.499-18.167-27.499 0 0 5.25 3.25 10.25 8 12.5V156c-3.25 0-10.25-1.25-10.25 4v28h-32v-28c0-2.25-1.75-4-4-4h-24c-2.25 0-4 1.75-4 4v28H96v-28c0-2.25-1.75-4-4-4H68c-2.25 0-4 1.75-4 4v156H32v-28c0-2.25-1.75-4-4-4H4c-2.25 0-4 1.75-4 4v192h160v-84c0-63.507 96-63.525 96 0v84h160V288c0-2.25-1.75-4-4-4zm-252-4.001c0 2.25-1.75 4-4 4h-24c-2.25 0-4-1.75-4-4V224c0-2.25 1.75-4 4-4h24c2.25 0 4 1.75 4 4v55.999zm128 0c0 2.25-1.75 4-4 4h-24c-2.25 0-4-1.75-4-4V224c0-2.25 1.75-4 4-4h24c2.25 0 4 1.75 4 4v55.999z"],"fort-awesome-alt":[512,512,[],"f3a3","M211.7 241.1v51.7c0 2.1-1.6 3.7-3.7 3.7h-22.2c-2.1 0-3.7-1.6-3.7-3.7v-51.7c0-2.1 1.6-3.7 3.7-3.7H208c2.1 0 3.7 1.6 3.7 3.7zm114.5-3.7H304c-2.1 0-3.7 1.6-3.7 3.7v51.7c0 2.1 1.6 3.7 3.7 3.7h22.2c2.1 0 3.7-1.6 3.7-3.7v-51.7c-.1-2.1-1.7-3.7-3.7-3.7zm-29.1 263.2c-.9.1-1.7.3-2.6.4-1 .2-2.1.3-3.1.5-.9.1-1.8.3-2.8.4-1 .1-2 .3-3 .4-1 .1-2 .2-2.9.3-1 .1-1.9.2-2.9.3-1 .1-2.1.2-3.1.3-.9.1-1.8.2-2.7.2-1.1.1-2.3.1-3.4.2-.8 0-1.7.1-2.5.1-1.3.1-2.6.1-3.9.1-.7 0-1.4.1-2.1.1-2 0-4 .1-6 .1s-4 0-6-.1c-.7 0-1.4 0-2.1-.1-1.3 0-2.6-.1-3.9-.1-.8 0-1.7-.1-2.5-.1-1.1-.1-2.3-.1-3.4-.2-.9-.1-1.8-.1-2.7-.2-1-.1-2.1-.2-3.1-.3-1-.1-1.9-.2-2.9-.3-1-.1-2-.2-2.9-.3-1-.1-2-.2-3-.4-.9-.1-1.8-.3-2.8-.4-1-.1-2.1-.3-3.1-.5-.9-.1-1.7-.3-2.6-.4-65.6-10.9-122.5-47.7-160-99.4-.2-.2-.3-.5-.5-.7-.8-1.1-1.6-2.2-2.3-3.3-.3-.4-.6-.8-.8-1.2-.7-1.1-1.4-2.1-2.1-3.2-.3-.5-.6-.9-.9-1.4-.7-1.1-1.4-2.1-2-3.2-.3-.5-.6-.9-.9-1.4-.7-1.1-1.3-2.2-2-3.3-.2-.4-.5-.8-.7-1.2-2.4-4-4.6-8.1-6.8-12.2-.1-.2-.2-.3-.3-.5-.6-1.1-1.1-2.2-1.7-3.3-.3-.6-.6-1.1-.8-1.7-.5-1-1-2.1-1.5-3.1-.3-.7-.6-1.3-.9-2-.5-1-.9-2-1.4-3l-.9-2.1c-.4-1-.9-2-1.3-3-.3-.7-.6-1.5-.9-2.2l-1.2-3c-.3-.8-.6-1.5-.9-2.3-.4-1-.8-2-1.1-3-.3-.9-.6-1.8-1-2.8-.6-1.6-1.1-3.3-1.7-4.9-.3-.9-.6-1.8-.9-2.8-.3-.9-.5-1.8-.8-2.7-.3-.9-.6-1.9-.8-2.8-.3-.9-.5-1.8-.8-2.7-.3-1-.5-1.9-.8-2.9-.2-.9-.5-1.8-.7-2.7-.3-1-.5-2-.7-3-.2-.9-.4-1.7-.6-2.6-.2-1.1-.5-2.2-.7-3.2-.2-.8-.3-1.6-.5-2.4-.3-1.3-.5-2.7-.8-4-.1-.6-.2-1.1-.3-1.7l-.9-5.7c-.1-.6-.2-1.3-.3-1.9-.2-1.3-.4-2.6-.5-3.9-.1-.8-.2-1.5-.3-2.3-.1-1.2-.3-2.4-.4-3.6-.1-.8-.2-1.6-.2-2.4-.1-1.2-.2-2.4-.3-3.5-.1-.8-.1-1.6-.2-2.4-.1-1.2-.2-2.4-.2-3.7 0-.8-.1-1.5-.1-2.3-.1-1.3-.1-2.7-.2-4 0-.7 0-1.3-.1-2 0-2-.1-4-.1-6 0-53.5 16.9-103 45.8-143.6 2.3-3.2 4.7-6.4 7.1-9.5 4.9-6.2 10.1-12.3 15.6-18 2.7-2.9 5.5-5.7 8.4-8.4 2.9-2.7 5.8-5.4 8.8-8 4.5-3.9 9.1-7.6 13.9-11.2 1.6-1.2 3.2-2.4 4.8-3.5C140 34.2 171.7 20.1 206 13c16.1-3.3 32.9-5 50-5s33.8 1.7 50 5c34.3 7 66 21.1 93.6 40.7 1.6 1.2 3.2 2.3 4.8 3.5 4.8 3.6 9.4 7.3 13.9 11.2 12 10.4 23 21.9 32.8 34.4 2.5 3.1 4.8 6.3 7.1 9.5C487.1 153 504 202.5 504 256c0 2 0 4-.1 6 0 .7 0 1.3-.1 2 0 1.3-.1 2.7-.2 4 0 .8-.1 1.5-.1 2.3-.1 1.2-.1 2.4-.2.7-.1.8-.1 1.6-.2 2.4-.1 1.2-.2 2.4-.3 3.5-.1.8-.2 1.6-.2 2.4-.1 1.2-.3 2.4-.4 3.6-.1.8-.2 1.5-.3 2.3-.2 1.3-.4 2.6-.5 3.9-.1.6-.2 1.3-.3 1.9l-.9 5.7c-.1.6-.2 1.1-.3 1.7-.2 1.3-.5 2.7-.8 4-.2.8-.3 1.6-.5 2.4-.2 1.1-.5 2.2-.7 3.2-.2.9-.4 1.7-.6 2.6-.2 1-.5 2-.7 3-.2.9-.5 1.8-.7 2.7-.3 1-.5 1.9-.8 2.9-.2.9-.5 1.8-.8 2.7-.3.9-.6 1.9-.8 2.8-.3.9-.5 1.8-.8 2.7-.3.9-.6 1.8-.9 2.8-.5 1.6-1.1 3.3-1.7 4.9-.3.9-.6 1.8-1 2.8-.4 1-.7 2-1.1 3-.3.8-.6 1.5-.9 2.3l-1.2 3c-.3.7-.6 1.5-.9 2.2-.4 1-.8 2-1.3 3l-.9 2.1c-.4 1-.9 2-1.4 3-.3.7-.6 1.3-.9 2-.5 1-1 2.1-1.5 3.1-.3.6-.6 1.1-.8 1.7-.6 1.1-1.1 2.2-1.7 3.3-.1.2-.2.3-.3.5-2.2 4.1-4.4 8.2-6.8 12.2-.2.4-.5.8-.7 1.2-.7 1.1-1.3 2.2-2 3.3-.3.5-.6.9-.9 1.4-.7 1.1-1.4 2.1-2 3.2-.3.5-.6.9-.9 1.4-.7 1.1-1.4 2.1-2.1 3.2-.3.4-.6.8-.8 1.2-.8 1.1-1.5 2.2-2.3 3.3-.2.2-.3.5-.5.7-37.6 54.7-94.5 91.4-160.1 102.4zm117.3-86.2c13-13 24.2-27.4 33.6-42.9v-71.3c0-2.1-1.6-3.7-3.7-3.7h-22.2c-2.1 0-3.7 1.6-3.7 3.7V326h-29.5V182c0-2.1-1.6-3.7-3.7-3.7h-22.1c-2.1 0-3.7 1.6-3.7 3.7v25.9h-29.5V182c0-2.1-1.6-3.7-3.7-3.7H304c-2.1 0-3.7 1.6-3.7 3.7v25.9h-29.5V182c0-4.8-6.5-3.7-9.5-3.7v-30.7c6.7-1.6 13.8-2.8 20.8-2.8 8.8 0 16.8 3.5 25.4 3.5 3.7 0 22.4-.9 22.4-6.5V93.4c0-2.1-1.6-3.7-3.7-3.7-4.2 0-12.2 3.5-19.4 3.5-7.9 0-16.9-3.5-26.3-3.5-6.5 0-12.9.9-19.2 2.3v-3.9c4.4-2.1 7.4-6.7 7.4-11.5 0-16.8-25.4-16.8-25.4 0 0 4.8 3 9.5 7.4 11.5v90.2c-3 0-9.5-1.1-9.5 3.7v25.9h-29.5V182c0-2.1-1.6-3.7-3.7-3.7h-22.2c-2.1 0-3.7 1.6-3.7 3.7v25.9h-29.5V182c0-2.1-1.6-3.7-3.7-3.7h-22.1c-2.1 0-3.7 1.6-3.7 3.7v144H93.5v-25.8c0-2.1-1.6-3.7-3.7-3.7H67.7c-2.1 0-3.7 1.6-3.7 3.7v71.3c9.4 15.5 20.6 29.9 33.6 42.9 20.6 20.6 44.5 36.7 71.2 48 13.9 5.9 28.2 10.3 42.9 13.2v-75.8c0-58.6 88.6-58.6 88.6 0v75.8c14.7-2.9 29-7.4 42.9-13.2 26.7-11.3 50.6-27.4 71.2-48"],forumbee:[448,512,[],"f211","M5.8 309.7C2 292.7 0 275.5 0 258.3 0 135 99.8 35 223.1 35c16.6 0 33.3 2 49.3 5.5C149 87.5 51.9 186 5.8 309.7zm392.9-189.2C385 103 369 87.8 350.9 75.2c-149.6 44.3-266.3 162.1-309.7 312 12.5 18.1 28 35.6 45.2 49 43.1-151.3 161.2-271.7 312.3-315.7zm15.8 252.7c15.2-25.1 25.4-53.7 29.5-82.8-79.4 42.9-145 110.6-187.6 190.3 30-4.4 58.9-15.3 84.6-31.3 35 13.1 70.9 24.3 107 33.6-9.3-36.5-20.4-74.5-33.5-109.8zm29.7-145.5c-2.6-19.5-7.9-38.7-15.8-56.8C290.5 216.7 182 327.5 137.1 466c18.1 7.6 37 12.5 56.6 15.2C240 367.1 330.5 274.4 444.2 227.7z"],foursquare:[368,512,[],"f180","M323.1 3H49.9C12.4 3 0 31.3 0 49.1v433.8c0 20.3 12.1 27.7 18.2 30.1 6.2 2.5 22.8 4.6 32.9-7.1C180 356.5 182.2 354 182.2 354c3.1-3.4 3.4-3.1 6.8-3.1h83.4c35.1 0 40.6-25.2 44.3-39.7l48.6-243C373.8 25.8 363.1 3 323.1 3zm-16.3 73.8l-11.4 59.7c-1.2 6.5-9.5 13.2-16.9 13.2H172.1c-12 0-20.6 8.3-20.6 20.3v13c0 12 8.6 20.6 20.6 20.6h90.4c8.3 0 16.6 9.2 14.8 18.2-1.8 8.9-10.5 53.8-11.4 58.8-.9 4.9-6.8 13.5-16.9 13.5h-73.5c-13.5 0-17.2 1.8-26.5 12.6 0 0-8.9 11.4-89.5 108.3-.9.9-1.8.6-1.8-.3V75.9c0-7.7 6.8-16.6 16.6-16.6h219c8.2 0 15.6 7.7 13.5 17.5z"],"free-code-camp":[576,512,[],"f2c5","M69.3 144.5c-41 68.5-36.4 163 1 227C92.5 409.7 120 423.9 120 438c0 6.8-6 13-12.8 13C87.7 451 8 375.5 8 253.2c0-111.5 78-186 97.1-186 6 0 14.9 4.8 14.9 11.1 0 12.7-28.3 28.6-50.7 66.2zm195.8 213.8c4.5 1.8 12.3 5.2 12.3-1.2 0-2.7-2.2-2.9-4.3-3.6-8.5-3.4-14-7.7-19.1-15.2-8.2-12.1-10.1-24.2-10.1-38.6 0-32.1 44.2-37.9 44.2-70 0-12.3-7.7-15.9-7.7-19.3 0-2.2.7-2.2 2.9-2.2 8 0 19.1 13.3 22.5 19.8 2.2 4.6 2.4 6 2.4 11.1 0 7-.7 14.2-.7 21.3 0 27 31.9 19.8 31.9 6.8 0-6-3.6-11.6-3.6-17.4 0-.7 0-1.2.7-1.2 3.4 0 9.4 7.7 11.1 10.1 5.8 8.9 8.5 20.8 8.5 31.4 0 32.4-29.5 49-29.5 56 0 1 2.9 7.7 12.1 1.9 29.7-15.1 53.1-47.6 53.1-89.8 0-33.6-8.7-57.7-32.1-82.6-3.9-4.1-16.4-16.9-22.5-16.9-8.2 0 7.2 18.6 7.2 31.2 0 7.2-4.8 12.3-12.3 12.3-11.6 0-14.5-25.4-15.9-33.3-5.8-33.8-12.8-58.2-46.4-74.1-10.4-5-36.5-11.8-36.5-2.2 0 2.4 2.7 4.1 4.6 5.1 9.2 5.6 19.6 21.4 19.6 38.2 0 46.1-57.7 88.2-57.7 136.2-.2 40.3 28.1 72.6 65.3 86.2zM470.4 67c-6 0-14.4 6.5-14.4 12.6 0 8.7 12.1 19.6 17.6 25.4 81.6 85.1 78.6 214.3 17.6 291-7 8.9-35.3 35.3-35.3 43.5 0 5.1 8.2 11.4 13.2 11.4 25.4 0 98.8-80.8 98.8-185.7C568 145.9 491.8 67 470.4 67zm-42.3 323.1H167c-9.4 0-15.5 7.5-15.5 16.4 0 8.5 7 15.5 15.5 15.5h261.1c9.4 0 11.9-7.5 11.9-16.4 0-8.5-3.5-15.5-11.9-15.5z"],freebsd:[448,512,[],"f3a4","M303.7 96.2c11.1-11.1 115.5-77 139.2-53.2 23.7 23.7-42.1 128.1-53.2 139.2-11.1 11.1-39.4.9-63.1-22.9-23.8-23.7-34.1-52-22.9-63.1zM109.9 68.1C73.6 47.5 22 24.6 5.6 41.1c-16.6 16.6 7.1 69.4 27.9 105.7 18.5-32.2 44.8-59.3 76.4-78.7zM406.7 174c3.3 11.3 2.7 20.7-2.7 26.1-20.3 20.3-87.5-27-109.3-70.1-18-32.3-11.1-53.4 14.9-48.7 5.7-3.6 12.3-7.6 19.6-11.6-29.8-15.5-63.6-24.3-99.5-24.3-119.1 0-215.6 96.5-215.6 215.6 0 119 96.5 215.6 215.6 215.6S445.3 380.1 445.3 261c0-38.4-10.1-74.5-27.7-105.8-3.9 7-7.6 13.3-10.9 18.8z"],"get-pocket":[448,512,[],"f265","M407.6 64h-367C18.5 64 0 82.5 0 104.6v135.2C0 364.5 99.7 464 224.2 464c124 0 223.8-99.5 223.8-224.2V104.6c0-22.4-17.7-40.6-40.4-40.6zm-162 268.5c-12.4 11.8-31.4 11.1-42.4 0C89.5 223.6 88.3 227.4 88.3 209.3c0-16.9 13.8-30.7 30.7-30.7 17 0 16.1 3.8 105.2 89.3 90.6-86.9 88.6-89.3 105.5-89.3 16.9 0 30.7 13.8 30.7 30.7 0 17.8-2.9 15.7-114.8 123.2z"],gg:[512,512,[],"f260","M179.2 230.4l102.4 102.4-102.4 102.4L0 256 179.2 76.8l44.8 44.8-25.6 25.6-19.2-19.2-128 128 128 128 51.5-51.5-77.1-76.5 25.6-25.6zM332.8 76.8L230.4 179.2l102.4 102.4 25.6-25.6-77.1-76.5 51.5-51.5 128 128-128 128-19.2-19.2-25.6 25.6 44.8 44.8L512 256 332.8 76.8z"],"gg-circle":[512,512,[],"f261","M257 8C120 8 9 119 9 256s111 248 248 248 248-111 248-248S394 8 257 8zm-49.5 374.8L81.8 257.1l125.7-125.7 35.2 35.4-24.2 24.2-11.1-11.1-77.2 77.2 77.2 77.2 26.6-26.6-53.1-52.9 24.4-24.4 77.2 77.2-75 75.2zm99-2.2l-35.2-35.2 24.1-24.4 11.1 11.1 77.2-77.2-77.2-77.2-26.5 26.5 53.1 52.9-24.4 24.4-77.2-77.2 75-75L432.2 255 306.5 380.6z"],git:[448,512,[],"f1d3","M18.8 221.7c0 25.3 16.2 60 41.5 68.5v1c-18.8 8.3-24 50.6 1 65.8v1C34 367 16 384.3 16 414.2c0 51.5 48.8 65.8 91.5 65.8 52 0 90.7-18.7 90.7-76 0-70.5-101-44.5-101-82.8 0-13.5 7.2-18.7 19.7-21.3 41.5-7.7 67.5-40 67.5-82.2 0-7.3-1.5-14.2-4-21 6.7-1.5 13.2-3.3 19.7-5.5v-50.5c-17.2 6.8-35.7 11.8-54.5 11.8-53.8-31-126.8 1.3-126.8 69.2zm87.7 163.8c17 0 41.2 3 41.2 25 0 21.8-19.5 26.3-37.7 26.3-17.3 0-43.3-2.7-43.3-25.2.1-22.3 22.1-26.1 39.8-26.1zM103.3 256c-22 0-31.3-13-31.3-33.8 0-49.3 61-48.8 61-.5 0 20.3-8 34.3-29.7 34.3zM432 305.5v49c-13.3 7.3-30.5 9.8-45.5 9.8-53.5 0-59.8-42.2-59.8-85.7v-87.7h.5v-1c-7 0-7.3-1.6-24 1v-47.5h24c0-22.3.3-31-1.5-41.2h56.7c-2 13.8-1.5 27.5-1.5 41.2h51v47.5s-19.3-1-51-1V281c0 14.8 3.3 32.8 21.8 32.8 9.8 0 21.3-2.8 29.3-8.3zM286 68.7c0 18.7-14.5 36.2-33.8 36.2-19.8 0-34.5-17.2-34.5-36.2 0-19.3 14.5-36.7 34.5-36.7C272 32 286 50 286 68.7zm-6.2 74.5c-1.8 14.6-1.6 199.8 0 217.8h-55.5c1.6-18.1 1.8-203 0-217.8h55.5z"],"git-square":[448,512,[],"f1d2","M140.1 348.5c12.1 0 29.5 2.1 29.5 17.9 0 15.5-13.9 18.8-27 18.8-12.3 0-30.9-2-30.9-18s15.7-18.7 28.4-18.7zm-24.7-116.6c0 14.8 6.6 24.1 22.3 24.1 15.5 0 21.2-10 21.2-24.5.1-34.4-43.5-34.8-43.5.4zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-241 93.7c-12.3 4.8-25.5 8.4-38.9 8.4-38.5-22.1-90.7.9-90.7 49.5 0 18 11.6 42.9 29.6 48.9v.7c-13.4 5.9-17.1 36.1.7 47v.7c-19.5 6.4-32.3 18.8-32.3 40.2 0 36.8 34.8 47 65.4 47 37.1 0 64.8-13.4 64.8-54.3 0-50.4-72.1-31.8-72.1-59.1 0-9.6 5.2-13.4 14.1-15.2 29.6-5.5 48.2-28.6 48.2-58.7 0-5.2-1.1-10.2-2.9-15 4.8-1.1 9.5-2.3 14.1-3.9v-36.2zm56.8 1.8h-39.6c1.3 10.6 1.1 142.6 0 155.5h39.6c-1.1-12.8-1.2-145.1 0-155.5zm4.5-53.3c0-13.4-10-26.2-24.1-26.2-14.3 0-24.6 12.5-24.6 26.2 0 13.6 10.5 25.9 24.6 25.9 13.7 0 24.1-12.5 24.1-25.9zm104.3 53.3h-36.4c0-9.8-.4-19.6 1.1-29.5h-40.5c1.3 7.3 1.1 13.6 1.1 29.5h-17.1v33.9c11.9-1.9 12.1-.7 17.1-.7v.7h-.4v62.7c0 31.1 4.5 61.2 42.7 61.2 10.7 0 23-1.8 32.5-7v-35c-5.7 3.9-13.9 5.9-20.9 5.9-13.2 0-15.5-12.9-15.5-23.4v-65.2c22.7 0 36.4.7 36.4.7v-33.8z"],github:[496,512,[],"f09b","M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"],"github-alt":[480,512,[],"f113","M186.1 328.7c0 20.9-10.9 55.1-36.7 55.1s-36.7-34.2-36.7-55.1 10.9-55.1 36.7-55.1 36.7 34.2 36.7 55.1zM480 278.2c0 31.9-3.2 65.7-17.5 95-37.9 76.6-142.1 74.8-216.7 74.8-75.8 0-186.2 2.7-225.6-74.8-14.6-29-20.2-63.1-20.2-95 0-41.9 13.9-81.5 41.5-113.6-5.2-15.8-7.7-32.4-7.7-48.8 0-21.5 4.9-32.3 14.6-51.8 45.3 0 74.3 9 108.8 36 29-6.9 58.8-10 88.7-10 27 0 54.2 2.9 80.4 9.2 34-26.7 63-35.2 107.8-35.2 9.8 19.5 14.6 30.3 14.6 51.8 0 16.4-2.6 32.7-7.7 48.2 27.5 32.4 39 72.3 39 114.2zm-64.3 50.5c0-43.9-26.7-82.6-73.5-82.6-18.9 0-37 3.4-56 6-14.9 2.3-29.8 3.2-45.1 3.2-15.2 0-30.1-.9-45.1-3.2-18.7-2.6-37-6-56-6-46.8 0-73.5 38.7-73.5 82.6 0 87.8 80.4 101.3 150.4 101.3h48.2c70.3 0 150.6-13.4 150.6-101.3zm-82.6-55.1c-25.8 0-36.7 34.2-36.7 55.1s10.9 55.1 36.7 55.1 36.7-34.2 36.7-55.1-10.9-55.1-36.7-55.1z"],"github-square":[448,512,[],"f092","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM277.3 415.7c-8.4 1.5-11.5-3.7-11.5-8 0-5.4.2-33 .2-55.3 0-15.6-5.2-25.5-11.3-30.7 37-4.1 76-9.2 76-73.1 0-18.2-6.5-27.3-17.1-39 1.7-4.3 7.4-22-1.7-45-13.9-4.3-45.7 17.9-45.7 17.9-13.2-3.7-27.5-5.6-41.6-5.6-14.1 0-28.4 1.9-41.6 5.6 0 0-31.8-22.2-45.7-17.9-9.1 22.9-3.5 40.6-1.7 45-10.6 11.7-15.6 20.8-15.6 39 0 63.6 37.3 69 74.3 73.1-4.8 4.3-9.1 11.7-10.6 22.3-9.5 4.3-33.8 11.7-48.3-13.9-9.1-15.8-25.5-17.1-25.5-17.1-16.2-.2-1.1 10.2-1.1 10.2 10.8 5 18.4 24.2 18.4 24.2 9.7 29.7 56.1 19.7 56.1 19.7 0 13.9.2 36.5.2 40.6 0 4.3-3 9.5-11.5 8-66-22.1-112.2-84.9-112.2-158.3 0-91.8 70.2-161.5 162-161.5S388 165.6 388 257.4c.1 73.4-44.7 136.3-110.7 158.3zm-98.1-61.1c-1.9.4-3.7-.4-3.9-1.7-.2-1.5 1.1-2.8 3-3.2 1.9-.2 3.7.6 3.9 1.9.3 1.3-1 2.6-3 3zm-9.5-.9c0 1.3-1.5 2.4-3.5 2.4-2.2.2-3.7-.9-3.7-2.4 0-1.3 1.5-2.4 3.5-2.4 1.9-.2 3.7.9 3.7 2.4zm-13.7-1.1c-.4 1.3-2.4 1.9-4.1 1.3-1.9-.4-3.2-1.9-2.8-3.2.4-1.3 2.4-1.9 4.1-1.5 2 .6 3.3 2.1 2.8 3.4zm-12.3-5.4c-.9 1.1-2.8.9-4.3-.6-1.5-1.3-1.9-3.2-.9-4.1.9-1.1 2.8-.9 4.3.6 1.3 1.3 1.8 3.3.9 4.1zm-9.1-9.1c-.9.6-2.6 0-3.7-1.5s-1.1-3.2 0-3.9c1.1-.9 2.8-.2 3.7 1.3 1.1 1.5 1.1 3.3 0 4.1zm-6.5-9.7c-.9.9-2.4.4-3.5-.6-1.1-1.3-1.3-2.8-.4-3.5.9-.9 2.4-.4 3.5.6 1.1 1.3 1.3 2.8.4 3.5zm-6.7-7.4c-.4.9-1.7 1.1-2.8.4-1.3-.6-1.9-1.7-1.5-2.6.4-.6 1.5-.9 2.8-.4 1.3.7 1.9 1.8 1.5 2.6z"],gitkraken:[592,512,[],"f3a6","M565.7 118.1c-2.3-6.1-9.3-9.2-15.3-6.6-5.7 2.4-8.5 8.9-6.3 14.6 10.9 29 16.9 60.5 16.9 93.3 0 134.6-100.3 245.7-230.2 262.7V358.4c7.9-1.5 15.5-3.6 23-6.2v104c106.7-25.9 185.9-122.1 185.9-236.8 0-91.8-50.8-171.8-125.8-213.3-5.7-3.2-13-.9-15.9 5-2.7 5.5-.6 12.2 4.7 15.1 67.9 37.6 113.9 110 113.9 193.2 0 93.3-57.9 173.1-139.8 205.4v-92.2c14.2-4.5 24.9-17.7 24.9-33.5 0-13.1-6.8-24.4-17.3-30.5 8.3-79.5 44.5-58.6 44.5-83.9V170c0-38-87.9-161.8-129-164.7-2.5-.2-5-.2-7.6 0C251.1 8.3 163.2 132 163.2 170v14.8c0 25.3 36.3 4.3 44.5 83.9-10.6 6.1-17.3 17.4-17.3 30.5 0 15.8 10.6 29 24.8 33.5v92.2c-81.9-32.2-139.8-112-139.8-205.4 0-83.1 46-155.5 113.9-193.2 5.4-3 7.4-9.6 4.7-15.1-2.9-5.9-10.1-8.2-15.9-5-75 41.5-125.8 121.5-125.8 213.3 0 114.7 79.2 210.8 185.9 236.8v-104c7.6 2.5 15.1 4.6 23 6.2v123.7C131.4 465.2 31 354.1 31 219.5c0-32.8 6-64.3 16.9-93.3 2.2-5.8-.6-12.2-6.3-14.6-6-2.6-13 .4-15.3 6.6C14.5 149.7 8 183.8 8 219.5c0 155.1 122.6 281.6 276.3 287.8V361.4c6.8.4 15 .5 23.4 0v145.8C461.4 501.1 584 374.6 584 219.5c0-35.7-6.5-69.8-18.3-101.4zM365.9 275.5c13 0 23.7 10.5 23.7 23.7 0 13.1-10.6 23.7-23.7 23.7-13 0-23.7-10.5-23.7-23.7 0-13.1 10.6-23.7 23.7-23.7zm-139.8 47.3c-13.2 0-23.7-10.7-23.7-23.7s10.5-23.7 23.7-23.7c13.1 0 23.7 10.6 23.7 23.7 0 13-10.5 23.7-23.7 23.7z"],gitlab:[512,512,[],"f296","M29.782 199.732L256 493.714 8.074 309.699c-6.856-5.142-9.712-13.996-7.141-21.993l28.849-87.974zm75.405-174.806c-3.142-8.854-15.709-8.854-18.851 0L29.782 199.732h131.961L105.187 24.926zm56.556 174.806L256 493.714l94.257-293.982H161.743zm349.324 87.974l-28.849-87.974L256 493.714l247.926-184.015c6.855-5.142 9.711-13.996 7.141-21.993zm-85.404-262.78c-3.142-8.854-15.709-8.854-18.851 0l-56.555 174.806h131.961L425.663 24.926z"],gitter:[384,512,[],"f426","M66.4 322.5H16V0h50.4v322.5zM166.9 76.1h-50.4V512h50.4V76.1zm100.6 0h-50.4V512h50.4V76.1zM368 76h-50.4v247H368V76z"],glide:[448,512,[],"f2a5","M252.8 148.6c0 8.8-1.6 17.7-3.4 26.4-5.8 27.8-11.6 55.8-17.3 83.6-1.4 6.3-8.3 4.9-13.7 4.9-23.8 0-30.5-26-30.5-45.5 0-29.3 11.2-68.1 38.5-83.1 4.3-2.5 9.2-4.2 14.1-4.2 11.4 0 12.3 8.3 12.3 17.9zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-64 187c0-5.1-20.8-37.7-25.5-39.5-2.2-.9-7.2-2.3-9.6-2.3-23.1 0-38.7 10.5-58.2 21.5l-.5-.5c4.3-29.4 14.6-57.2 14.6-87.4 0-44.6-23.8-62.7-67.5-62.7-71.7 0-108 70.8-108 123.5 0 54.7 32 85 86.3 85 7.5 0 6.9-.6 6.9 2.3-10.5 80.3-56.5 82.9-56.5 58.9 0-24.4 28-36.5 28.3-38-.2-7.6-29.3-17.2-36.7-17.2-21.1 0-32.7 33-32.7 50.6 0 32.3 20.4 54.7 53.3 54.7 48.2 0 83.4-49.7 94.3-91.7 9.4-37.7 7-39.4 12.3-42.1 20-10.1 35.8-16.8 58.4-16.8 11.1 0 19 2.3 36.7 5.2 1.8.1 4.1-1.7 4.1-3.5z"],"glide-g":[448,512,[],"f2a6","M407.1 211.2c-3.5-1.4-11.6-3.8-15.4-3.8-37.1 0-62.2 16.8-93.5 34.5l-.9-.9c7-47.3 23.5-91.9 23.5-140.4C320.8 29.1 282.6 0 212.4 0 97.3 0 39 113.7 39 198.4 39 286.3 90.3 335 177.6 335c12 0 11-1 11 3.8-16.9 128.9-90.8 133.1-90.8 94.6 0-39.2 45-58.6 45.5-61-.3-12.2-47-27.6-58.9-27.6-33.9.1-52.4 51.2-52.4 79.3C32 476 64.8 512 117.5 512c77.4 0 134-77.8 151.4-145.4 15.1-60.5 11.2-63.3 19.7-67.6 32.2-16.2 57.5-27 93.8-27 17.8 0 30.5 3.7 58.9 8.4 2.9 0 6.7-2.9 6.7-5.8 0-8-33.4-60.5-40.9-63.4zm-175.3-84.4c-9.3 44.7-18.6 89.6-27.8 134.3-2.3 10.2-13.3 7.8-22 7.8-38.3 0-49-41.8-49-73.1 0-47 18-109.3 61.8-133.4 7-4.1 14.8-6.7 22.6-6.7 18.6 0 20 13.3 20 28.7-.1 14.3-2.7 28.5-5.6 42.4z"],gofore:[400,512,[],"f3a7","M324 319.8h-13.2v34.7c-24.5 23.1-56.3 35.8-89.9 35.8-73.2 0-132.4-60.2-132.4-134.4 0-74.1 59.2-134.4 132.4-134.4 35.3 0 68.6 14 93.6 39.4l62.3-63.3C335 55.3 279.7 32 220.7 32 98 32 0 132.6 0 256c0 122.5 97 224 220.7 224 63.2 0 124.5-26.2 171-82.5-2-27.6-13.4-77.7-67.7-77.7zm-12.1-112.5H205.6v89H324c33.5 0 60.5 15.1 76 41.8v-30.6c0-65.2-40.4-100.2-88.1-100.2z"],goodreads:[448,512,[],"f3a8","M299.9 191.2c5.1 37.3-4.7 79-35.9 100.7-22.3 15.5-52.8 14.1-70.8 5.7-37.1-17.3-49.5-58.6-46.8-97.2 4.3-60.9 40.9-87.9 75.3-87.5 46.9-.2 71.8 31.8 78.2 78.3zM448 88v336c0 30.9-25.1 56-56 56H56c-30.9 0-56-25.1-56-56V88c0-30.9 25.1-56 56-56h336c30.9 0 56 25.1 56 56zM330 313.2s-.1-34-.1-217.3h-29v40.3c-.8.3-1.2-.5-1.6-1.2-9.6-20.7-35.9-46.3-76-46-51.9.4-87.2 31.2-100.6 77.8-4.3 14.9-5.8 30.1-5.5 45.6 1.7 77.9 45.1 117.8 112.4 115.2 28.9-1.1 54.5-17 69-45.2.5-1 1.1-1.9 1.7-2.9.2.1.4.1.6.2.3 3.8.2 30.7.1 34.5-.2 14.8-2 29.5-7.2 43.5-7.8 21-22.3 34.7-44.5 39.5-17.8 3.9-35.6 3.8-53.2-1.2-21.5-6.1-36.5-19-41.1-41.8-.3-1.6-1.3-1.3-2.3-1.3h-26.8c.8 10.6 3.2 20.3 8.5 29.2 24.2 40.5 82.7 48.5 128.2 37.4 49.9-12.3 67.3-54.9 67.4-106.3z"],"goodreads-g":[384,512,[],"f3a9","M42.6 403.3h2.8c12.7 0 25.5 0 38.2.1 1.6 0 3.1-.4 3.6 2.1 7.1 34.9 30 54.6 62.9 63.9 26.9 7.6 54.1 7.8 81.3 1.8 33.8-7.4 56-28.3 68-60.4 8-21.5 10.7-43.8 11-66.5.1-5.8.3-47-.2-52.8l-.9-.3c-.8 1.5-1.7 2.9-2.5 4.4-22.1 43.1-61.3 67.4-105.4 69.1-103 4-169.4-57-172-176.2-.5-23.7 1.8-46.9 8.3-69.7C58.3 47.7 112.3.6 191.6 0c61.3-.4 101.5 38.7 116.2 70.3.5 1.1 1.3 2.3 2.4 1.9V10.6h44.3c0 280.3.1 332.2.1 332.2-.1 78.5-26.7 143.7-103 162.2-69.5 16.9-159 4.8-196-57.2-8-13.5-11.8-28.3-13-44.5zM188.9 36.5c-52.5-.5-108.5 40.7-115 133.8-4.1 59 14.8 122.2 71.5 148.6 27.6 12.9 74.3 15 108.3-8.7 47.6-33.2 62.7-97 54.8-154-9.7-71.1-47.8-120-119.6-119.7z"],google:[488,512,[],"f1a0","M488 261.8C488 403.3 391.1 504 248 504 110.8 504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z"],"google-drive":[512,512,[],"f3aa","M339 314.9L175.4 32h161.2l163.6 282.9H339zm-137.5 23.6L120.9 480h310.5L512 338.5H201.5zM154.1 67.4L0 338.5 80.6 480 237 208.8 154.1 67.4z"],"google-play":[512,512,[],"f3ab","M325.3 234.3L104.6 13l280.8 161.2-60.1 60.1zM47 0C34 6.8 25.3 19.2 25.3 35.3v441.3c0 16.1 8.7 28.5 21.7 35.3l256.6-256L47 0zm425.2 225.6l-58.9-34.1-65.7 64.5 65.7 64.5 60.1-34.1c18-14.3 18-46.5-1.2-60.8zM104.6 499l280.8-161.2-60.1-60.1L104.6 499z"],"google-plus":[496,512,[],"f2b3","M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8zm-70.7 372c-68.8 0-124-55.5-124-124s55.2-124 124-124c31.3 0 60.1 11 83 32.3l-33.6 32.6c-13.2-12.9-31.3-19.1-49.4-19.1-42.9 0-77.2 35.5-77.2 78.1s34.2 78.1 77.2 78.1c32.6 0 64.9-19.1 70.1-53.3h-70.1v-42.6h116.9c1.3 6.8 1.9 13.6 1.9 20.7 0 70.8-47.5 121.2-118.8 121.2zm230.2-106.2v35.5H372v-35.5h-35.5v-35.5H372v-35.5h35.5v35.5h35.2v35.5h-35.2z"],"google-plus-g":[640,512,[],"f0d5","M386.061 228.496c1.834 9.692 3.143 19.384 3.143 31.956C389.204 370.205 315.599 448 204.8 448c-106.084 0-192-85.915-192-192s85.916-192 192-192c51.864 0 95.083 18.859 128.611 50.292l-52.126 50.03c-14.145-13.621-39.028-29.599-76.485-29.599-65.484 0-118.92 54.221-118.92 121.277 0 67.056 53.436 121.277 118.92 121.277 75.961 0 104.513-54.745 108.965-82.773H204.8v-66.009h181.261zm185.406 6.437V179.2h-56.001v55.733h-55.733v56.001h55.733v55.733h56.001v-55.733H627.2v-56.001h-55.733z"],"google-plus-square":[448,512,[],"f0d4","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM164 356c-55.3 0-100-44.7-100-100s44.7-100 100-100c27 0 49.5 9.8 67 26.2l-27.1 26.1c-7.4-7.1-20.3-15.4-39.8-15.4-34.1 0-61.9 28.2-61.9 63.2 0 34.9 27.8 63.2 61.9 63.2 39.6 0 54.4-28.5 56.8-43.1H164v-34.4h94.4c1 5 1.6 10.1 1.6 16.6 0 57.1-38.3 97.6-96 97.6zm220-81.8h-29v29h-29.2v-29h-29V245h29v-29H355v29h29v29.2z"],"google-wallet":[448,512,[],"f1ee","M156.8 126.8c37.6 60.6 64.2 113.1 84.3 162.5-8.3 33.8-18.8 66.5-31.3 98.3-13.2-52.3-26.5-101.3-56-148.5 6.5-36.4 2.3-73.6 3-112.3zM109.3 200H16.1c-6.5 0-10.5 7.5-6.5 12.7C51.8 267 81.3 330.5 101.3 400h103.5c-16.2-69.7-38.7-133.7-82.5-193.5-3-4-8-6.5-13-6.5zm47.8-88c68.5 108 130 234.5 138.2 368H409c-12-138-68.4-265-143.2-368H157.1zm251.8-68.5c-1.8-6.8-8.2-11.5-15.2-11.5h-88.3c-5.3 0-9 5-7.8 10.3 13.2 46.5 22.3 95.5 26.5 146 48.2 86.2 79.7 178.3 90.6 270.8 15.8-60.5 25.3-133.5 25.3-203 0-73.6-12.1-145.1-31.1-212.6z"],gratipay:[496,512,[],"f184","M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8zm114.6 226.4l-113 152.7-112.7-152.7c-8.7-11.9-19.1-50.4 13.6-72 28.1-18.1 54.6-4.2 68.5 11.9 15.9 17.9 46.6 16.9 61.7 0 13.9-16.1 40.4-30 68.1-11.9 32.9 21.6 22.6 60 13.8 72z"],grav:[512,512,[],"f2d6","M301.1 212c4.4 4.4 4.4 11.9 0 16.3l-9.7 9.7c-4.4 4.7-11.9 4.7-16.6 0l-10.5-10.5c-4.4-4.7-4.4-11.9 0-16.6l9.7-9.7c4.4-4.4 11.9-4.4 16.6 0l10.5 10.8zm-30.2-19.7c3-3 3-7.8 0-10.5-2.8-3-7.5-3-10.5 0-2.8 2.8-2.8 7.5 0 10.5 3.1 2.8 7.8 2.8 10.5 0zm-26 5.3c-3 2.8-3 7.5 0 10.2 2.8 3 7.5 3 10.5 0 2.8-2.8 2.8-7.5 0-10.2-3-3-7.7-3-10.5 0zm72.5-13.3c-19.9-14.4-33.8-43.2-11.9-68.1 21.6-24.9 40.7-17.2 59.8.8 11.9 11.3 29.3 24.9 17.2 48.2-12.5 23.5-45.1 33.2-65.1 19.1zm47.7-44.5c-8.9-10-23.3 6.9-15.5 16.1 7.4 9 32.1 2.4 15.5-16.1zM504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-66.2 42.6c2.5-16.1-20.2-16.6-25.2-25.7-13.6-24.1-27.7-36.8-54.5-30.4 11.6-8 23.5-6.1 23.5-6.1.3-6.4 0-13-9.4-24.9 3.9-12.5.3-22.4.3-22.4 15.5-8.6 26.8-24.4 29.1-43.2 3.6-31-18.8-59.2-49.8-62.8-22.1-2.5-43.7 7.7-54.3 25.7-23.2 40.1 1.4 70.9 22.4 81.4-14.4-1.4-34.3-11.9-40.1-34.3-6.6-25.7 2.8-49.8 8.9-61.4 0 0-4.4-5.8-8-8.9 0 0-13.8 0-24.6 5.3 11.9-15.2 25.2-14.4 25.2-14.4 0-6.4-.6-14.9-3.6-21.6-5.4-11-23.8-12.9-31.7 2.8.1-.2.3-.4.4-.5-5 11.9-1.1 55.9 16.9 87.2-2.5 1.4-9.1 6.1-13 10-21.6 9.7-56.2 60.3-56.2 60.3-28.2 10.8-77.2 50.9-70.6 79.7.3 3 1.4 5.5 3 7.5-2.8 2.2-5.5 5-8.3 8.3-11.9 13.8-5.3 35.2 17.7 24.4 15.8-7.2 29.6-20.2 36.3-30.4 0 0-5.5-5-16.3-4.4 27.7-6.6 34.3-9.4 46.2-9.1 8 3.9 8-34.3 8-34.3 0-14.7-2.2-31-11.1-41.5 12.5 12.2 29.1 32.7 28 60.6-.8 18.3-15.2 23-15.2 23-9.1 16.6-43.2 65.9-30.4 106 0 0-9.7-14.9-10.2-22.1-17.4 19.4-46.5 52.3-24.6 64.5 26.6 14.7 108.8-88.6 126.2-142.3 34.6-20.8 55.4-47.3 63.9-65 22 43.5 95.3 94.5 101.1 59z"],gripfire:[384,512,[],"f3ac","M171.8 503.8c0-5.3 4.8-12.2 4.8-22.3 0-15.2-13-39.9-78.1-86.6C64.2 365.8 32 336.4 32 286.6 32 171.9 179.1 110.1 179.1 18c0-3.3-.2-6.7-.6-10 5.1 2.4 39.1 43.3 39.1 90.4 0 80.5-105.1 129.2-105.1 203 0 26.9 16.6 47.2 32.6 69.5 22.5 30.2 44.2 56.9 44.2 86.5-.1 14.5-4.4 29.7-17.5 46.4zm146-241.4c1.5 8.4 2.2 16.6 2.2 24.6 0 51.8-29.4 97.5-67.3 136.8-1 1-2.2 2.4-3.2 2.4-3.6 0-35.5-41.6-35.5-53.2 0 0 41.8-55.7 41.8-96.9 0-10.8-2.7-21.7-9.1-33.4-1.5 32.3-55.7 87.7-58.1 87.7-2.7 0-17.9-22-17.9-42.1 0-5.3 1-10.7 3.2-15.8 2.4-5.5 56.6-72 56.6-116.7 0-6.2-1-12-3.4-17.1l-4-7.2c16.7 6.5 82.6 64.1 94.7 130.9"],grunt:[384,512,[],"f3ad","M61.3 189.3c-1.1 10 5.2 19.1 5.2 19.1.7-7.5 2.2-12.8 4-16.6.4 10.3 3.2 23.5 12.8 34.1 6.9 7.6 35.6 23.3 54.9 6.1 1 2.4 2.1 5.3 3 8.5 2.9 10.3-2.7 25.3-2.7 25.3s15.1-17.1 13.9-32.5c10.8-.5 21.4-8.4 21.1-19.5 0 0-18.9 10.4-35.5-8.8-9.7-11.2-40.9-42-83.1-31.8 4.3 1 8.9 2.4 13.5 4.1h-.1c-4.2 2-6.5 7.1-7 12zm28.3-1.8c19.5 11 37.4 25.7 44.9 37-5.7 3.3-21.7 10.4-38-1.7-10.3-7.6-9.8-26.2-6.9-35.3zm79.2 233.7c2.2 2.3 1.5 5.3.9 6.8-1.1 2.7-5.5 11.6-13 19.8-2.7 2.9-6.6 4.6-11 4.6-4.3 0-8.7-1.6-11.8-4.3-2.3-2.1-10.2-9.5-13.7-18.6-1.3-3.4-1-6.1.9-8.1 1.3-1.3 4-2.9 9.5-2.9H160c4.1 0 7 .9 8.8 2.7zm62.9-187.9c-1.2 15.5 13.9 32.5 13.9 32.5s-5.6-15-2.7-25.3c.9-3.2 2-6 3-8.5 19.3 17.3 48 1.5 54.8-6.1 9.6-10.6 12.3-23.8 12.8-34.1 1.8 3.8 3.4 9.1 4 16.6 0 0 6.4-9.1 5.2-19.1-.6-5-2.9-10-7-11.8h-.1c4.6-1.8 9.2-3.2 13.5-4.1-42.3-10.2-73.4 20.6-83.1 31.8-16.7 19.2-35.5 8.8-35.5 8.8-.2 10.9 10.4 18.9 21.2 19.3zm17.8-8.8c7.5-11.4 25.4-26 44.9-37 3 9.1 3.4 27.7-7 35.4-16.3 12.1-32.2 5-37.9 1.6-.1.1 0 0 0 0zM263 421.4c1.9 1.9 2.2 4.6.9 7.9-3.5 8.9-11.4 16.1-13.7 18.1-3.1 2.6-7.4 4.2-11.8 4.2s-8.3-1.6-11-4.5c-7.5-8-12-16.7-13-19.3-.6-1.5-1.3-4.4.9-6.7 1.7-1.8 4.7-2.7 8.9-2.7h29.4c5.4.1 8.1 1.7 9.4 3zm-98.3-251.5c9.9 6 18.8 8.1 27.3 8.3 8.5-.2 17.4-2.3 27.3-8.3 0 0-14.5 17.7-27.2 17.8h-.2c-12.7-.2-27.2-17.8-27.2-17.8zm184.5 147.4c-2.4 17.9-13 33.8-24.6 43.7-3.1-22.7-3.7-55.5-3.7-62.4 0-14.7 9.5-24.5 12.2-26.1 2.5-1.5 5.4-3 8.3-4.6 18-9.6 40.4-21.6 40.4-43.7 0-16.2-9.3-23.2-15.4-27.8-.8-.6-1.5-1.1-2.2-1.7-2.1-1.7-3.7-3-4.3-4.4-4.4-9.8-3.6-34.2-1.7-37.6.6-.6 16.7-20.9 11.8-39.2-2-7.4-6.9-13.3-14.1-17-5.3-2.7-11.9-4.2-19.5-4.5-.1-2-.5-3.9-.9-5.9-.6-2.6-1.1-5.3-.9-8.1.4-4.7.8-9 2.2-11.3 8.4-13.3 28.8-17.6 29-17.6l12.3-2.4-8.1-9.5c-.1-.2-17.3-17.5-46.3-17.5-7.9 0-16 1.3-24.1 3.9-24.2 7.8-42.9 30.5-49.4 39.3-3.1-1-6.3-1.9-9.6-2.7-4.2-15.8 9-38.5 9-38.5s-13.6-3-33.7 15.2c-2.6-6.5-8.1-20.5-1.8-37.2C184.6 10.1 177.2 26 175 40.4c-7.6-5.4-6.7-23.1-7.2-27.6-7.5.9-29.2 21.9-28.2 48.3-2 .5-3.9 1.1-5.9 1.7-6.5-8.8-25.1-31.5-49.4-39.3-7.9-2.2-16-3.5-23.9-3.5-29 0-46.1 17.3-46.3 17.5L6 46.9l12.3 2.4c.2 0 20.6 4.3 29 17.6 1.4 2.2 1.8 6.6 2.2 11.3.2 2.8-.4 5.5-.9 8.1-.4 1.9-.8 3.9-.9 5.9-7.7.3-14.2 1.8-19.5 4.5-7.2 3.7-12.1 9.6-14.1 17-5 18.2 11.2 38.5 11.8 39.2 1.9 3.4 2.7 27.8-1.7 37.6-.6 1.4-2.2 2.7-4.3 4.4-.7.5-1.4 1.1-2.2 1.7-6.1 4.6-15.4 11.7-15.4 27.8 0 22.1 22.4 34.1 40.4 43.7 3 1.6 5.8 3.1 8.3 4.6 2.7 1.6 12.2 11.4 12.2 26.1 0 6.9-.6 39.7-3.7 62.4-11.6-9.9-22.2-25.9-24.6-43.8 0 0-29.2 22.6-20.6 70.8 5.2 29.5 23.2 46.1 47 54.7 8.8 19.1 29.4 45.7 67.3 49.6C143 504.3 163 512 192.2 512h.2c29.1 0 49.1-7.7 63.6-19.5 37.9-3.9 58.5-30.5 67.3-49.6 23.8-8.7 41.7-25.2 47-54.7 8.2-48.4-21.1-70.9-21.1-70.9zM305.7 37.7c5.6-1.8 11.6-2.7 17.7-2.7 11 0 19.9 3 24.7 5-3.1 1.4-6.4 3.2-9.7 5.3-2.4-.4-5.6-.8-9.2-.8-10.5 0-20.5 3.1-28.7 8.9-12.3 8.7-18 16.9-20.7 22.4-2.2-1.3-4.5-2.5-7.1-3.7-1.6-.8-3.1-1.5-4.7-2.2 6.1-9.1 19.9-26.5 37.7-32.2zm21 18.2c-.8 1-1.6 2.1-2.3 3.2-3.3 5.2-3.9 11.6-4.4 17.8-.5 6.4-1.1 12.5-4.4 17-4.2.8-8.1 1.7-11.5 2.7-2.3-3.1-5.6-7-10.5-11.2 1.4-4.8 5.5-16.1 13.5-22.5 5.6-4.3 12.2-6.7 19.6-7zM45.6 45.3c-3.3-2.2-6.6-4-9.7-5.3 4.8-2 13.7-5 24.7-5 6.1 0 12 .9 17.7 2.7 17.8 5.8 31.6 23.2 37.7 32.1-1.6.7-3.2 1.4-4.8 2.2-2.5 1.2-4.9 2.5-7.1 3.7-2.6-5.4-8.3-13.7-20.7-22.4-8.3-5.8-18.2-8.9-28.8-8.9-3.4.1-6.6.5-9 .9zm44.7 40.1c-4.9 4.2-8.3 8-10.5 11.2-3.4-.9-7.3-1.9-11.5-2.7C65 89.5 64.5 83.4 64 77c-.5-6.2-1.1-12.6-4.4-17.8-.7-1.1-1.5-2.2-2.3-3.2 7.4.3 14 2.6 19.5 7 8 6.3 12.1 17.6 13.5 22.4zM58.1 259.9c-2.7-1.6-5.6-3.1-8.4-4.6-14.9-8-30.2-16.3-30.2-30.5 0-11.1 4.3-14.6 8.9-18.2l.5-.4c.7-.6 1.4-1.2 2.2-1.8-.9 7.2-1.9 13.3-2.7 14.9 0 0 12.1-15 15.7-44.3 1.4-11.5-1.1-34.3-5.1-43 .2 4.9 0 9.8-.3 14.4-.4-.8-.8-1.6-1.3-2.2-3.2-4-11.8-17.5-9.4-26.6.9-3.5 3.1-6 6.7-7.8 3.8-1.9 8.8-2.9 15.1-2.9 12.3 0 25.9 3.7 32.9 6 25.1 8 55.4 30.9 64.1 37.7.2.2.4.3.4.3l5.6 3.9-3.5-5.8c-.2-.3-19.1-31.4-53.2-46.5 2-2.9 7.4-8.1 21.6-15.1 21.4-10.5 46.5-15.8 74.3-15.8 27.9 0 52.9 5.3 74.3 15.8 14.2 6.9 19.6 12.2 21.6 15.1-34 15.1-52.9 46.2-53.1 46.5l-3.5 5.8 5.6-3.9s.2-.1.4-.3c8.7-6.8 39-29.8 64.1-37.7 7-2.2 20.6-6 32.9-6 6.3 0 11.3 1 15.1 2.9 3.5 1.8 5.7 4.4 6.7 7.8 2.5 9.1-6.1 22.6-9.4 26.6-.5.6-.9 1.3-1.3 2.2-.3-4.6-.5-9.5-.3-14.4-4 8.8-6.5 31.5-5.1 43 3.6 29.3 15.7 44.3 15.7 44.3-.8-1.6-1.8-7.7-2.7-14.9.7.6 1.5 1.2 2.2 1.8l.5.4c4.6 3.7 8.9 7.1 8.9 18.2 0 14.2-15.4 22.5-30.2 30.5-2.9 1.5-5.7 3.1-8.4 4.6-8.7 5-18 16.7-19.1 34.2-.9 14.6.9 49.9 3.4 75.9-12.4 4.8-26.7 6.4-39.7 6.8-2-4.1-3.9-8.5-5.5-13.1-.7-2-19.6-51.1-26.4-62.2 5.5 39 17.5 73.7 23.5 89.6-3.5-.5-7.3-.7-11.7-.7h-117c-4.4 0-8.3.3-11.7.7 6-15.9 18.1-50.6 23.5-89.6-6.8 11.2-25.7 60.3-26.4 62.2-1.6 4.6-3.5 9-5.5 13.1-13-.4-27.2-2-39.7-6.8 2.5-26 4.3-61.2 3.4-75.9-.9-17.4-10.3-29.2-19-34.2zM34.8 404.6c-12.1-20-8.7-54.1-3.7-59.1 10.9 34.4 47.2 44.3 74.4 45.4-2.7 4.2-5.2 7.6-7 10l-1.4 1.4c-7.2 7.8-8.6 18.5-4.1 31.8-22.7-.1-46.3-9.8-58.2-29.5zm45.7 43.5c6 1.1 12.2 1.9 18.6 2.4 3.5 8 7.4 15.9 12.3 23.1-14.4-5.9-24.4-16-30.9-25.5zM192 498.2c-60.6-.1-78.3-45.8-84.9-64.7-3.7-10.5-3.4-18.2.9-23.1 2.9-3.3 9.5-7.2 24.6-7.2h118.8c15.1 0 21.8 3.9 24.6 7.2 4.2 4.8 4.5 12.6.9 23.1-6.6 18.8-24.3 64.6-84.9 64.7zm80.6-24.6c4.9-7.2 8.8-15.1 12.3-23.1 6.4-.5 12.6-1.3 18.6-2.4-6.5 9.5-16.5 19.6-30.9 25.5zm76.6-69c-12 19.7-35.6 29.3-58.1 29.7 4.5-13.3 3.1-24.1-4.1-31.8-.4-.5-.9-1-1.4-1.5-1.8-2.4-4.3-5.8-7-10 27.2-1.2 63.5-11 74.4-45.4 5 5 8.4 39.1-3.8 59z"],gulp:[256,512,[],"f3ae","M209.8 391.1l-14.1 24.6-4.6 80.2c0 8.9-28.3 16.1-63.1 16.1s-63.1-7.2-63.1-16.1l-5.8-79.4-14.9-25.4c41.2 17.3 126 16.7 165.6 0zm-196-253.3l13.6 125.5c5.9-20 20.8-47 40-55.2 6.3-2.7 12.7-2.7 18.7.9 5.2 3 9.6 9.3 10.1 11.8 1.2 6.5-2 9.1-4.5 9.1-3 0-5.3-4.6-6.8-7.3-4.1-7.3-10.3-7.6-16.9-2.8-6.9 5-12.9 13.4-17.1 20.7-5.1 8.8-9.4 18.5-12 28.2-1.5 5.6-2.9 14.6-.6 19.9 1 2.2 2.5 3.6 4.9 3.6 5 0 12.3-6.6 15.8-10.1 4.5-4.5 10.3-11.5 12.5-16l5.2-15.5c2.6-6.8 9.9-5.6 9.9 0 0 10.2-3.7 13.6-10 34.7-5.8 19.5-7.6 25.8-7.6 25.8-.7 2.8-3.4 7.5-6.3 7.5-1.2 0-2.1-.4-2.6-1.2-1-1.4-.9-5.3-.8-6.3.2-3.2 6.3-22.2 7.3-25.2-2 2.2-4.1 4.4-6.4 6.6-5.4 5.1-14.1 11.8-21.5 11.8-3.4 0-5.6-.9-7.7-2.4l7.6 79.6c2 5 39.2 17.1 88.2 17.1 49.1 0 86.3-12.2 88.2-17.1l10.9-94.6c-5.7 5.2-12.3 11.6-19.6 14.8-5.4 2.3-17.4 3.8-17.4-5.7 0-5.2 9.1-14.8 14.4-21.5 1.4-1.7 4.7-5.9 4.7-8.1 0-2.9-6-2.2-11.7 2.5-3.2 2.7-6.2 6.3-8.7 9.7-4.3 6-6.6 11.2-8.5 15.5-6.2 14.2-4.1 8.6-9.1 22-5 13.3-4.2 11.8-5.2 14-.9 1.9-2.2 3.5-4 4.5-1.9 1-4.5.9-6.1-.3-.9-.6-1.3-1.9-1.3-3.7 0-.9.1-1.8.3-2.7 1.5-6.1 7.8-18.1 15-34.3 1.6-3.7 1-2.6.8-2.3-6.2 6-10.9 8.9-14.4 10.5-5.8 2.6-13 2.6-14.5-4.1-.1-.4-.1-.8-.2-1.2-11.8 9.2-24.3 11.7-20-8.1-4.6 8.2-12.6 14.9-22.4 14.9-4.1 0-7.1-1.4-8.6-5.1-2.3-5.5 1.3-14.9 4.6-23.8 1.7-4.5 4-9.9 7.1-16.2 1.6-3.4 4.2-5.4 7.6-4.5.6.2 1.1.4 1.6.7 2.6 1.8 1.6 4.5.3 7.2-3.8 7.5-7.1 13-9.3 20.8-.9 3.3-2 9 1.5 9 2.4 0 4.7-.8 6.9-2.4 4.6-3.4 8.3-8.5 11.1-13.5 2-3.6 4.4-8.3 5.6-12.3.5-1.7 1.1-3.3 1.8-4.8 1.1-2.5 2.6-5.1 5.2-5.1 1.3 0 2.4.5 3.2 1.5 1.7 2.2 1.3 4.5.4 6.9-2 5.6-4.7 10.6-6.9 16.7-1.3 3.5-2.7 8-2.7 11.7 0 3.4 3.7 2.6 6.8 1.2 2.4-1.1 4.8-2.8 6.8-4.5 1.2-4.9.9-3.8 26.4-68.2 1.3-3.3 3.7-4.7 6.1-4.7 1.2 0 2.2.4 3.2 1.1 1.7 1.3 1.7 4.1 1 6.2-.7 1.9-.6 1.3-4.5 10.5-5.2 12.1-8.6 20.8-13.2 31.9-1.9 4.6-7.7 18.9-8.7 22.3-.6 2.2-1.3 5.8 1 5.8 5.4 0 19.3-13.1 23.1-17 .2-.3.5-.4.9-.6.6-1.9 1.2-3.7 1.7-5.5 1.4-3.8 2.7-8.2 5.3-11.3.8-1 1.7-1.6 2.7-1.6 2.8 0 4.2 1.2 4.2 4 0 1.1-.7 5.1-1.1 6.2 1.4-1.5 2.9-3 4.5-4.5 15-13.9 25.7-6.8 25.7.2 0 7.4-8.9 17.7-13.8 23.4-1.6 1.9-4.9 5.4-5 6.4 0 1.3.9 1.8 2.2 1.8 2 0 6.4-3.5 8-4.7 5-3.9 11.8-9.9 16.6-14.1l14.8-136.8c-30.5 17.1-197.6 17.2-228.3.2zm229.7-8.5c0 21-231.2 21-231.2 0 0-8.8 51.8-15.9 115.6-15.9 9 0 17.8.1 26.3.4l12.6-48.7L228.1.6c1.4-1.4 5.8-.2 9.9 3.5s6.6 7.9 5.3 9.3l-.1.1L185.9 74l-10 40.7c39.9 2.6 67.6 8.1 67.6 14.6zm-69.4 4.6c0-.8-.9-1.5-2.5-2.1l-.2.8c0 1.3-5 2.4-11.1 2.4s-11.1-1.1-11.1-2.4c0-.1 0-.2.1-.3l.2-.7c-1.8.6-3 1.4-3 2.3 0 2.1 6.2 3.7 13.7 3.7 7.7.1 13.9-1.6 13.9-3.7z"],"hacker-news":[448,512,[],"f1d4","M0 32v448h448V32H0zm21.2 197.2H21c.1-.1.2-.3.3-.4 0 .1 0 .3-.1.4zm218 53.9V384h-31.4V281.3L128 128h37.3c52.5 98.3 49.2 101.2 59.3 125.6 12.3-27 5.8-24.4 60.6-125.6H320l-80.8 155.1z"],"hacker-news-square":[448,512,[],"f3af","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM21.2 229.2H21c.1-.1.2-.3.3-.4 0 .1 0 .3-.1.4zm218 53.9V384h-31.4V281.3L128 128h37.3c52.5 98.3 49.2 101.2 59.3 125.6 12.3-27 5.8-24.4 60.6-125.6H320l-80.8 155.1z"],"hire-a-helper":[512,512,[],"f3b0","M443.1 0H71.9C67.9 37.3 37.4 67.8 0 71.7v371.5c37.4 4.9 66 32.4 71.9 68.8h372.2c3-36.4 32.5-65.8 67.9-69.8V71.7c-36.4-5.9-65-35.3-68.9-71.7zm-37 404.9c-36.3 0-18.8-2-55.1-2-35.8 0-21 2-56.1 2-5.9 0-4.9-8.2 0-9.8 22.8-7.6 22.9-10.2 24.6-12.8 10.4-15.6 5.9-83 5.9-113 0-5.3-6.4-12.8-13.8-12.8H200.4c-7.4 0-13.8 7.5-13.8 12.8 0 30-4.5 97.4 5.9 113 1.7 2.5 1.8 5.2 24.6 12.8 4.9 1.6 6 9.8 0 9.8-35.1 0-20.3-2-56.1-2-36.3 0-18.8 2-55.1 2-7.9 0-5.8-10.8 0-10.8 10.2-3.4 13.5-3.5 21.7-13.8 7.7-12.9 7.9-44.4 7.9-127.8V151.3c0-22.2-12.2-28.3-28.6-32.4-8.8-2.2-4-11.8 1-11.8 36.5 0 20.6 2 57.1 2 32.7 0 16.5-2 49.2-2 3.3 0 8.5 8.3 1 10.8-4.9 1.6-27.6 3.7-27.6 39.3 0 45.6-.2 55.8 1 68.8 0 1.3 2.3 12.8 12.8 12.8h109.2c10.5 0 12.8-11.5 12.8-12.8 1.2-13 1-23.2 1-68.8 0-35.6-22.7-37.7-27.6-39.3-7.5-2.5-2.3-10.8 1-10.8 32.7 0 16.5 2 49.2 2 36.5 0 20.6-2 57.1-2 4.9 0 9.9 9.6 1 11.8-16.4 4.1-28.6 10.3-28.6 32.4v101.2c0 83.4.1 114.9 7.9 127.8 8.2 10.2 11.4 10.4 21.7 13.8 5.8 0 7.8 10.8 0 10.8z"],hooli:[640,512,[],"f427","M508.4 352h57.9V156.7L508.4 184v168zm73.7-110.5V352H640V241.5h-57.9zm-250.7-8.9c-18.2-18.2-50.4-17.1-50.4-17.1s-32.2-1.1-50.4 17.1c-1.9 1.9-3.7 3.9-5.3 6-38.2-29.6-72.5-46.5-102.1-61.1v-20.7l-22.5 10.6c-54.4-22.1-89-18.2-97.3.1 0 0-24.9 32.8 61.9 110.9v-31c-48.8-54.6-39-76.1-35.3-79.2 13.5-11.4 37.5-8 64.4 2.1L65.2 184v63.3c13.1 14.7 30.5 31.5 53.5 50.4l4.5 3.6v-29.8c0-6.9 1.7-18.2 10.8-18.2s10.6 6.9 10.6 15V317c18 12.2 37.3 22.1 57.7 29.6v-93.9c0-18.7-13.4-37.4-40.6-37.4-15.8-.1-30.5 8.2-38.5 21.9v-54.3c41.9 20.9 83.9 46.5 99.9 58.3-10.2 14.6-9.3 28.1-9.3 43.7 0 18.7-1.4 34.3 16.8 52.5 18.2 18.2 50.4 17.1 50.4 17.1s32.3 1.1 50.4-17.1c18.2-18.2 16.7-33.8 16.7-52.5 0-18.5 1.5-34.2-16.7-52.3zm-39.7 71.9c0 3.6-1.8 12.5-10.7 12.5-8.9 0-10.7-8.9-10.7-12.5v-40.4c0-8.7 7.3-10.9 10.7-10.9 3.4 0 10.7 2.1 10.7 10.9v40.4zm185.7-71.9c-18.2-18.2-50.4-17.1-50.4-17.1s-32.3-1.1-50.4 17.1c-18.2 18.2-16.8 33.9-16.8 52.6 0 18.7-1.4 34.3 16.8 52.5 18.2 18.2 50.4 17.1 50.4 17.1s32.3 1.1 50.4-17.1c18.2-18.2 16.8-33.8 16.8-52.5-.1-18.8 1.3-34.5-16.8-52.6zm-39.8 71.9c0 3.6-1.8 12.5-10.7 12.5-8.9 0-10.7-8.9-10.7-12.5v-40.4c0-8.7 7.3-10.9 10.7-10.9 3.4 0 10.7 2.1 10.7 10.9v40.4zm173.5-73c15.9 0 28.9-12.9 28.9-28.9s-12.9-24.5-28.9-24.5c-15.9 0-28.9 8.6-28.9 24.5s12.9 28.9 28.9 28.9zM144.5 352l38.3.8c-13.2-4.6-26-10.2-38.3-16.8v16zm-21.4 0v-28.6c-6.5-4.2-13-8.7-19.4-13.6-14.8-11.2-27.5-21.7-38.5-31.5V352h57.9zm59.7.8c36.5 12.5 69.9 14.2 94.7 7.2-19.9.2-45.8-2.6-75.3-13.3v5.3l-19.4.8z"],hotjar:[448,512,[],"f3b1","M414.9 161.5C340.2 29 121.1 0 121.1 0S222.2 110.4 93 197.7C11.3 252.8-21 324.4 14 402.6c26.8 59.9 83.5 84.3 144.6 93.4-29.2-55.1-6.6-122.4-4.1-129.6 57.1 86.4 165 0 110.8-93.9 71 15.4 81.6 138.6 27.1 215.5 80.5-25.3 134.1-88.9 148.8-145.6 15.5-59.3 3.7-127.9-26.3-180.9z"],houzz:[320,512,[],"f27c","M12.2 256L160 341.1 12.2 426.6V256M160 512l147.8-85.4V256L160 341.1V512zm0-512L12.2 85.4V256L160 170.6V0zm0 170.6L307.8 256V85.4L160 170.6z"],html5:[384,512,[],"f13b","M0 32l34.9 395.8L191.5 480l157.6-52.2L384 32H0zm308.2 127.9H124.4l4.1 49.4h175.6l-13.6 148.4-97.9 27v.3h-1.1l-98.7-27.3-6-75.8h47.7L138 320l53.5 14.5 53.7-14.5 6-62.2H84.3L71.5 112.2h241.1l-4.4 47.7z"],hubspot:[512,512,[],"f3b2","M267.4 211.6c-25.1 23.7-40.8 57.3-40.8 94.6 0 29.3 9.7 56.3 26 78L203.1 434c-4.4-1.6-9.1-2.5-14-2.5-10.8 0-20.9 4.2-28.5 11.8-7.6 7.6-11.8 17.8-11.8 28.6s4.2 20.9 11.8 28.5c7.6 7.6 17.8 11.6 28.5 11.6 10.8 0 20.9-3.9 28.6-11.6 7.6-7.6 11.8-17.8 11.8-28.5 0-4.2-.6-8.2-1.9-12.1l50-50.2c22 16.9 49.4 26.9 79.3 26.9 71.9 0 130-58.3 130-130.2 0-65.2-47.7-119.2-110.2-128.7V116c17.5-7.4 28.2-23.8 28.2-42.9 0-26.1-20.9-47.9-47-47.9S311.2 47 311.2 73.1c0 19.1 10.7 35.5 28.2 42.9v61.2c-15.2 2.1-29.6 6.7-42.7 13.6-27.6-20.9-117.5-85.7-168.9-124.8 1.2-4.4 2-9 2-13.8C129.8 23.4 106.3 0 77.4 0 48.6 0 25.2 23.4 25.2 52.2c0 28.9 23.4 52.3 52.2 52.3 9.8 0 18.9-2.9 26.8-7.6l163.2 114.7zm89.5 163.6c-38.1 0-69-30.9-69-69s30.9-69 69-69 69 30.9 69 69-30.9 69-69 69z"],imdb:[448,512,[],"f2d8","M350.5 288.7c0 5.4 1.6 14.4-6.2 14.4-1.6 0-3-.8-3.8-2.4-2.2-5.1-1.1-44.1-1.1-44.7 0-3.8-1.1-12.7 4.9-12.7 7.3 0 6.2 7.3 6.2 12.7v32.7zM265 229.9c0-9.7 1.6-16-10.3-16v83.7c12.2.3 10.3-8.7 10.3-18.4v-49.3zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zM21.3 228.8c-.1.1-.2.3-.3.4h.3v-.4zM97 192H64v127.8h33V192zm113.3 0h-43.1l-7.6 59.9c-2.7-20-5.4-40.1-8.7-59.9h-42.8v127.8h29v-84.5l12.2 84.5h20.6l11.6-86.4v86.4h28.7V192zm86.3 45.3c0-8.1.3-16.8-1.4-24.4-4.3-22.5-31.4-20.9-49-20.9h-24.6v127.8c86.1.1 75 6 75-82.5zm85.9 17.3c0-17.3-.8-30.1-22.2-30.1-8.9 0-14.9 2.7-20.9 9.2V192h-31.7v127.8h29.8l1.9-8.1c5.7 6.8 11.9 9.8 20.9 9.8 19.8 0 22.2-15.2 22.2-30.9v-36z"],instagram:[448,512,[],"f16d","M224.1 141c-63.6 0-114.9 51.3-114.9 114.9s51.3 114.9 114.9 114.9S339 319.5 339 255.9 287.7 141 224.1 141zm0 189.6c-41.1 0-74.7-33.5-74.7-74.7s33.5-74.7 74.7-74.7 74.7 33.5 74.7 74.7-33.6 74.7-74.7 74.7zm146.4-194.3c0 14.9-12 26.8-26.8 26.8-14.9 0-26.8-12-26.8-26.8s12-26.8 26.8-26.8 26.8 12 26.8 26.8zm76.1 27.2c-1.7-35.9-9.9-67.7-36.2-93.9-26.2-26.2-58-34.4-93.9-36.2-37-2.1-147.9-2.1-184.9 0-35.8 1.7-67.6 9.9-93.9 36.1s-34.4 58-36.2 93.9c-2.1 37-2.1 147.9 0 184.9 1.7 35.9 9.9 67.7 36.2 93.9s58 34.4 93.9 36.2c37 2.1 147.9 2.1 184.9 0 35.9-1.7 67.7-9.9 93.9-36.2 26.2-26.2 34.4-58 36.2-93.9 2.1-37 2.1-147.8 0-184.8zM398.8 388c-7.8 19.6-22.9 34.7-42.6 42.6-29.5 11.7-99.5 9-132.1 9s-102.7 2.6-132.1-9c-19.6-7.8-34.7-22.9-42.6-42.6-11.7-29.5-9-99.5-9-132.1s-2.6-102.7 9-132.1c7.8-19.6 22.9-34.7 42.6-42.6 29.5-11.7 99.5-9 132.1-9s102.7-2.6 132.1 9c19.6 7.8 34.7 22.9 42.6 42.6 11.7 29.5 9 99.5 9 132.1s2.7 102.7-9 132.1z"],"internet-explorer":[512,512,[],"f26b","M483.049 159.706c10.855-24.575 21.424-60.438 21.424-87.871 0-72.722-79.641-98.371-209.673-38.577-107.632-7.181-211.221 73.67-237.098 186.457 30.852-34.862 78.271-82.298 121.977-101.158C125.404 166.85 79.128 228.002 43.992 291.725 23.246 329.651 0 390.94 0 436.747c0 98.575 92.854 86.5 180.251 42.006 31.423 15.43 66.559 15.573 101.695 15.573 97.124 0 184.249-54.294 216.814-146.022H377.927c-52.509 88.593-196.819 52.996-196.819-47.436H509.9c6.407-43.581-1.655-95.715-26.851-141.162zM64.559 346.877c17.711 51.15 53.703 95.871 100.266 123.304-88.741 48.94-173.267 29.096-100.266-123.304zm115.977-108.873c2-55.151 50.276-94.871 103.98-94.871 53.418 0 101.981 39.72 103.981 94.871H180.536zm184.536-187.6c21.425-10.287 48.563-22.003 72.558-22.003 31.422 0 54.274 21.717 54.274 53.722 0 20.003-7.427 49.007-14.569 67.867-26.28-42.292-65.986-81.584-112.263-99.586z"],ioxhost:[640,512,[],"f208","M616 160h-67.3C511.2 70.7 422.9 8 320 8 183 8 72 119 72 256c0 16.4 1.6 32.5 4.7 48H24c-13.3 0-24 10.8-24 24 0 13.3 10.7 24 24 24h67.3c37.5 89.3 125.8 152 228.7 152 137 0 248-111 248-248 0-16.4-1.6-32.5-4.7-48H616c13.3 0 24-10.8 24-24 0-13.3-10.7-24-24-24zm-96 96c0 110.5-89.5 200-200 200-75.7 0-141.6-42-175.5-104H424c13.3 0 24-10.8 24-24 0-13.3-10.7-24-24-24H125.8c-3.8-15.4-5.8-31.4-5.8-48 0-110.5 89.5-200 200-200 75.7 0 141.6 42 175.5 104H216c-13.3 0-24 10.8-24 24 0 13.3 10.7 24 24 24h298.2c3.8 15.4 5.8 31.4 5.8 48zm-304-24h208c13.3 0 24 10.7 24 24 0 13.2-10.7 24-24 24H216c-13.3 0-24-10.7-24-24 0-13.2 10.7-24 24-24z"],itunes:[448,512,[],"f3b4","M223.6 80.3C129 80.3 52.5 157 52.5 251.5S129 422.8 223.6 422.8s171.2-76.7 171.2-171.2c0-94.6-76.7-171.3-171.2-171.3zm79.4 240c-3.2 13.6-13.5 21.2-27.3 23.8-12.1 2.2-22.2 2.8-31.9-5-11.8-10-12-26.4-1.4-36.8 8.4-8 20.3-9.6 38-12.8 3-.5 5.6-1.2 7.7-3.7 3.2-3.6 2.2-2 2.2-80.8 0-5.6-2.7-7.1-8.4-6.1-4 .7-91.9 17.1-91.9 17.1-5 1.1-6.7 2.6-6.7 8.3 0 116.1.5 110.8-1.2 118.5-2.1 9-7.6 15.8-14.9 19.6-8.3 4.6-23.4 6.6-31.4 5.2-21.4-4-28.9-28.7-14.4-42.9 8.4-8 20.3-9.6 38-12.8 3-.5 5.6-1.2 7.7-3.7 5-5.7.9-127 2.6-133.7.4-2.6 1.5-4.8 3.5-6.4 2.1-1.7 5.8-2.7 6.7-2.7 101-19 113.3-21.4 115.1-21.4 5.7-.4 9 3 9 8.7-.1 170.6.4 161.4-1 167.6zM345.2 32H102.8C45.9 32 0 77.9 0 134.8v242.4C0 434.1 45.9 480 102.8 480h242.4c57 0 102.8-45.9 102.8-102.8V134.8C448 77.9 402.1 32 345.2 32zM223.6 444c-106.3 0-192.5-86.2-192.5-192.5S117.3 59 223.6 59s192.5 86.2 192.5 192.5S329.9 444 223.6 444z"],"itunes-note":[384,512,[],"f3b5","M381.9 388.2c-6.4 27.4-27.2 42.8-55.1 48-24.5 4.5-44.9 5.6-64.5-10.2-23.9-20.1-24.2-53.4-2.7-74.4 17-16.2 40.9-19.5 76.8-25.8 6-1.1 11.2-2.5 15.6-7.4 6.4-7.2 4.4-4.1 4.4-163.2 0-11.2-5.5-14.3-17-12.3-8.2 1.4-185.7 34.6-185.7 34.6-10.2 2.2-13.4 5.2-13.4 16.7 0 234.7 1.1 223.9-2.5 239.5-4.2 18.2-15.4 31.9-30.2 39.5-16.8 9.3-47.2 13.4-63.4 10.4-43.2-8.1-58.4-58-29.1-86.6 17-16.2 40.9-19.5 76.8-25.8 6-1.1 11.2-2.5 15.6-7.4 10.1-11.5 1.8-256.6 5.2-270.2.8-5.2 3-9.6 7.1-12.9 4.2-3.5 11.8-5.5 13.4-5.5 204-38.2 228.9-43.1 232.4-43.1 11.5-.8 18.1 6 18.1 17.6.2 344.5 1.1 326-1.8 338.5z"],jenkins:[512,512,[],"f3b6","M487.1 425c-1.4-11.2-19-23.1-28.2-31.9-5.1-5-29-23.1-30.4-29.9-1.4-6.6 9.7-21.5 13.3-28.9 5.1-10.7 8.8-23.7 11.3-32.6 18.8-66.1 20.7-156.9-6.2-211.2-10.2-20.6-38.6-49-56.4-62.5-42-31.7-119.6-35.3-170.1-16.6-14.1 5.2-27.8 9.8-40.1 17.1-33.1 19.4-68.3 32.5-78.1 71.6-24.2 10.8-31.5 41.8-30.3 77.8.2 7 4.1 15.8 2.7 22.4-.7 3.3-5.2 7.6-6.1 9.8-11.6 27.7-2.3 64 11.1 83.7 8.1 11.9 21.5 22.4 39.2 25.2.7 10.6 3.3 19.7 8.2 30.4 3.1 6.8 14.7 19 10.4 27.7-2.2 4.4-21 13.8-27.3 17.6C89 407.2 73.7 415 54.2 429c-12.6 9-32.3 10.2-29.2 31.1 2.1 14.1 10.1 31.6 14.7 45.8.7 2 1.4 4.1 2.1 6h422c4.9-15.3 9.7-30.9 14.6-47.2 3.4-11.4 10.2-27.8 8.7-39.7zM205.9 33.7c1.8-.5 3.4.7 4.9 2.4-.2 5.2-5.4 5.1-8.9 6.8-5.4 6.7-13.4 9.8-20 17.2-6.8 7.5-14.4 27.7-23.4 30-4.5 1.1-9.7-.8-13.6-.5-10.4.7-17.7 6-28.3 7.5 13.6-29.9 56.1-54 89.3-63.4zm-104.8 93.6c13.5-14.9 32.1-24.1 54.8-25.9 11.7 29.7-8.4 65-.9 97.6 2.3 9.9 10.2 25.4-2.4 25.7.3-28.3-34.8-46.3-61.3-29.6-1.8-21.5-4.9-51.7 9.8-67.8zm36.7 200.2c-1-4.1-2.7-12.9-2.3-15.1 1.6-8.7 17.1-12.5 11-24.7-11.3-.1-13.8 10.2-24.1 11.3-26.7 2.6-45.6-35.4-44.4-58.4 1-19.5 17.6-38.2 40.1-35.8 16 1.8 21.4 19.2 24.5 34.7 9.2.5 22.5-.4 26.9-7.6-.6-17.5-8.8-31.6-8.2-47.7 1-30.3 17.5-57.6 4.8-87.4 13.6-30.9 53.5-55.3 83.1-70 36.6-18.3 94.9-3.7 129.3 15.8 19.7 11.1 34.4 32.7 48.3 50.7-19.5-5.8-36.1 4.2-33.1 20.3 16.3-14.9 44.2-.2 52.5 16.4 7.9 15.8 7.8 39.3 9 62.8 2.9 57-10.4 115.9-39.1 157.1-7.7 11-14.1 23-24.9 30.6-26 18.2-65.4 34.7-99.2 23.4-44.7-15-65-44.8-89.5-78.8.7 18.7 13.8 34.1 26.8 48.4 11.3 12.5 25 26.6 39.7 32.4-12.3-2.9-31.1-3.8-36.2 7.2-28.6-1.9-55.1-4.8-68.7-24.2-10.6-15.4-21.4-41.4-26.3-61.4zm222 124.1c4.1-3 11.1-2.9 17.4-3.6-5.4-2.7-13-3.7-19.3-2.2-.1-4.2-2-6.8-3.2-10.2 10.6-3.8 35.5-28.5 49.6-20.3 6.7 3.9 9.5 26.2 10.1 37 .4 9-.8 18-4.5 22.8-18.8-.6-35.8-2.8-50.7-7 .9-6.1-1-12.1.6-16.5zm-17.2-20c-16.8.8-26-1.2-38.3-10.8.2-.8 1.4-.5 1.5-1.4 18 8 40.8-3.3 59-4.9-7.9 5.1-14.6 11.6-22.2 17.1zm-12.1 33.2c-1.6-9.4-3.5-12-2.8-20.2 25-16.6 29.7 28.6 2.8 20.2zM226 438.6c-11.6-.7-48.1-14-38.5-23.7 9.4 6.5 27.5 4.9 41.3 7.3.8 4.4-2.8 10.2-2.8 16.4zM57.7 497.1c-4.3-12.7-9.2-25.1-14.8-36.9 30.8-23.8 65.3-48.9 102.2-63.5 2.8-1.1 23.2 25.4 26.2 27.6 16.5 11.7 37 21 56.2 30.2 1.2 8.8 3.9 20.2 8.7 35.5.7 2.3 1.4 4.7 2.2 7.2H57.7zm240.6 5.7h-.8c.3-.2.5-.4.8-.5v.5zm7.5-5.7c2.1-1.4 4.3-2.8 6.4-4.3 1.1 1.4 2.2 2.8 3.2 4.3h-9.6zm15.1-24.7c-10.8 7.3-20.6 18.3-33.3 25.2-6 3.3-27 11.7-33.4 10.2-3.6-.8-3.9-5.3-5.4-9.5-3.1-9-10.1-23.4-10.8-37-.8-17.2-2.5-46 16-42.4 14.9 2.9 32.3 9.7 43.9 16.1 7.1 3.9 11.1 8.6 21.9 9.5-.1 1.4-.1 2.8-.2 4.3-5.9 3.9-15.3 3.8-21.8 7.1 9.5.4 17 2.7 23.5 5.9-.1 3.4-.3 7-.4 10.6zm53.4 24.7h-14c-.1-3.2-2.8-5.8-6.1-5.8s-5.9 2.6-6.1 5.8h-17.4c-2.8-4.4-5.7-8.6-8.9-12.5 2.1-2.2 4-4.7 6-6.9 9 3.7 14.8-4.9 21.7-4.2 7.9.8 14.2 11.7 25.4 11l-.6 12.6zm8.7 0c.2-4 .4-7.8.6-11.5 15.6-7.3 29 1.3 35.7 11.5H383zm83.4-37c-2.3 11.2-5.8 24-9.9 37.1-.2-.1-.4-.1-.6-.1H428c.6-1.1 1.2-2.2 1.9-3.3-2.6-6.1-9-8.7-10.9-15.5 12.1-22.7 6.5-93.4-24.2-78.5 4.3-6.3 15.6-11.5 20.8-19.3 13 10.4 20.8 20.3 33.2 31.4 6.8 6 20 13.3 21.4 23.1.8 5.5-2.6 18.9-3.8 25.1zM222.2 130.5c5.4-14.9 27.2-34.7 45-32 7.7 1.2 18 8.2 12.2 17.7-30.2-7-45.2 12.6-54.4 33.1-8.1-2-4.9-13.1-2.8-18.8zm184.1 63.1c8.2-3.6 22.4-.7 29.6-5.3-4.2-11.5-10.3-21.4-9.3-37.7.5 0 1 0 1.4.1 6.8 14.2 12.7 29.2 21.4 41.7-5.7 13.5-43.6 25.4-43.1 1.2zm20.4-43zm-117.2 45.7c-6.8-10.9-19-32.5-14.5-45.3 6.5 11.9 8.6 24.4 17.8 33.3 4.1 4 12.2 9 8.2 20.2-.9 2.7-7.8 8.6-11.7 9.7-14.4 4.3-47.9.9-36.6-17.1 11.9.7 27.9 7.8 36.8-.8zm27.3 70c3.8 6.6 1.4 18.7 12.1 20.6 20.2 3.4 43.6-12.3 58.1-17.8 9-15.2-.8-20.7-8.9-30.5-16.6-20-38.8-44.8-38-74.7 6.7-4.9 7.3 7.4 8.2 9.7 8.7 20.3 30.4 46.2 46.3 63.5 3.9 4.3 10.3 8.4 11 11.2 2.1 8.2-5.4 18-4.5 23.5-21.7 13.9-45.8 29.1-81.4 25.6-7.4-6.7-10.3-21.4-2.9-31.1zm-201.3-9.2c-6.8-3.9-8.4-21-16.4-21.4-11.4-.7-9.3 22.2-9.3 35.5-7.8-7.1-9.2-29.1-3.5-40.3-6.6-3.2-9.5 3.6-13.1 5.9 4.7-34.1 49.8-15.8 42.3 20.3zm299.6 28.8c-10.1 19.2-24.4 40.4-54 41-.6-6.2-1.1-15.6 0-19.4 22.7-2.2 36.6-13.7 54-21.6zm-141.9 12.4c18.9 9.9 53.6 11 79.3 10.2 1.4 5.6 1.3 12.6 1.4 19.4-33 1.8-72-6.4-80.7-29.6zm92.2 46.7c-1.7 4.3-5.3 9.3-9.8 11.1-12.1 4.9-45.6 8.7-62.4-.3-10.7-5.7-17.5-18.5-23.4-26-2.8-3.6-16.9-12.9-.2-12.9 13.1 32.7 58 29 95.8 28.1z"],joget:[496,512,[],"f3b7","M227.5 468.7c-9-13.6-19.9-33.3-23.7-42.4-5.7-13.7-27.2-45.6 31.2-67.1 51.7-19.1 176.7-16.5 208.8-17.6-4 9-8.6 17.9-13.9 26.6-40.4 65.5-110.4 101.5-182 101.5-6.8 0-13.6-.4-20.4-1M66.1 143.9C128 43.4 259.6 12.2 360.1 74.1c74.8 46.1 111.2 130.9 99.3 212.7-24.9-.5-179.3-3.6-230.3-4.9-55.5-1.4-81.7-20.8-58.5-48.2 23.2-27.4 51.1-40.7 68.9-51.2 17.9-10.5 27.3-33.7-23.6-29.7C87.3 161.5 48.6 252.1 37.6 293c-8.8-49.7-.1-102.7 28.5-149.1m-29.2-18c-71.9 116.6-35.6 269.3 81 341.2 116.6 71.9 269.3 35.6 341.2-80.9 71.9-116.6 35.6-269.4-81-341.2-40.5-25.1-85.5-37-129.9-37C165 8 83.8 49.9 36.9 125.9m244.4 110.4c-31.5 20.5-65.3 31.3-65.3 31.3l169.5-1.6 46.5-23.4s3.6-9.5-19.1-15.5c-22.7-6-57 11.3-86.7 27.2-29.7 15.8-31.1 8.2-31.1 8.2s40.2-28.1 50.7-34.5c10.5-6.4 31.9-14 13.4-24.6-3.2-1.8-6.7-2.7-10.4-2.7-17.8 0-41.5 18.7-67.5 35.6"],joomla:[448,512,[],"f1aa","M.6 92.1C.6 58.8 27.4 32 60.4 32c30 0 54.5 21.9 59.2 50.2 32.6-7.6 67.1.6 96.5 30l-44.3 44.3c-20.5-20.5-42.6-16.3-55.4-3.5-14.3 14.3-14.3 37.9 0 52.2l99.5 99.5-44 44.3c-87.7-87.2-49.7-49.7-99.8-99.7-26.8-26.5-35-64.8-24.8-98.9C20.4 144.6.6 120.7.6 92.1zm129.5 116.4l44.3 44.3c10-10 89.7-89.7 99.7-99.8 14.3-14.3 37.6-14.3 51.9 0 12.8 12.8 17 35-3.5 55.4l44 44.3c31.2-31.2 38.5-67.6 28.9-101.2 29.2-4.1 51.9-29.2 51.9-59.5 0-33.2-26.8-60.1-59.8-60.1-30.3 0-55.4 22.5-59.5 51.6-33.8-9.9-71.7-1.5-98.3 25.1-18.3 19.1-71.1 71.5-99.6 99.9zm266.3 152.2c8.2-32.7-.9-68.5-26.3-93.9-11.8-12.2 5 4.7-99.5-99.7l-44.3 44.3 99.7 99.7c14.3 14.3 14.3 37.6 0 51.9-12.8 12.8-35 17-55.4-3.5l-44 44.3c27.6 30.2 68 38.8 102.7 28 5.5 27.4 29.7 48.1 58.9 48.1 33 0 59.8-26.8 59.8-60.1 0-30.2-22.5-55-51.6-59.1zm-84.3-53.1l-44-44.3c-87 86.4-50.4 50.4-99.7 99.8-14.3 14.3-37.6 14.3-51.9 0-13.1-13.4-16.9-35.3 3.2-55.4l-44-44.3c-30.2 30.2-38 65.2-29.5 98.3-26.7 6-46.2 29.9-46.2 58.2C0 453.2 26.8 480 59.8 480c28.6 0 52.5-19.8 58.6-46.7 32.7 8.2 68.5-.6 94.2-26 32.1-32 12.2-12.4 99.5-99.7z"],js:[448,512,[],"f3b8","M0 32v448h448V32H0zm243.8 349.4c0 43.6-25.6 63.5-62.9 63.5-33.7 0-53.2-17.4-63.2-38.5l34.3-20.7c6.6 11.7 12.6 21.6 27.1 21.6 13.8 0 22.6-5.4 22.6-26.5V237.7h42.1v143.7zm99.6 63.5c-39.1 0-64.4-18.6-76.7-43l34.3-19.8c9 14.7 20.8 25.6 41.5 25.6 17.4 0 28.6-8.7 28.6-20.8 0-14.4-11.4-19.5-30.7-28l-10.5-4.5c-30.4-12.9-50.5-29.2-50.5-63.5 0-31.6 24.1-55.6 61.6-55.6 26.8 0 46 9.3 59.8 33.7L368 290c-7.2-12.9-15-18-27.1-18-12.3 0-20.1 7.8-20.1 18 0 12.6 7.8 17.7 25.9 25.6l10.5 4.5c35.8 15.3 55.9 31 55.9 66.2 0 37.8-29.8 58.6-69.7 58.6z"],"js-square":[512,512,[],"f3b9","M432 32H80c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM275.8 381.4c0 43.6-25.6 63.5-62.9 63.5-33.7 0-53.2-17.4-63.2-38.5l34.3-20.7c6.6 11.7 12.6 21.6 27.1 21.6 13.8 0 22.6-5.4 22.6-26.5V237.7h42.1v143.7zm99.6 63.5c-39.1 0-64.4-18.6-76.7-43l34.3-19.8c9 14.7 20.8 25.6 41.5 25.6 17.4 0 28.6-8.7 28.6-20.8 0-14.4-11.4-19.5-30.7-28l-10.5-4.5c-30.4-12.9-50.5-29.2-50.5-63.5 0-31.6 24.1-55.6 61.6-55.6 26.8 0 46 9.3 59.8 33.7L400 290c-7.2-12.9-15-18-27.1-18-12.3 0-20.1 7.8-20.1 18 0 12.6 7.8 17.7 25.9 25.6l10.5 4.5c35.8 15.3 55.9 31 55.9 66.2 0 37.8-29.8 58.6-69.7 58.6z"],jsfiddle:[576,512,[],"f1cc","M510.634 237.462c-4.727-2.621-5.664-5.748-6.381-10.776-2.352-16.488-3.539-33.619-9.097-49.095-35.895-99.957-153.99-143.386-246.849-91.646-27.37 15.25-48.971 36.369-65.493 63.903-3.184-1.508-5.458-2.71-7.824-3.686-30.102-12.421-59.049-10.121-85.331 9.167-25.531 18.737-36.422 44.548-32.676 76.408.355 3.025-1.967 7.621-4.514 9.545-39.712 29.992-56.031 78.065-41.902 124.615 13.831 45.569 57.514 79.796 105.608 81.433 30.291 1.031 60.637.546 90.959.539 84.041-.021 168.09.531 252.12-.48 52.664-.634 96.108-36.873 108.212-87.293 11.54-48.074-11.144-97.3-56.832-122.634zm21.107 156.88c-18.23 22.432-42.343 35.253-71.28 35.65-56.874.781-113.767.23-170.652.23 0 .7-163.028.159-163.728.154-43.861-.332-76.739-19.766-95.175-59.995-18.902-41.245-4.004-90.848 34.186-116.106 9.182-6.073 12.505-11.566 10.096-23.136-5.49-26.361 4.453-47.956 26.42-62.981 22.987-15.723 47.422-16.146 72.034-3.083 10.269 5.45 14.607 11.564 22.198-2.527 14.222-26.399 34.557-46.727 60.671-61.294 97.46-54.366 228.37 7.568 230.24 132.697.122 8.15 2.412 12.428 9.848 15.894 57.56 26.829 74.456 96.122 35.142 144.497zm-87.789-80.499c-5.848 31.157-34.622 55.096-66.666 55.095-16.953-.001-32.058-6.545-44.079-17.705-27.697-25.713-71.141-74.98-95.937-93.387-20.056-14.888-41.99-12.333-60.272 3.782-49.996 44.071 15.859 121.775 67.063 77.188 4.548-3.96 7.84-9.543 12.744-12.844 8.184-5.509 20.766-.884 13.168 10.622-17.358 26.284-49.33 38.197-78.863 29.301-28.897-8.704-48.84-35.968-48.626-70.179 1.225-22.485 12.364-43.06 35.414-55.965 22.575-12.638 46.369-13.146 66.991 2.474C295.68 280.7 320.467 323.97 352.185 343.47c24.558 15.099 54.254 7.363 68.823-17.506 28.83-49.209-34.592-105.016-78.868-63.46-3.989 3.744-6.917 8.932-11.41 11.72-10.975 6.811-17.333-4.113-12.809-10.353 20.703-28.554 50.464-40.44 83.271-28.214 31.429 11.714 49.108 44.366 42.76 78.186z"],keycdn:[512,512,[],"f3ba","M63.8 409.3l60.5-59c32.1 42.8 71.1 66 126.6 67.4 30.5.7 60.3-7 86.4-22.4 5.1 5.3 18.5 19.5 20.9 22-32.2 20.7-69.6 31.1-108.1 30.2-43.3-1.1-84.6-16.7-117.7-44.4.3-.6-38.2 37.5-38.6 37.9 9.5 29.8-13.1 62.4-46.3 62.4C20.7 503.3 0 481.7 0 454.9c0-34.3 33.1-56.6 63.8-45.6zm354.9-252.4c19.1 31.3 29.6 67.4 28.7 104-1.1 44.8-19 87.5-48.6 121 .3.3 23.8 25.2 24.1 25.5 9.6-1.3 19.2 2 25.9 9.1 11.3 12 10.9 30.9-1.1 42.4-12 11.3-30.9 10.9-42.4-1.1-6.7-7-9.4-16.8-7.6-26.3-24.9-26.6-44.4-47.2-44.4-47.2 42.7-34.1 63.3-79.6 64.4-124.2.7-28.9-7.2-57.2-21.1-82.2l22.1-21zM104 53.1c6.7 7 9.4 16.8 7.6 26.3l45.9 48.1c-4.7 3.8-13.3 10.4-22.8 21.3-25.4 28.5-39.6 64.8-40.7 102.9-.7 28.9 6.1 57.2 20 82.4l-22 21.5C72.7 324 63.1 287.9 64.2 250.9c1-44.6 18.3-87.6 47.5-121.1l-25.3-26.4c-9.6 1.3-19.2-2-25.9-9.1-11.3-12-10.9-30.9 1.1-42.4C73.5 40.7 92.2 41 104 53.1zM464.9 8c26 0 47.1 22.4 47.1 48.3S490.9 104 464.9 104c-6.3.1-14-1.1-15.9-1.8l-62.9 59.7c-32.7-43.6-76.7-65.9-126.9-67.2-30.5-.7-60.3 6.8-86.2 22.4l-21.1-22C184.1 74.3 221.5 64 260 64.9c43.3 1.1 84.6 16.7 117.7 44.6l41.1-38.6c-1.5-4.7-2.2-9.6-2.2-14.5C416.5 29.7 438.9 8 464.9 8zM256.7 113.4c5.5 0 10.9.4 16.4 1.1 78.1 9.8 133.4 81.1 123.8 159.1-9.8 78.1-81.1 133.4-159.1 123.8-78.1-9.8-133.4-81.1-123.8-159.2 9.3-72.4 70.1-124.6 142.7-124.8zm-59 119.4c.6 22.7 12.2 41.8 32.4 52.2l-11 51.7h73.7l-11-51.7c20.1-10.9 32.1-29 32.4-52.2-.4-32.8-25.8-57.5-58.3-58.3-32.1.8-57.3 24.8-58.2 58.3zM256 160"],kickstarter:[448,512,[],"f3bb","M400 480H48c-26.4 0-48-21.6-48-48V80c0-26.4 21.6-48 48-48h352c26.4 0 48 21.6 48 48v352c0 26.4-21.6 48-48 48zM199.6 178.5c0-30.7-17.6-45.1-39.7-45.1-25.8 0-40 19.8-40 44.5v154.8c0 25.8 13.7 45.6 40.5 45.6 21.5 0 39.2-14 39.2-45.6v-41.8l60.6 75.7c12.3 14.9 39 16.8 55.8 0 14.6-15.1 14.8-36.8 4-50.4l-49.1-62.8 40.5-58.7c9.4-13.5 9.5-34.5-5.6-49.1-16.4-15.9-44.6-17.3-61.4 7l-44.8 64.7v-38.8z"],"kickstarter-k":[384,512,[],"f3bc","M147.3 114.4c0-56.2-32.5-82.4-73.4-82.4C26.2 32 0 68.2 0 113.4v283c0 47.3 25.3 83.4 74.9 83.4 39.8 0 72.4-25.6 72.4-83.4v-76.5l112.1 138.3c22.7 27.2 72.1 30.7 103.2 0 27-27.6 27.3-67.4 7.4-92.2l-90.8-114.8 74.9-107.4c17.4-24.7 17.5-63.1-10.4-89.8-30.3-29-82.4-31.6-113.6 12.8L147.3 185v-70.6z"],laravel:[640,512,[],"f3bd","M637.5 204.7c-4.2-4.8-62.8-78.1-73.1-90.5-10.3-12.4-15.4-10.2-21.7-9.3s-80.5 13.4-89.1 14.8c-8.6 1.5-14 4.9-8.7 12.3 4.7 6.6 53.4 75.7 64.2 90.9l-193.7 46.4L161.2 11.7C155.1 2.6 153.8-.6 139.8.1 125.9.7 19 9.6 11.4 10.2c-7.6.6-16 4-8.4 22s129 279.6 132.4 287.2c3.4 7.6 12.2 20 32.8 15 21.1-5.1 94.3-24.2 134.3-34.7 21.1 38.3 64.2 115.9 72.2 127 10.6 14.9 18 12.4 34.3 7.4 12.8-3.9 199.6-71.1 208-74.5 8.4-3.5 13.6-5.9 7.9-14.4-4.2-6.2-53.5-72.2-79.3-106.8 17.7-4.7 80.6-21.4 87.3-23.3 7.8-1.8 8.9-5.7 4.6-10.4zm-352.2 72c-2.3.5-110.8 26.5-116.6 27.8-5.8 1.3-5.8.7-6.5-1.3-.7-2-129-266.7-130.8-270-1.8-3.3-1.7-5.9 0-5.9s102.5-9 106-9.2c3.6-.2 3.2.6 4.5 2.8 0 0 142.2 245.4 144.6 249.7 2.6 4.3 1.1 5.6-1.2 6.1zm306 57.3c1.7 2.7 3.5 4.5-2 6.4-5.4 2-183.7 62.1-187.1 63.6-3.5 1.5-6.2 2-10.6-4.5-4.5-6.4-62.4-106.8-62.4-106.8l188.8-49c4.7-1.5 6.2-2.5 9.2 2.2 2.9 4.7 62.4 85.4 64.1 88.1zm12.1-134.1c-4.2.9-73.6 18.1-73.6 18.1l-56.7-77.8c-1.6-2.2-2.9-4.5 1.1-5s68.4-12.2 71.3-12.8c2.9-.7 5.4-1.5 9 3.4 3.6 4.9 52.6 67 54.5 69.4 1.8 2.3-1.4 3.8-5.6 4.7z"],lastfm:[512,512,[],"f202","M225.8 367.1l-18.8-51s-30.5 34-76.2 34c-40.5 0-69.2-35.2-69.2-91.5 0-72.1 36.4-97.9 72.1-97.9 66.5 0 74.8 53.3 100.9 134.9 18.8 56.9 54 102.6 155.4 102.6 72.7 0 122-22.3 122-80.9 0-72.9-62.7-80.6-115-92.1-25.8-5.9-33.4-16.4-33.4-34 0-19.9 15.8-31.7 41.6-31.7 28.2 0 43.4 10.6 45.7 35.8l58.6-7c-4.7-52.8-41.1-74.5-100.9-74.5-52.8 0-104.4 19.9-104.4 83.9 0 39.9 19.4 65.1 68 76.8 44.9 10.6 79.8 13.8 79.8 45.7 0 21.7-21.1 30.5-61 30.5-59.2 0-83.9-31.1-97.9-73.9-32-96.8-43.6-163-161.3-163C45.7 113.8 0 168.3 0 261c0 89.1 45.7 137.2 127.9 137.2 66.2 0 97.9-31.1 97.9-31.1z"],"lastfm-square":[448,512,[],"f203","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-92.2 312.9c-63.4 0-85.4-28.6-97.1-64.1-16.3-51-21.5-84.3-63-84.3-22.4 0-45.1 16.1-45.1 61.2 0 35.2 18 57.2 43.3 57.2 28.6 0 47.6-21.3 47.6-21.3l11.7 31.9s-19.8 19.4-61.2 19.4c-51.3 0-79.9-30.1-79.9-85.8 0-57.9 28.6-92 82.5-92 73.5 0 80.8 41.4 100.8 101.9 8.8 26.8 24.2 46.2 61.2 46.2 24.9 0 38.1-5.5 38.1-19.1 0-19.9-21.8-22-49.9-28.6-30.4-7.3-42.5-23.1-42.5-48 0-40 32.3-52.4 65.2-52.4 37.4 0 60.1 13.6 63 46.6l-36.7 4.4c-1.5-15.8-11-22.4-28.6-22.4-16.1 0-26 7.3-26 19.8 0 11 4.8 17.6 20.9 21.3 32.7 7.1 71.8 12 71.8 57.5.1 36.7-30.7 50.6-76.1 50.6z"],leanpub:[576,512,[],"f212","M386.539 111.485l15.096 248.955-10.979-.275c-36.232-.824-71.64 8.783-102.657 27.997-31.016-19.214-66.424-27.997-102.657-27.997-45.564 0-82.07 10.705-123.516 27.723L93.117 129.6c28.546-11.803 61.484-18.115 92.226-18.115 41.173 0 73.836 13.175 102.657 42.544 27.723-28.271 59.013-41.721 98.539-42.544zM569.07 448c-25.526 0-47.485-5.215-70.542-15.645-34.31-15.645-69.993-24.978-107.871-24.978-38.977 0-74.934 12.901-102.657 40.623-27.723-27.723-63.68-40.623-102.657-40.623-37.878 0-73.561 9.333-107.871 24.978C55.239 442.236 32.731 448 8.303 448H6.93L49.475 98.859C88.726 76.626 136.486 64 181.775 64 218.83 64 256.984 71.685 288 93.095 319.016 71.685 357.17 64 394.225 64c45.289 0 93.049 12.626 132.3 34.859L569.07 448zm-43.368-44.741l-34.036-280.246c-30.742-13.999-67.248-21.41-101.009-21.41-38.428 0-74.385 12.077-102.657 38.702-28.272-26.625-64.228-38.702-102.657-38.702-33.761 0-70.267 7.411-101.009 21.41L50.298 403.259c47.211-19.487 82.894-33.486 135.045-33.486 37.604 0 70.817 9.606 102.657 29.644 31.84-20.038 65.052-29.644 102.657-29.644 52.151 0 87.834 13.999 135.045 33.486z"],less:[640,512,[],"f41d","M612.7 219c0-20.5 3.2-32.6 3.2-54.6 0-34.2-12.6-45.2-40.5-45.2h-20.5v24.2h6.3c14.2 0 17.3 4.7 17.3 22.1 0 16.3-1.6 32.6-1.6 51.5 0 24.2 7.9 33.6 23.6 37.3v1.6c-15.8 3.7-23.6 13.1-23.6 37.3 0 18.9 1.6 34.2 1.6 51.5 0 17.9-3.7 22.6-17.3 22.6v.5h-6.3V393h20.5c27.8 0 40.5-11 40.5-45.2 0-22.6-3.2-34.2-3.2-54.6 0-11 6.8-22.6 27.3-23.6v-27.3c-20.5-.7-27.3-12.3-27.3-23.3zm-105.6 32c-15.8-6.3-30.5-10-30.5-20.5 0-7.9 6.3-12.6 17.9-12.6s22.1 4.7 33.6 13.1l21-27.8c-13.1-10-31-20.5-55.2-20.5-35.7 0-59.9 20.5-59.9 49.4 0 25.7 22.6 38.9 41.5 46.2 16.3 6.3 32.1 11.6 32.1 22.1 0 7.9-6.3 13.1-20.5 13.1-13.1 0-26.3-5.3-40.5-16.3l-21 30.5c15.8 13.1 39.9 22.1 59.9 22.1 42 0 64.6-22.1 64.6-51s-22.5-41-43-47.8zm-358.9 59.4c-3.7 0-8.4-3.2-8.4-13.1V119.1H65.2c-28.4 0-41 11-41 45.2 0 22.6 3.2 35.2 3.2 54.6 0 11-6.8 22.6-27.3 23.6v27.3c20.5.5 27.3 12.1 27.3 23.1 0 19.4-3.2 31-3.2 53.6 0 34.2 12.6 45.2 40.5 45.2h20.5v-24.2h-6.3c-13.1 0-17.3-5.3-17.3-22.6s1.6-32.1 1.6-51.5c0-24.2-7.9-33.6-23.6-37.3v-1.6c15.8-3.7 23.6-13.1 23.6-37.3 0-18.9-1.6-34.2-1.6-51.5s3.7-22.1 17.3-22.1H93v150.8c0 32.1 11 53.1 43.1 53.1 10 0 17.9-1.6 23.6-3.7l-5.3-34.2c-3.1.8-4.6.8-6.2.8zM379.9 251c-16.3-6.3-31-10-31-20.5 0-7.9 6.3-12.6 17.9-12.6 11.6 0 22.1 4.7 33.6 13.1l21-27.8c-13.1-10-31-20.5-55.2-20.5-35.7 0-59.9 20.5-59.9 49.4 0 25.7 22.6 38.9 41.5 46.2 16.3 6.3 32.1 11.6 32.1 22.1 0 7.9-6.3 13.1-20.5 13.1-13.1 0-26.3-5.3-40.5-16.3l-20.5 30.5c15.8 13.1 39.9 22.1 59.9 22.1 42 0 64.6-22.1 64.6-51 .1-28.9-22.5-41-43-47.8zm-155-68.8c-38.4 0-75.1 32.1-74.1 82.5 0 52 34.2 82.5 79.3 82.5 18.9 0 39.9-6.8 56.2-17.9l-15.8-27.8c-11.6 6.8-22.6 10-34.2 10-21 0-37.3-10-41.5-34.2H290c.5-3.7 1.6-11 1.6-19.4.6-42.6-22.6-75.7-66.7-75.7zm-30 66.2c3.2-21 15.8-31 30.5-31 18.9 0 26.3 13.1 26.3 31h-56.8z"],line:[448,512,[],"f3c0","M272.1 204.2v71.1c0 1.8-1.4 3.2-3.2 3.2h-11.4c-1.1 0-2.1-.6-2.6-1.3l-32.6-44v42.2c0 1.8-1.4 3.2-3.2 3.2h-11.4c-1.8 0-3.2-1.4-3.2-3.2v-71.1c0-1.8 1.4-3.2 3.2-3.2H219c1 0 2.1.5 2.6 1.4l32.6 44v-42.2c0-1.8 1.4-3.2 3.2-3.2h11.4c1.8-.1 3.3 1.4 3.3 3.1zm-82-3.2h-11.4c-1.8 0-3.2 1.4-3.2 3.2v71.1c0 1.8 1.4 3.2 3.2 3.2h11.4c1.8 0 3.2-1.4 3.2-3.2v-71.1c0-1.7-1.4-3.2-3.2-3.2zm-27.5 59.6h-31.1v-56.4c0-1.8-1.4-3.2-3.2-3.2h-11.4c-1.8 0-3.2 1.4-3.2 3.2v71.1c0 .9.3 1.6.9 2.2.6.5 1.3.9 2.2.9h45.7c1.8 0 3.2-1.4 3.2-3.2v-11.4c0-1.7-1.4-3.2-3.1-3.2zM332.1 201h-45.7c-1.7 0-3.2 1.4-3.2 3.2v71.1c0 1.7 1.4 3.2 3.2 3.2h45.7c1.8 0 3.2-1.4 3.2-3.2v-11.4c0-1.8-1.4-3.2-3.2-3.2H301v-12h31.1c1.8 0 3.2-1.4 3.2-3.2V234c0-1.8-1.4-3.2-3.2-3.2H301v-12h31.1c1.8 0 3.2-1.4 3.2-3.2v-11.4c-.1-1.7-1.5-3.2-3.2-3.2zM448 113.7V399c-.1 44.8-36.8 81.1-81.7 81H81c-44.8-.1-81.1-36.9-81-81.7V113c.1-44.8 36.9-81.1 81.7-81H367c44.8.1 81.1 36.8 81 81.7zm-61.6 122.6c0-73-73.2-132.4-163.1-132.4-89.9 0-163.1 59.4-163.1 132.4 0 65.4 58 120.2 136.4 130.6 19.1 4.1 16.9 11.1 12.6 36.8-.7 4.1-3.3 16.1 14.1 8.8 17.4-7.3 93.9-55.3 128.2-94.7 23.6-26 34.9-52.3 34.9-81.5z"],linkedin:[448,512,[],"f08c","M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"],"linkedin-in":[448,512,[],"f0e1","M100.3 480H7.4V180.9h92.9V480zM53.8 140.1C24.1 140.1 0 115.5 0 85.8 0 56.1 24.1 32 53.8 32c29.7 0 53.8 24.1 53.8 53.8 0 29.7-24.1 54.3-53.8 54.3zM448 480h-92.7V334.4c0-34.7-.7-79.2-48.3-79.2-48.3 0-55.7 37.7-55.7 76.7V480h-92.8V180.9h89.1v40.8h1.3c12.4-23.5 42.7-48.3 87.9-48.3 94 0 111.3 61.9 111.3 142.3V480z"],linode:[448,512,[],"f2b8","M437.4 226.3c-.3-.9-.9-1.4-1.4-2l-70-38.6c-.9-.6-2-.6-3.1 0l-58.9 36c-.9.6-1.4 1.7-1.4 2.6l-.9 31.4-24-16c-.9-.6-2.3-.6-3.1 0L240 260.9l-1.4-35.1c0-.9-.6-2-1.4-2.3l-36-24.3 33.7-17.4c1.1-.6 1.7-1.7 1.7-2.9l-5.7-132.3c0-.9-.9-2-1.7-2.6L138.6.3c-.9-.3-1.7-.3-2.3-.3L12.6 38.6c-1.4.6-2.3 2-2 3.7L38 175.4c.9 3.4 34 27.4 38.6 30.9l-26.9 12.9c-1.4.9-2 2.3-1.7 3.4l20.6 100.3c.6 2.9 23.7 23.1 27.1 26.3l-17.4 10.6c-.9.6-1.7 2-1.4 3.1 1.4 7.1 15.4 77.7 16.9 79.1l65.1 69.1c.6.6 1.4.6 2.3.9.6 0 1.1-.3 1.7-.6l83.7-66.9c.9-.6 1.1-1.4 1.1-2.3l-2-46 28 23.7c1.1.9 2.9.9 4 0l66.9-53.4c.9-.6 1.1-1.4 1.1-2.3l2.3-33.4 20.3 14c1.1.9 2.6.9 3.7 0l54.6-43.7c.6-.3 1.1-1.1 1.1-2 .9-6.5 10.3-70.8 9.7-72.8zm-204.8 4.8l4 92.6-90.6 61.2-14-96.6 100.6-57.2zm-7.7-180l5.4 126-106.6 55.4L104 97.7l120.9-46.6zM44 173.1L18 48l79.7 49.4 19.4 132.9L44 173.1zm30.6 147.8L55.7 230l70 58.3 13.7 93.4-64.8-60.8zm24.3 117.7l-13.7-67.1 61.7 60.9 9.7 67.4-57.7-61.2zm64.5 64.5l-10.6-70.9 85.7-61.4 3.1 70-78.2 62.3zm82-115.1c0-3.4.9-22.9-2-25.1l-24.3-20 22.3-14.9c2.3-1.7 1.1-5.7 1.1-8l29.4 22.6.6 68.3-27.1-22.9zm94.3-25.4l-60.9 48.6-.6-68.6 65.7-46.9-4.2 66.9zm27.7-25.7l-19.1-13.4 2-34c.3-.9-.3-2-1.1-2.6L308 259.7l.6-30 64.6 40.6-5.8 66.6zm54.6-39.8l-48.3 38.3 5.7-65.1 51.1-36.6-8.5 63.4z"],linux:[448,512,[],"f17c","M196.1 123.6c-.2-1.4 1.9-2.3 3.2-2.9 1.7-.7 3.9-1 5.5-.1.4.2.8.7.6 1.1-.4 1.2-2.4 1-3.5 1.6-1 .5-1.8 1.7-3 1.7-1 .1-2.7-.4-2.8-1.4zm24.7-.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7zm214.7 310.2c-.5 8.2-6.5 13.8-13.9 18.3-14.9 9-37.3 15.8-50.9 32.2l-2.6-2.2 2.6 2.2c-14.2 16.9-31.7 26.6-48.3 27.9-16.5 1.3-32-6.3-40.3-23v-.1c-1.1-2.1-1.9-4.4-2.5-6.7-21.5 1.2-40.2-5.3-55.1-4.1-22 1.2-35.8 6.5-48.3 6.6-4.8 10.6-14.3 17.6-25.9 20.2-16 3.7-36.1 0-55.9-10.4l1.6-3-1.6 3c-18.5-9.8-42-8.9-59.3-12.5-8.7-1.8-16.3-5-20.1-12.3-3.7-7.3-3-17.3 2.2-31.7 1.7-5.1.4-12.7-.8-20.8-.6-3.9-1.2-7.9-1.2-11.8 0-4.3.7-8.5 2.8-12.4 4.5-8.5 11.8-12.1 18.5-14.5 6.7-2.4 12.8-4 17-8.3 5.2-5.5 10.1-14.4 16.6-20.2-2.6-17.2.2-35.4 6.2-53.3 12.6-37.9 39.2-74.2 58.1-96.7 16.1-22.9 20.8-41.3 22.5-64.7C158 103.4 132.4-.2 234.8 0c80.9.1 76.3 85.4 75.8 131.3-.3 30.1 16.3 50.5 33.4 72 15.2 18 35.1 44.3 46.5 74.4 9.3 24.6 12.9 51.8 3.7 79.1 1.4.5 2.8 1.2 4.1 2 1.4.8 2.7 1.8 4 2.9 6.6 5.6 8.7 14.3 10.5 22.4 1.9 8.1 3.6 15.7 7.2 19.7 11.1 12.4 15.9 21.5 15.5 29.7zM220.8 109.1c3.6.9 8.9 2.4 13 4.4-2.1-12.2 4.5-23.5 11.8-23 8.9.3 13.9 15.5 9.1 27.3-.8 1.9-2.8 3.4-3.9 4.6 6.7 2.3 11 4.1 12.6 4.9 7.9-9.5 10.8-26.2 4.3-40.4-9.8-21.4-34.2-21.8-44 .4-3.2 7.2-3.9 14.9-2.9 21.8zm-46.2 18.8c7.8-5.7 6.9-4.7 5.9-5.5-8-6.9-6.6-27.4 1.8-28.1 6.3-.5 10.8 10.7 9.6 19.6 3.1-2.1 6.7-3.6 10.2-4.6 1.7-19.3-9-33.5-19.1-33.5-18.9 0-24 37.5-8.4 52.1zm-9.4 20.9c1.5 4.9 6.1 10.5 14.7 15.3 7.8 4.6 12 11.5 20 15 2.6 1.1 5.7 1.9 9.6 2.1 18.4 1.1 27.1-11.3 38.2-14.9 11.7-3.7 20.1-11 22.7-18.1 3.2-8.5-2.1-14.7-10.5-18.2-11.3-4.9-16.3-5.2-22.6-9.3-10.3-6.6-18.8-8.9-25.9-8.9-14.4 0-23.2 9.8-27.9 14.2-.5.5-7.9 5.9-14.1 10.5-4.2 3.3-5.6 7.4-4.2 12.3zm-33.5 252.8L112.1 366c-6.8-9.2-13.8-14.8-21.9-16-7.7-1.2-12.6 1.4-17.7 6.9-4.8 5.1-8.8 12.3-14.3 18-7.8 6.5-9.3 6.2-19.6 9.9-6.3 2.2-11.3 4.6-14.8 11.3-2.7 5-2.1 12.2-.9 20 1.2 7.9 3 16.3.6 23.9v.2c-5 13.7-5 21.7-2.6 26.4 7.9 15.4 46.6 6.1 76.5 21.9 31.4 16.4 72.6 17.1 75.3-18 2.1-20.5-31.5-49-41-68.9zm153.9 35.8c3.2-11 6.3-21.3 6.8-29 .8-15.2 1.6-28.7 4.4-39.9 3.1-12.6 9.3-23.1 21.4-27.3 2.3-21.1 18.7-21.1 38.3-12.5 18.9 8.5 26 16 22.8 26.1 1 0 2-.1 4.2 0 5.2-16.9-14.3-28-30.7-34.8 2.9-12 2.4-24.1-.4-35.7-6-25.3-22.6-47.8-35.2-59-2.3-.1-2.1 1.9 2.6 6.5 11.6 10.7 37.1 49.2 23.3 84.9-3.9-1-7.6-1.5-10.9-1.4-5.3-29.1-17.5-53.2-23.6-64.6-11.5-21.4-29.5-65.3-37.2-95.7-4.5 6.4-12.4 11.9-22.3 15-4.7 1.5-9.7 5.5-15.9 9-13.9 8-30 8.8-42.4-1.2-4.5-3.6-8-7.6-12.6-10.3-1.6-.9-5.1-3.3-6.2-4.1-2 37.8-27.3 85.3-39.3 112.7-8.3 19.7-13.2 40.8-13.8 61.5-21.8-29.1-5.9-66.3 2.6-82.4 9.5-17.6 11-22.5 8.7-20.8-8.6 14-22 36.3-27.2 59.2-2.7 11.9-3.2 24 .3 35.2 3.5 11.2 11.1 21.5 24.6 29.9 0 0 24.8 14.3 38.3 32.5 7.4 10 9.7 18.7 7.4 24.9-2.5 6.7-9.6 8.9-16.7 8.9 4.8 6 10.3 13 14.4 19.6 37.6 25.7 82.2 15.7 114.3-7.2zM415 408.5c-10-11.3-7.2-33.1-17.1-41.6-6.9-6-13.6-5.4-22.6-5.1-7.7 8.8-25.8 19.6-38.4 16.3-11.5-2.9-18-16.3-18.8-29.5-.3.2-.7.3-1 .5-7.1 3.9-11.1 10.8-13.7 21.1-2.5 10.2-3.4 23.5-4.2 38.7-.7 11.8-6.2 26.4-9.9 40.6-3.5 13.2-5.8 25.2-1.1 36.3 7.2 14.5 19.5 20.4 33.7 19.3 14.2-1.1 30.4-9.8 43.6-25.5 22-26.6 62.3-29.7 63.2-46.5.3-5.1-3.1-13-13.7-24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4 3.9-3.4 5.9-6.3 3.1-6.6-2.8-.3-2.6 2.6-6 5.1-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2-10.4 0-18.7-4.8-24.9-9.7-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"],lyft:[512,512,[],"f3c3","M0 81.1h77.8v208.7c0 33.1 15 52.8 27.2 61-12.7 11.1-51.2 20.9-80.2-2.8C7.8 334 0 310.7 0 289V81.1zm485.9 173.5v-22h23.8v-76.8h-26.1c-10.1-46.3-51.2-80.7-100.3-80.7-56.6 0-102.7 46-102.7 102.7V357c16 2.3 35.4-.3 51.7-14 17.1-14 24.8-37.2 24.8-59v-6.7h38.8v-76.8h-38.8v-23.3c0-34.6 52.2-34.6 52.2 0v77.1c0 56.6 46 102.7 102.7 102.7v-76.5c-14.5 0-26.1-11.7-26.1-25.9zm-294.3-99v113c0 15.4-23.8 15.4-23.8 0v-113H91v132.7c0 23.8 8 54 45 63.9 37 9.8 58.2-10.6 58.2-10.6-2.1 13.4-14.5 23.3-34.9 25.3-15.5 1.6-35.2-3.6-45-7.8v70.3c25.1 7.5 51.5 9.8 77.6 4.7 47.1-9.1 76.8-48.4 76.8-100.8V155.1h-77.1v.5z"],magento:[448,512,[],"f3c4","M445.7 127.9V384l-63.4 36.5V164.7L223.8 73.1 65.2 164.7l.4 255.9L2.3 384V128.1L224.2 0l221.5 127.9zM255.6 420.5L224 438.9l-31.8-18.2v-256l-63.3 36.6.1 255.9 94.9 54.9 95.1-54.9v-256l-63.4-36.6v255.9z"],maxcdn:[512,512,[],"f136","M461.1 442.7h-97.4L415.6 200c2.3-10.2.9-19.5-4.4-25.7-5-6.1-13.7-9.6-24.2-9.6h-49.3l-59.5 278h-97.4l59.5-278h-83.4l-59.5 278H0l59.5-278-44.6-95.4H387c39.4 0 75.3 16.3 98.3 44.9 23.3 28.6 31.8 67.4 23.6 105.9l-47.8 222.6z"],medapps:[320,512,[],"f3c6","M118.3 238.4c3.5-12.5 6.9-33.6 13.2-33.6 8.3 1.8 9.6 23.4 18.6 36.6 4.6-23.5 5.3-85.1 14.1-86.7 9-.7 19.7 66.5 22 77.5 9.9 4.1 48.9 6.6 48.9 6.6 1.9 7.3-24 7.6-40 7.8-4.6 14.8-5.4 27.7-11.4 28-4.7.2-8.2-28.8-17.5-49.6l-9.4 65.5c-4.4 13-15.5-22.5-21.9-39.3-3.3-.1-62.4-1.6-47.6-7.8l31-5zM228 448c21.2 0 21.2-32 0-32H92c-21.2 0-21.2 32 0 32h136zm-24 64c21.2 0 21.2-32 0-32h-88c-21.2 0-21.2 32 0 32h88zm34.2-141.5c3.2-18.9 5.2-36.4 11.9-48.8 7.9-14.7 16.1-28.1 24-41 24.6-40.4 45.9-75.2 45.9-125.5C320 69.6 248.2 0 160 0S0 69.6 0 155.2c0 50.2 21.3 85.1 45.9 125.5 7.9 12.9 16 26.3 24 41 6.7 12.5 8.7 29.8 11.9 48.9 3.5 21 36.1 15.7 32.6-5.1-3.6-21.7-5.6-40.7-15.3-58.6C66.5 246.5 33 211.3 33 155.2 33 87.3 90 32 160 32s127 55.3 127 123.2c0 56.1-33.5 91.3-66.1 151.6-9.7 18-11.7 37.4-15.3 58.6-3.4 20.6 29 26.4 32.6 5.1z"],medium:[448,512,[],"f23a","M0 32v448h448V32H0zm372.2 106.1l-24 23c-2.1 1.6-3.1 4.2-2.7 6.7v169.3c-.4 2.6.6 5.2 2.7 6.7l23.5 23v5.1h-118V367l24.3-23.6c2.4-2.4 2.4-3.1 2.4-6.7V199.8l-67.6 171.6h-9.1L125 199.8v115c-.7 4.8 1 9.7 4.4 13.2l31.6 38.3v5.1H71.2v-5.1l31.6-38.3c3.4-3.5 4.9-8.4 4.1-13.2v-133c.4-3.7-1-7.3-3.8-9.8L75 138.1V133h87.3l67.4 148L289 133.1h83.2v5z"],"medium-m":[512,512,[],"f3c7","M71.5 142.3c.6-5.9-1.7-11.8-6.1-15.8L20.3 72.1V64h140.2l108.4 237.7L364.2 64h133.7v8.1l-38.6 37c-3.3 2.5-5 6.7-4.3 10.8v272c-.7 4.1 1 8.3 4.3 10.8l37.7 37v8.1H307.3v-8.1l39.1-37.9c3.8-3.8 3.8-5 3.8-10.8V171.2L241.5 447.1h-14.7L100.4 171.2v184.9c-1.1 7.8 1.5 15.6 7 21.2l50.8 61.6v8.1h-144v-8L65 377.3c5.4-5.6 7.9-13.5 6.5-21.2V142.3z"],medrt:[544,512,[],"f3c8","M113.7 256c0 121.8 83.9 222.8 193.5 241.1-18.7 4.5-38.2 6.9-58.2 6.9C111.4 504 0 393 0 256S111.4 8 248.9 8c20.1 0 39.6 2.4 58.2 6.9C197.5 33.2 113.7 134.2 113.7 256m297.4 100.3c-77.7 55.4-179.6 47.5-240.4-14.6 5.5 14.1 12.7 27.7 21.7 40.5 61.6 88.2 182.4 109.3 269.7 47 87.3-62.3 108.1-184.3 46.5-272.6-9-12.9-19.3-24.3-30.5-34.2 37.4 78.8 10.7 178.5-67 233.9m-218.8-244c-1.4 1-2.7 2.1-4 3.1 64.3-17.8 135.9 4 178.9 60.5 35.7 47 42.9 106.6 24.4 158 56.7-56.2 67.6-142.1 22.3-201.8-50-65.5-149.1-74.4-221.6-19.8M296 224c-4.4 0-8-3.6-8-8v-40c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v40c0 4.4-3.6 8-8 8h-40c-4.4 0-8 3.6-8 8v48c0 4.4 3.6 8 8 8h40c4.4 0 8 3.6 8 8v40c0 4.4 3.6 8 8 8h48c4.4 0 8-3.6 8-8v-40c0-4.4 3.6-8 8-8h40c4.4 0 8-3.6 8-8v-48c0-4.4-3.6-8-8-8h-40z"],meetup:[512,512,[],"f2e0","M99 414.3c1.1 5.7-2.3 11.1-8 12.3-5.4 1.1-10.9-2.3-12-8-1.1-5.4 2.3-11.1 7.7-12.3 5.4-1.2 11.1 2.3 12.3 8zm143.1 71.4c-6.3 4.6-8 13.4-3.7 20 4.6 6.6 13.4 8.3 20 3.7 6.3-4.6 8-13.4 3.4-20-4.2-6.5-13.1-8.3-19.7-3.7zm-86-462.3c6.3-1.4 10.3-7.7 8.9-14-1.1-6.6-7.4-10.6-13.7-9.1-6.3 1.4-10.3 7.7-9.1 14 1.4 6.6 7.6 10.6 13.9 9.1zM34.4 226.3c-10-6.9-23.7-4.3-30.6 6-6.9 10-4.3 24 5.7 30.9 10 7.1 23.7 4.6 30.6-5.7 6.9-10.4 4.3-24.1-5.7-31.2zm272-170.9c10.6-6.3 13.7-20 7.7-30.3-6.3-10.6-19.7-14-30-7.7s-13.7 20-7.4 30.6c6 10.3 19.4 13.7 29.7 7.4zm-191.1 58c7.7-5.4 9.4-16 4.3-23.7s-15.7-9.4-23.1-4.3c-7.7 5.4-9.4 16-4.3 23.7 5.1 7.8 15.6 9.5 23.1 4.3zm372.3 156c-7.4 1.7-12.3 9.1-10.6 16.9 1.4 7.4 8.9 12.3 16.3 10.6 7.4-1.4 12.3-8.9 10.6-16.6-1.5-7.4-8.9-12.3-16.3-10.9zm39.7-56.8c-1.1-5.7-6.6-9.1-12-8-5.7 1.1-9.1 6.9-8 12.6 1.1 5.4 6.6 9.1 12.3 8 5.4-1.5 9.1-6.9 7.7-12.6zM447 138.9c-8.6 6-10.6 17.7-4.9 26.3 5.7 8.6 17.4 10.6 26 4.9 8.3-6 10.3-17.7 4.6-26.3-5.7-8.7-17.4-10.9-25.7-4.9zm-6.3 139.4c26.3 43.1 15.1 100-26.3 129.1-17.4 12.3-37.1 17.7-56.9 17.1-12 47.1-69.4 64.6-105.1 32.6-1.1.9-2.6 1.7-3.7 2.9-39.1 27.1-92.3 17.4-119.4-22.3-9.7-14.3-14.6-30.6-15.1-46.9-65.4-10.9-90-94-41.1-139.7-28.3-46.9.6-107.4 53.4-114.9C151.6 70 234.1 38.6 290.1 82c67.4-22.3 136.3 29.4 130.9 101.1 41.1 12.6 52.8 66.9 19.7 95.2zm-70 74.3c-3.1-20.6-40.9-4.6-43.1-27.1-3.1-32 43.7-101.1 40-128-3.4-24-19.4-29.1-33.4-29.4-13.4-.3-16.9 2-21.4 4.6-2.9 1.7-6.6 4.9-11.7-.3-6.3-6-11.1-11.7-19.4-12.9-12.3-2-17.7 2-26.6 9.7-3.4 2.9-12 12.9-20 9.1-3.4-1.7-15.4-7.7-24-11.4-16.3-7.1-40 4.6-48.6 20-12.9 22.9-38 113.1-41.7 125.1-8.6 26.6 10.9 48.6 36.9 47.1 11.1-.6 18.3-4.6 25.4-17.4 4-7.4 41.7-107.7 44.6-112.6 2-3.4 8.9-8 14.6-5.1 5.7 3.1 6.9 9.4 6 15.1-1.1 9.7-28 70.9-28.9 77.7-3.4 22.9 26.9 26.6 38.6 4 3.7-7.1 45.7-92.6 49.4-98.3 4.3-6.3 7.4-8.3 11.7-8 3.1 0 8.3.9 7.1 10.9-1.4 9.4-35.1 72.3-38.9 87.7-4.6 20.6 6.6 41.4 24.9 50.6 11.4 5.7 62.5 15.7 58.5-11.1zm5.7 92.3c-10.3 7.4-12.9 22-5.7 32.6 7.1 10.6 21.4 13.1 32 6 10.6-7.4 13.1-22 6-32.6-7.4-10.6-21.7-13.5-32.3-6z"],microsoft:[448,512,[],"f3ca","M0 32h214.6v214.6H0V32zm233.4 0H448v214.6H233.4V32zM0 265.4h214.6V480H0V265.4zm233.4 0H448V480H233.4V265.4z"],mix:[416,512,[],"f3cb","M0 64v348.9c0 56.2 88 58.1 88 0V174.3c7.9-52.9 88-50.4 88 6.5v175.3c0 57.9 96 58 96 0V240c5.3-54.7 88-52.5 88 4.3v23.8c0 59.9 88 56.6 88 0V64H0z"],mixcloud:[640,512,[],"f289","M424.43 219.729C416.124 134.727 344.135 68 256.919 68c-72.266 0-136.224 46.516-159.205 114.074-54.545 8.029-96.63 54.822-96.63 111.582 0 62.298 50.668 112.966 113.243 112.966h289.614c52.329 0 94.969-42.362 94.969-94.693 0-45.131-32.118-83.063-74.48-92.2zm-20.489 144.53H114.327c-39.04 0-70.881-31.564-70.881-70.604s31.841-70.604 70.881-70.604c18.827 0 36.548 7.475 49.838 20.766 19.963 19.963 50.133-10.227 30.18-30.18-14.675-14.398-32.672-24.365-52.053-29.349 19.935-44.3 64.79-73.926 114.628-73.926 69.496 0 125.979 56.483 125.979 125.702 0 13.568-2.215 26.857-6.369 39.594-8.943 27.517 32.133 38.939 40.147 13.29 2.769-8.306 4.984-16.889 6.369-25.472 19.381 7.476 33.502 26.303 33.502 48.453 0 28.795-23.535 52.33-52.607 52.33zm235.069-52.33c0 44.024-12.737 86.386-37.102 122.657-4.153 6.092-10.798 9.414-17.72 9.414-16.317 0-27.127-18.826-17.443-32.949 19.381-29.349 29.903-63.682 29.903-99.122s-10.521-69.773-29.903-98.845c-15.655-22.831 19.361-47.24 35.163-23.534 24.366 35.993 37.102 78.356 37.102 122.379zm-70.88 0c0 31.565-9.137 62.021-26.857 88.325-4.153 6.091-10.798 9.136-17.72 9.136-17.201 0-27.022-18.979-17.443-32.948 13.013-19.104 19.658-41.255 19.658-64.513 0-22.981-6.645-45.408-19.658-64.512-15.761-22.986 19.008-47.095 35.163-23.535 17.719 26.026 26.857 56.483 26.857 88.047z"],mizuni:[496,512,[],"f3cc","M248 8C111 8 0 119.1 0 256c0 137 111 248 248 248s248-111 248-248C496 119.1 385 8 248 8zm-80 351.9c-31.4 10.6-58.8 27.3-80 48.2V136c0-22.1 17.9-40 40-40s40 17.9 40 40v223.9zm120-9.9c-12.9-2-26.2-3.1-39.8-3.1-13.8 0-27.2 1.1-40.2 3.1V136c0-22.1 17.9-40 40-40s40 17.9 40 40v214zm120 57.7c-21.2-20.8-48.6-37.4-80-48V136c0-22.1 17.9-40 40-40s40 17.9 40 40v271.7z"],modx:[448,512,[],"f285","M356 241.8l36.7 23.7V480l-133-83.8L356 241.8zM440 75H226.3l-23 37.8 153.5 96.5L440 75zm-89 142.8L55.2 32v214.5l46 29L351 217.8zM97 294.2L8 437h213.7l125-200.5L97 294.2z"],monero:[496,512,[],"f3d0","M352 384h108.4C417 455.9 338.1 504 248 504S79 455.9 35.6 384H144V256.2L248 361l104-105v128zM88 336V128l159.4 159.4L408 128v208h74.8c8.5-25.1 13.2-52 13.2-80C496 119 385 8 248 8S0 119 0 256c0 28 4.6 54.9 13.2 80H88z"],napster:[496,512,[],"f3d2","M298.3 373.6c-14.2 13.6-31.3 24.1-50.4 30.5-19-6.4-36.2-16.9-50.3-30.5h100.7zm44-199.6c20-16.9 43.6-29.2 69.6-36.2V299c0 219.4-328 217.6-328 .3V137.7c25.9 6.9 49.6 19.6 69.5 36.4 56.8-40 132.5-39.9 188.9-.1zm-208.8-58.5c64.4-60 164.3-60.1 228.9-.2-7.1 3.5-13.9 7.3-20.6 11.5-58.7-30.5-129.2-30.4-187.9.1-6.3-4-13.9-8.2-20.4-11.4zM43.8 93.2v69.3c-58.4 36.5-58.4 121.1.1 158.3 26.4 245.1 381.7 240.3 407.6 1.5l.3-1.7c58.7-36.3 58.9-121.7.2-158.2V93.2c-17.3.5-34 3-50.1 7.4-82-91.5-225.5-91.5-307.5.1-16.3-4.4-33.1-7-50.6-7.5zM259.2 352s36-.3 61.3-1.5c10.2-.5 21.1-4 25.5-6.5 26.3-15.1 25.4-39.2 26.2-47.4-79.5-.6-99.9-3.9-113 55.4zm-135.5-55.3c.8 8.2-.1 32.3 26.2 47.4 4.4 2.5 15.2 6 25.5 6.5 25.3 1.1 61.3 1.5 61.3 1.5-13.2-59.4-33.7-56.1-113-55.4zm169.1 123.4c-3.2-5.3-6.9-7.3-6.9-7.3-24.8 7.3-52.2 6.9-75.9 0 0 0-2.9 1.5-6.4 6.6-2.8 4.1-3.7 9.6-3.7 9.6 29.1 17.6 67.1 17.6 96.2 0-.1-.1-.3-4-3.3-8.9z"],"nintendo-switch":[448,512,[],"f418","M95.9 33.5c-44.6 8-80.5 41-91.8 84.4C0 133.6-.3 142.8.2 264.4.4 376 .5 378.6 2.4 387.3c10.3 46.5 43.3 79.6 90.3 90.5 6.1 1.4 13.9 1.7 64.1 1.9 51.9.4 57.3.3 58.7-1.1 1.4-1.4 1.5-19.3 1.5-222.2 0-150.5-.3-221.3-.9-222.6-.9-1.7-2.5-1.8-56.9-1.7-44.2.1-57.5.4-63.3 1.4zm83.9 222.6V444l-37.8-.5c-34.8-.4-38.5-.6-45.5-2.3-29.9-7.7-52-30.7-58.3-60.7-2-9.4-2-240.1-.1-249.3 5.6-26.1 23.7-47.7 48-57.4 12.2-4.9 17.9-5.5 57.6-5.6l35.9-.1v188zm-75.9-131.2c-5.8 1.1-14.7 5.6-19.5 9.7-9.7 8.4-14.6 20.4-13.8 34.5.4 7.3.8 9.3 3.8 15.2 4.4 9 10.9 15.6 19.9 20 6.2 3.1 7.8 3.4 15.9 3.7 7.3.3 9.9 0 14.8-1.7 20.1-6.8 32.3-26.3 28.8-46.4-3.9-23.7-26.6-39.7-49.9-35zm158.2-92.3c-.4.3-.6 100.8-.6 223.5 0 202.3.1 222.8 1.5 223.4 2.5.9 74.5.6 83.4-.4 37.7-4.3 71-27.2 89-61.2 2.3-4.4 5.4-11.7 7-16.2 5.8-17.4 5.7-12.8 5.7-146.1 0-106.4-.2-122.3-1.5-129-9.2-48.3-46.1-84.8-94.5-93.1-6.5-1.1-16.5-1.4-48.8-1.4-22.4-.1-40.9.2-41.2.5zm99.1 202.1c14.5 3.8 26.3 14.8 31.2 28.9 3.1 8.7 3 21.5-.1 29.5-5.7 14.7-16.8 25-31.1 28.8-23.2 6-47.9-8-54.6-31-2-7-1.9-18.9.4-26.2 6.9-22.7 31-36.1 54.2-30z"],node:[640,512,[],"f419","M316.3 452c-2.1 0-4.2-.6-6.1-1.6L291 439c-2.9-1.6-1.5-2.2-.5-2.5 3.8-1.3 4.6-1.6 8.7-4 .4-.2 1-.1 1.4.1l14.8 8.8c.5.3 1.3.3 1.8 0L375 408c.5-.3.9-.9.9-1.6v-66.7c0-.7-.3-1.3-.9-1.6l-57.8-33.3c-.5-.3-1.2-.3-1.8 0l-57.8 33.3c-.6.3-.9 1-.9 1.6v66.7c0 .6.4 1.2.9 1.5l15.8 9.1c8.6 4.3 13.9-.8 13.9-5.8v-65.9c0-.9.7-1.7 1.7-1.7h7.3c.9 0 1.7.7 1.7 1.7v65.9c0 11.5-6.2 18-17.1 18-3.3 0-6 0-13.3-3.6l-15.2-8.7c-3.7-2.2-6.1-6.2-6.1-10.5v-66.7c0-4.3 2.3-8.4 6.1-10.5l57.8-33.4c3.7-2.1 8.5-2.1 12.1 0l57.8 33.4c3.7 2.2 6.1 6.2 6.1 10.5v66.7c0 4.3-2.3 8.4-6.1 10.5l-57.8 33.4c-1.7 1.1-3.8 1.7-6 1.7zm46.7-65.8c0-12.5-8.4-15.8-26.2-18.2-18-2.4-19.8-3.6-19.8-7.8 0-3.5 1.5-8.1 14.8-8.1 11.9 0 16.3 2.6 18.1 10.6.2.8.8 1.3 1.6 1.3h7.5c.5 0 .9-.2 1.2-.5.3-.4.5-.8.4-1.3-1.2-13.8-10.3-20.2-28.8-20.2-16.5 0-26.3 7-26.3 18.6 0 12.7 9.8 16.1 25.6 17.7 18.9 1.9 20.4 4.6 20.4 8.3 0 6.5-5.2 9.2-17.4 9.2-15.3 0-18.7-3.8-19.8-11.4-.1-.8-.8-1.4-1.7-1.4h-7.5c-.9 0-1.7.7-1.7 1.7 0 9.7 5.3 21.3 30.6 21.3 18.5 0 29-7.2 29-19.8zm54.5-50.1c0 6.1-5 11.1-11.1 11.1s-11.1-5-11.1-11.1c0-6.3 5.2-11.1 11.1-11.1 6-.1 11.1 4.8 11.1 11.1zm-1.8 0c0-5.2-4.2-9.3-9.4-9.3-5.1 0-9.3 4.1-9.3 9.3 0 5.2 4.2 9.4 9.3 9.4 5.2-.1 9.4-4.3 9.4-9.4zm-4.5 6.2h-2.6c-.1-.6-.5-3.8-.5-3.9-.2-.7-.4-1.1-1.3-1.1h-2.2v5h-2.4v-12.5h4.3c1.5 0 4.4 0 4.4 3.3 0 2.3-1.5 2.8-2.4 3.1 1.7.1 1.8 1.2 2.1 2.8.1 1 .3 2.7.6 3.3zm-2.8-8.8c0-1.7-1.2-1.7-1.8-1.7h-2v3.5h1.9c1.6 0 1.9-1.1 1.9-1.8zM137.3 191c0-2.7-1.4-5.1-3.7-6.4l-61.3-35.3c-1-.6-2.2-.9-3.4-1h-.6c-1.2 0-2.3.4-3.4 1L3.7 184.6C1.4 185.9 0 188.4 0 191l.1 95c0 1.3.7 2.5 1.8 3.2 1.1.7 2.5.7 3.7 0L42 268.3c2.3-1.4 3.7-3.8 3.7-6.4v-44.4c0-2.6 1.4-5.1 3.7-6.4l15.5-8.9c1.2-.7 2.4-1 3.7-1 1.3 0 2.6.3 3.7 1l15.5 8.9c2.3 1.3 3.7 3.8 3.7 6.4v44.4c0 2.6 1.4 5.1 3.7 6.4l36.4 20.9c1.1.7 2.6.7 3.7 0 1.1-.6 1.8-1.9 1.8-3.2l.2-95zM472.5 87.3v176.4c0 2.6-1.4 5.1-3.7 6.4l-61.3 35.4c-2.3 1.3-5.1 1.3-7.4 0l-61.3-35.4c-2.3-1.3-3.7-3.8-3.7-6.4v-70.8c0-2.6 1.4-5.1 3.7-6.4l61.3-35.4c2.3-1.3 5.1-1.3 7.4 0l15.3 8.8c1.7 1 3.9-.3 3.9-2.2v-94c0-2.8 3-4.6 5.5-3.2l36.5 20.4c2.3 1.2 3.8 3.7 3.8 6.4zm-46 128.9c0-.7-.4-1.3-.9-1.6l-21-12.2c-.6-.3-1.3-.3-1.9 0l-21 12.2c-.6.3-.9.9-.9 1.6v24.3c0 .7.4 1.3.9 1.6l21 12.1c.6.3 1.3.3 1.8 0l21-12.1c.6-.3.9-.9.9-1.6v-24.3zm209.8-.7c2.3-1.3 3.7-3.8 3.7-6.4V192c0-2.6-1.4-5.1-3.7-6.4l-60.9-35.4c-2.3-1.3-5.1-1.3-7.4 0l-61.3 35.4c-2.3 1.3-3.7 3.8-3.7 6.4v70.8c0 2.7 1.4 5.1 3.7 6.4l60.9 34.7c2.2 1.3 5 1.3 7.3 0l36.8-20.5c2.5-1.4 2.5-5 0-6.4L550 241.6c-1.2-.7-1.9-1.9-1.9-3.2v-22.2c0-1.3.7-2.5 1.9-3.2l19.2-11.1c1.1-.7 2.6-.7 3.7 0l19.2 11.1c1.1.7 1.9 1.9 1.9 3.2v17.4c0 2.8 3.1 4.6 5.6 3.2l36.7-21.3zM559 219c-.4.3-.7.7-.7 1.2v13.6c0 .5.3 1 .7 1.2l11.8 6.8c.4.3 1 .3 1.4 0L584 235c.4-.3.7-.7.7-1.2v-13.6c0-.5-.3-1-.7-1.2l-11.8-6.8c-.4-.3-1-.3-1.4 0L559 219zm-254.2 43.5v-70.4c0-2.6-1.6-5.1-3.9-6.4l-61.1-35.2c-2.1-1.2-5-1.4-7.4 0l-61.1 35.2c-2.3 1.3-3.9 3.7-3.9 6.4v70.4c0 2.8 1.9 5.2 4 6.4l61.2 35.2c2.4 1.4 5.2 1.3 7.4 0l61-35.2c1.8-1 3.1-2.7 3.6-4.7.1-.5.2-1.1.2-1.7zm-74.3-124.9l-.8.5h1.1l-.3-.5zm76.2 130.2l-.4-.7v.9l.4-.2z"],"node-js":[448,512,[],"f3d3","M224 480c-6 0-12-1.6-17.2-4.6L151.9 443c-8.2-4.6-4.2-6.2-1.5-7.1 10.9-3.8 13.1-4.7 24.8-11.3 1.2-.7 2.8-.4 4.1.3l42.1 25c1.5.8 3.7.8 5.1 0l164.2-94.8c1.5-.9 2.5-2.6 2.5-4.4V161.2c0-1.9-1-3.6-2.5-4.5L226.5 62c-1.5-.9-3.5-.9-5.1 0l-164 94.7c-1.6.9-2.6 2.7-2.6 4.5v189.5c0 1.8 1 3.5 2.6 4.4l45 26c24.4 12.2 39.3-2.2 39.3-16.6V177.4c0-2.6 2.1-4.7 4.8-4.7h20.8c2.6 0 4.8 2.1 4.8 4.7v187.1c0 32.6-17.7 51.2-48.6 51.2-9.5 0-17 0-37.8-10.3l-43.1-24.8C32 374.5 25.4 363 25.4 350.7V161.2c0-12.3 6.6-23.8 17.2-29.9l164.2-94.9c10.4-5.9 24.2-5.9 34.5 0l164.2 94.9c10.6 6.1 17.2 17.6 17.2 29.9v189.5c0 12.3-6.6 23.8-17.2 29.9l-164.2 94.8c-5.3 3-11.3 4.6-17.3 4.6zm132.5-186.8c0-35.5-24-44.9-74.4-51.6-51-6.7-56.2-10.2-56.2-22.2 0-9.9 4.4-23 42.2-23 33.7 0 46.2 7.3 51.3 30 .4 2.1 2.4 3.7 4.6 3.7h21.3c1.3 0 2.6-.6 3.5-1.5.9-1 1.4-2.3 1.3-3.7-3.3-39.2-29.3-57.4-81.9-57.4-46.8 0-74.7 19.8-74.7 52.9 0 35.9 27.8 45.9 72.7 50.3 53.8 5.3 57.9 13.1 57.9 23.7 0 18.3-14.7 26.2-49.3 26.2-43.4 0-53-10.9-56.2-32.5-.4-2.3-2.3-4-4.7-4h-21.2c-2.6 0-4.7 2.1-4.7 4.7 0 27.7 15.1 60.6 86.9 60.6 51.8.1 81.6-20.4 81.6-56.2z"],npm:[576,512,[],"f3d4","M288 288h-32v-64h32v64zm288-128v192H288v32H160v-32H0V160h576zm-416 32H32v128h64v-96h32v96h32V192zm160 0H192v160h64v-32h64V192zm224 0H352v128h64v-96h32v96h32v-96h32v96h32V192z"],ns8:[640,512,[],"f3d5","M187.1 159.9l-34.2 113.7-54.5-113.7H49L0 320h44.9L76 213.5 126.6 320h56.9L232 159.9h-44.9zm452.5-.9c-2.9-18-23.9-28.1-42.1-31.3-44.6-7.8-101.9 16.3-88.5 58.8v.1c-43.8 8.7-74.3 26.8-94.2 48.2-3-9.8-13.6-16.6-34-16.6h-87.6c-9.3 0-12.9-2.3-11.5-7.4 1.6-5.5 1.9-6.8 3.7-12.2 2.1-6.4 7.8-7.1 13.3-7.1h133.5l9.7-31.5c-139.7 0-144.5-.5-160.1 1.2-12.3 1.3-23.5 4.8-30.6 15-6.8 9.9-14.4 35.6-17.6 47.1-5.4 19.4-.6 28.6 32.8 28.6h87.3c7.8 0 8.8 2.7 7.7 6.6-1.1 4.4-2.8 10-4.5 14.6-1.6 4.2-4.7 7.4-13.8 7.4H216.3L204.7 320c139.9 0 145.3-.6 160.9-2.3 6.6-.7 13-2.1 18.5-4.9.2 3.7.5 7.3 1.2 10.8 5.4 30.5 27.4 52.3 56.8 59.5 48.6 11.9 108.7-16.8 135.1-68 18.7-36.2 14.1-76.2-3.4-105.5h.1c29.6-5.9 70.3-22 65.7-50.6zM530.7 263.7c-5.9 29.5-36.6 47.8-61.6 43.9-30.9-4.8-38.5-39.5-14.1-64.8 16.2-16.8 45.2-24 68.5-26.9 6.7 14.1 10.3 32 7.2 47.8zm21.8-83.1c-4.2-6-9.8-18.5-2.5-26.3 6.7-7.2 20.9-10.1 31.8-7.7 15.3 3.4 19.7 15.9 4.9 24.4-10.7 6.1-23.6 8.1-34.2 9.6z"],nutritionix:[400,512,[],"f3d6","M88 8.1S221.4-.1 209 112.5c0 0 19.1-74.9 103-40.6 0 0-17.7 74-88 56 0 0 14.6-54.6 66.1-56.6 0 0-39.9-10.3-82.1 48.8 0 0-19.8-94.5-93.6-99.7 0 0 75.2 19.4 77.6 107.5 0 .1-106.4 7-104-119.8zm312 315.6c0 48.5-9.7 95.3-32 132.3-42.2 30.9-105 48-168 48-62.9 0-125.8-17.1-168-48C9.7 419 0 372.2 0 323.7 0 275.3 17.7 229 40 192c42.2-30.9 97.1-48.6 160-48.6 63 0 117.8 17.6 160 48.6 22.3 37 40 83.3 40 131.7zM120 428c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zM192 428c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zM264 428c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zM336 428c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm0-66.2c0-15.5-12.5-28-28-28s-28 12.5-28 28 12.5 28 28 28 28-12.5 28-28zm24-39.6c-4.8-22.3-7.4-36.9-16-56-38.8-19.9-90.5-32-144-32S94.8 180.1 56 200c-8.8 19.5-11.2 33.9-16 56 42.2-7.9 98.7-14.8 160-14.8s117.8 6.9 160 14.8z"],odnoklassniki:[320,512,[],"f263","M275.1 334c-27.4 17.4-65.1 24.3-90 26.9l20.9 20.6 76.3 76.3c27.9 28.6-17.5 73.3-45.7 45.7-19.1-19.4-47.1-47.4-76.3-76.6L84 503.4c-28.2 27.5-73.6-17.6-45.4-45.7 19.4-19.4 47.1-47.4 76.3-76.3l20.6-20.6c-24.6-2.6-62.9-9.1-90.6-26.9-32.6-21-46.9-33.3-34.3-59 7.4-14.6 27.7-26.9 54.6-5.7 0 0 36.3 28.9 94.9 28.9s94.9-28.9 94.9-28.9c26.9-21.1 47.1-8.9 54.6 5.7 12.4 25.7-1.9 38-34.5 59.1zM30.3 129.7C30.3 58 88.6 0 160 0s129.7 58 129.7 129.7c0 71.4-58.3 129.4-129.7 129.4s-129.7-58-129.7-129.4zm66 0c0 35.1 28.6 63.7 63.7 63.7s63.7-28.6 63.7-63.7c0-35.4-28.6-64-63.7-64s-63.7 28.6-63.7 64z"],"odnoklassniki-square":[448,512,[],"f264","M184.2 177.1c0-22.1 17.9-40 39.8-40s39.8 17.9 39.8 40c0 22-17.9 39.8-39.8 39.8s-39.8-17.9-39.8-39.8zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-305.1 97.1c0 44.6 36.4 80.9 81.1 80.9s81.1-36.2 81.1-80.9c0-44.8-36.4-81.1-81.1-81.1s-81.1 36.2-81.1 81.1zm174.5 90.7c-4.6-9.1-17.3-16.8-34.1-3.6 0 0-22.7 18-59.3 18s-59.3-18-59.3-18c-16.8-13.2-29.5-5.5-34.1 3.6-7.9 16.1 1.1 23.7 21.4 37 17.3 11.1 41.2 15.2 56.6 16.8l-12.9 12.9c-18.2 18-35.5 35.5-47.7 47.7-17.6 17.6 10.7 45.8 28.4 28.6l47.7-47.9c18.2 18.2 35.7 35.7 47.7 47.9 17.6 17.2 46-10.7 28.6-28.6l-47.7-47.7-13-12.9c15.5-1.6 39.1-5.9 56.2-16.8 20.4-13.3 29.3-21 21.5-37z"],opencart:[640,512,[],"f23d","M423.3 440.7c0 25.3-20.3 45.6-45.6 45.6s-45.8-20.3-45.8-45.6 20.6-45.8 45.8-45.8c25.4 0 45.6 20.5 45.6 45.8zm-253.9-45.8c-25.3 0-45.6 20.6-45.6 45.8s20.3 45.6 45.6 45.6 45.8-20.3 45.8-45.6-20.5-45.8-45.8-45.8zm291.7-270C158.9 124.9 81.9 112.1 0 25.7c34.4 51.7 53.3 148.9 373.1 144.2 333.3-5 130 86.1 70.8 188.9 186.7-166.7 319.4-233.9 17.2-233.9z"],openid:[448,512,[],"f19b","M271.5 432l-68 32C88.5 453.7 0 392.5 0 318.2c0-71.5 82.5-131 191.7-144.3v43c-71.5 12.5-124 53-124 101.3 0 51 58.5 93.3 135.7 103v-340l68-33.2v384zM448 291l-131.3-28.5 36.8-20.7c-19.5-11.5-43.5-20-70-24.8v-43c46.2 5.5 87.7 19.5 120.3 39.3l35-19.8L448 291z"],opera:[496,512,[],"f26a","M313.9 32.7c-170.2 0-252.6 223.8-147.5 355.1 36.5 45.4 88.6 75.6 147.5 75.6 36.3 0 70.3-11.1 99.4-30.4-43.8 39.2-101.9 63-165.3 63-3.9 0-8 0-11.9-.3C104.6 489.6 0 381.1 0 248 0 111 111 0 248 0h.8c63.1.3 120.7 24.1 164.4 63.1-29-19.4-63.1-30.4-99.3-30.4zm101.8 397.7c-40.9 24.7-90.7 23.6-132-5.8 56.2-20.5 97.7-91.6 97.7-176.6 0-84.7-41.2-155.8-97.4-176.6 41.8-29.2 91.2-30.3 132.9-5 105.9 98.7 105.5 265.7-1.2 364z"],"optin-monster":[576,512,[],"f23c","M550.671 450.303c0 11.62-15.673 19.457-32.158 14.863-12.16-3.243-31.346-17.565-36.211-27.294-5.674-11.62 4.054-32.698 18.916-30.806 15.674 1.621 49.453 25.401 49.453 43.237zM372.86 75.223c-3.783-72.151-100.796-79.718-125.928-23.51 44.588-24.321 90.257-15.673 125.928 23.51zM74.795 407.066c-15.673 1.621-49.452 25.401-49.452 43.237 0 11.62 15.673 19.457 32.157 14.863 12.16-3.243 31.076-17.565 35.94-27.294 5.946-11.62-3.782-32.698-18.645-30.806zm497.765 14.322c1.081 3.513 1.892 7.026 1.892 10.809.81 31.616-44.317 64.045-73.503 65.125-17.295.81-34.59-8.377-42.696-23.51-113.497 4.053-226.994 4.864-340.22 0-8.377 15.133-25.672 24.05-42.967 23.51-28.915-1.081-74.043-33.509-73.503-65.125.27-3.783.811-7.296 1.892-10.809-5.566-9.463-4.845-15.282 5.405-11.62 3.243-5.134 7.026-9.458 11.08-13.782-2.57-10.917 1.27-14.094 11.079-9.188 4.594-3.243 9.998-6.485 15.944-9.188 0-15.757 11.839-11.131 17.295-5.675 12.467-1.78 20.129.709 26.753 5.675v-19.726c-12.987 0-40.641-11.375-45.94-36.212-4.974-20.725 2.607-38.075 25.132-47.56.81-5.945 8.107-14.052 14.862-15.944 7.567-1.892 12.431 4.594 14.052 10.269 7.425 0 17.757 1.465 21.078 8.107 5.405-.541 11.079-1.352 16.484-1.892-2.432-1.892-5.134-3.513-8.107-4.594-5.134-8.917-13.782-11.079-24.591-11.62 0-.81 0-1.621.27-2.702-19.727-.541-44.048-5.675-54.857-17.835-21.321-23.638-15.935-83.577 12.16-103.498 8.377-5.675 21.618-.811 22.699 9.728 2.425 20.598.399 26.833 26.212 25.942 8.107-7.836 16.755-14.592 26.483-19.997-14.862-1.352-28.914 1.621-43.778 3.783 12.752-12.48 23.953-25.442 56.748-42.427 23.511-11.89 49.993-20.808 76.205-23.239-18.646-7.837-39.993-11.891-59.721-16.484 76.475-16.214 174.569-22.159 244.289 37.562 18.105 15.403 32.427 36.211 42.696 59.992 39.799 4.853 36.47-5.581 38.643-25.132 1.081-10.269 14.322-15.403 22.699-9.458 14.862 10.539 22.159 30.806 24.59 48.101 2.162 17.835.27 41.345-12.43 55.127-10.809 12.16-34.32 17.565-53.776 18.105v2.703c-11.08.27-20.268 2.432-25.673 11.62-2.972 1.081-5.674 2.703-8.377 4.594 5.675.54 11.35 1.351 16.755 1.891 1.869-5.619 12.535-8.377 21.077-8.377 1.621-5.405 6.756-11.89 14.052-10.269s14.052 9.998 14.863 15.944c10.809 4.324 22.159 12.16 25.131 25.672 1.892 8.107 1.621 15.133.27 21.888-5.726 25.262-33.361 36.212-45.939 36.212 0 6.756 0 13.241-.27 19.726 8.01-6.006 16.367-7.158 26.752-5.675 5.919-5.919 17.565-9.41 17.565 5.675 5.675 2.703 11.349 5.945 15.944 9.188 10.1-5.051 13.669-.539 10.809 9.188 4.053 4.323 8.107 8.917 11.079 13.782 10.136-3.62 11.021 2.078 5.409 11.62zm-73.773-254.016c17.295 6.756 26.212 22.159 30.265 35.67 1.081-10.539-2.702-39.453-13.782-51.073-7.296-7.296-14.052-5.134-14.052.81.001 6.216-1.35 11.62-2.431 14.593zm-18.646 12.43c12.971 15.673 17.024 41.615 12.7 62.963 10.809-2.162 20.537-6.215 26.212-12.16 1.892-2.162 3.783-4.864 4.864-7.566-1.081-21.348-10.269-42.697-29.725-48.912-3.242 3.243-9.187 4.864-14.051 5.675zm-21.889.811c7.567 20.537 12.431 42.696 14.322 64.585 3.513 0 7.567-.27 11.62-.811 5.945-24.321-.27-51.614-14.052-63.504-3.783 0-8.107 0-11.89-.27zM77.768 167.372c-1.081-2.973-2.432-8.377-2.432-14.593 0-5.945-7.026-8.107-14.052-.81-11.35 11.62-14.863 40.534-13.782 51.073 4.053-13.512 12.971-28.915 30.266-35.67zm5.675 75.394c-4.324-21.348-.27-47.291 12.701-62.963-4.865-.811-10.809-2.432-14.052-5.675-19.457 6.215-28.375 27.563-29.726 48.912 1.351 2.702 2.972 5.404 4.864 7.566 5.675 6.215 15.403 9.998 26.213 12.16zm41.345-61.073c-5.134 1.081-9.998 2.973-14.862 4.865l-12.16 5.134v-.27c-7.296 14.052-9.999 34.319-5.405 52.965 4.594.541 8.647.811 12.7.811 2.432-22.159 9.188-43.778 19.727-63.505zm88.095-23.239c0 42.155 34.319 76.205 76.205 76.205s76.205-34.05 76.205-76.205c0-41.886-34.319-75.935-76.205-75.935s-76.205 34.049-76.205 75.935zm152.41 97.283c9.969 50.608 3.299 64.692 16.484 58.099 15.944-8.107 22.699-39.183 22.97-57.019-12.971-.81-26.213-.81-39.454-1.08zm-71.611-.541v-.27c-.27 5.134.27 38.103 4.324 41.075 11.079 5.405 39.453 4.594 51.073 1.081 5.405-1.621 2.432-37.022 1.621-41.886-18.916-.27-38.102-.27-57.018 0zm-14.053 0v-.27c-19.456.27-38.642.27-57.829.811-1.892 9.187-4.594 48.911 1.892 51.614 12.971 5.675 41.616 5.134 54.586 1.621 4.595-2.432 2.433-45.399 1.351-53.776zm-85.662 57.56c5.405 2.432 8.647 2.432 9.728-4.324 1.892-8.647 2.432-36.752 4.865-52.155-12.16.27-24.591.811-36.752 1.621-5.405 19.727.27 45.129 22.159 54.858zm-65.666-11.08c43.778 47.02 92.689 85.663 155.923 106.47 67.558-19.186 115.659-59.991 163.219-107.011-11.095-4.315-7.715-10.363-7.296-11.62-8.918-.81-17.835-1.892-26.483-2.702-9.458 32.968-35.94 52.965-46.75 31.616-2.702-5.134-3.513-11.62-4.594-16.754-3.783 8.377-13.242 8.107-24.591 8.918-13.241 1.081-31.617 1.351-44.048-2.972-2.972 12.971-11.079 12.971-26.752 14.322-14.052 1.352-48.642 4.054-54.857-10.809-1.081 28.644-35.13 9.998-45.129-7.026-3.243-5.675-5.405-11.35-7.026-17.565-7.837.81-15.673 1.621-23.511 2.702 2.443 3.663 1.549 9.052-8.105 12.431zM115.6 453.545c-5.674-23.239-18.646-49.722-33.508-54.046-22.429-6.756-68.909 23.51-66.207 54.586 12.701 19.457 39.994 35.67 59.181 36.481 17.835.81 35.94-11.08 39.724-28.914.539-2.432.81-5.134.81-8.107zm7.296-5.944c33.509-19.457 69.179-35.671 105.931-47.02-38.643-20.537-68.098-47.831-97.283-77.016-2.162 1.352-5.134 2.432-7.836 3.513-1.637 4.91 8.718 5.33 5.405 12.431-2.162 4.054-8.648 7.567-15.133 9.188-2.161 2.702-5.134 4.864-7.836 6.485h-.27c-.27 13.511-.27 27.024.27 40.535 8.939 15.964 15.426 33.314 16.752 51.884zm320.764 12.7c-36.752-21.348-74.044-41.345-115.659-52.965-13.782 6.215-27.833 11.349-42.155 15.403-2.162.811-2.162.811-4.324 0-11.89-3.783-23.239-8.107-34.859-13.241-40.265 11.62-77.286 29.185-112.416 50.803h-.27v.27c.27 0 .27 0 .27-.27 103.227 4.054 206.455 3.513 309.413 0zm27.023-64.045l-.27.27c.541-13.782.811-27.563.811-41.345-2.973-1.621-5.675-4.054-8.107-6.756-6.485-1.351-12.971-5.134-15.133-8.918-1.892-4.053 1.351-7.566 5.945-10.269-.27-.541-.541-1.621-.541-2.432-2.972-.811-5.405-1.892-7.567-3.243-31.616 29.455-65.396 56.749-103.498 76.746 38.914 11.62 75.935 28.104 111.875 47.561 1.05-14.692 7.231-35.749 16.485-51.614zm23.24 3.244c-14.593 4.323-27.834 30.806-33.509 54.046 0 23.826 21.278 37.897 40.534 37.022 19.186-.811 46.48-17.024 59.181-36.481 2.973-31.077-43.507-61.344-66.206-54.587zM290.709 134.133c.045 0 .089.003.134.003.046 0 .09-.003.136-.003h-.27zm0 96.743c28.645 0 51.884-21.618 51.884-48.371 0-36.092-40.507-58.079-72.151-44.318 9.458 2.972 16.484 11.62 16.484 21.618 0 23.257-33.291 31.955-46.48 11.35-7.297 34.067 19.368 59.721 50.263 59.721zM68.039 474.083c.54 6.486 12.16 12.701 21.618 9.458 6.756-2.703 14.593-10.539 17.295-16.214 2.973-7.026-1.081-19.997-9.728-18.375-8.917 1.621-29.725 16.754-29.185 25.131zm410.75-25.131c-8.377-1.621-12.431 11.349-9.458 18.375 2.432 5.675 10.269 13.511 17.295 16.214 9.187 3.243 21.078-2.972 21.348-9.458.811-8.377-20.267-23.51-29.185-25.131z"],osi:[495,512,[],"f41a","M0 259.2C2.3 123.4 97.4 26.8 213.8 11.1c138.8-18.6 255.6 75.8 278 201.1 21.3 118.8-44 230-151.6 274-9.3 3.8-14.4 1.7-18-7.7-17.8-46.3-35.6-92.7-53.4-139-3.1-8.1-1-13.2 7-16.8 24.2-11 39.3-29.4 43.3-55.8 6.4-42.4-24.5-78.7-64.5-82.2-39-3.4-71.8 23.7-77.5 59.7-5.2 33 11.1 63.7 41.9 77.7 9.6 4.4 11.5 8.6 7.8 18.4-17.9 46.6-35.8 93.2-53.7 139.9-2.6 6.9-8.3 9.3-15.5 6.5-52.6-20.3-101.4-61-130.8-119C1.9 318.7 1.6 280.2 0 259.2zm20.9-1.9c.4 6.6.6 14.3 1.3 22.1 6.3 71.9 49.6 143.5 131 183.1 3.2 1.5 4.4.8 5.6-2.3 14.9-39.1 29.9-78.2 45-117.3 1.3-3.3.6-4.8-2.4-6.7-31.6-19.9-47.3-48.5-45.6-86 1-21.6 9.3-40.5 23.8-56.3 30-32.7 77-39.8 115.5-17.6 31.9 18.4 49.5 53.8 45.2 90.4-3.6 30.6-19.3 53.9-45.7 69.8-2.7 1.6-3.5 2.9-2.3 6 15.2 39.2 30.2 78.4 45.2 117.7 1.2 3.1 2.4 3.8 5.6 2.3 35.5-16.6 65.2-40.3 88.1-72 34.8-48.2 49.1-101.9 42.3-161C459.8 112 354.1 14.7 218 31.5 111.9 44.5 22.7 134 20.9 257.3z"],page4:[496,512,[],"f3d7","M248 504C111 504 0 393 0 256S111 8 248 8c20.9 0 41.3 2.6 60.7 7.5L42.3 392H248v112zm0-143.6V146.8L98.6 360.4H248zm96 31.6v92.7c45.7-19.2 84.5-51.7 111.4-92.7H344zm57.4-138.2l-21.2 8.4 21.2 8.3v-16.7zm-20.3 54.5c-6.7 0-8 6.3-8 12.9v7.7h16.2v-10c0-5.9-2.3-10.6-8.2-10.6zM496 256c0 37.3-8.2 72.7-23 104.4H344V27.3C433.3 64.8 496 153.1 496 256zM360.4 143.6h68.2V96h-13.9v32.6h-13.9V99h-13.9v29.6h-12.7V96h-13.9v47.6zm68.1 185.3H402v-11c0-15.4-5.6-25.2-20.9-25.2-15.4 0-20.7 10.6-20.7 25.9v25.3h68.2v-15zm0-103l-68.2 29.7V268l68.2 29.5v-16.6l-14.4-5.7v-26.5l14.4-5.9v-16.9zm-4.8-68.5h-35.6V184H402v-12.2h11c8.6 15.8 1.3 35.3-18.6 35.3-22.5 0-28.3-25.3-15.5-37.7l-11.6-10.6c-16.2 17.5-12.2 63.9 27.1 63.9 34 0 44.7-35.9 29.3-65.3z"],pagelines:[384,512,[],"f18c","M384 312.7c-55.1 136.7-187.1 54-187.1 54-40.5 81.8-107.4 134.4-184.6 134.7-16.1 0-16.6-24.4 0-24.4 64.4-.3 120.5-42.7 157.2-110.1-41.1 15.9-118.6 27.9-161.6-82.2 109-44.9 159.1 11.2 178.3 45.5 9.9-24.4 17-50.9 21.6-79.7 0 0-139.7 21.9-149.5-98.1 119.1-47.9 152.6 76.7 152.6 76.7 1.6-16.7 3.3-52.6 3.3-53.4 0 0-106.3-73.7-38.1-165.2 124.6 43 61.4 162.4 61.4 162.4.5 1.6.5 23.8 0 33.4 0 0 45.2-89 136.4-57.5-4.2 134-141.9 106.4-141.9 106.4-4.4 27.4-11.2 53.4-20 77.5 0 0 83-91.8 172-20z"],palfed:[560,512,[],"f3d8","M376.9 194.1c0-47.4-55.2-44.2-95.4-29.8-1.3 39.4-2.5 80.7-3 119.8.7 2.8 2.6 6.2 15.1 6.2 36.7-.1 83.3-42.9 83.3-96.2zm-194.5 72.2c.2 0 6.5-2.7 11.2-2.7 26.6 0 20.7 44.1-14.4 44.1-21.5 0-37.1-18.1-37.1-43 0-42 42.9-95.6 100.7-126.5 1-12.4 3-22 10.5-28.2 11.2-9 26.6-3.5 29.5 11.1 72.2-22.2 135.2 1 135.2 72 0 77.9-79.3 152.6-140.1 138.2-.1 39.4.9 74.4 2.7 100v.2c.2 3.4.6 12.5-5.3 19.1-9.6 10.6-33.4 10-36.4-22.3-4.1-44.4.2-206.1 1.4-242.5-21.5 15-58.5 50.3-58.5 75.9.1 2.4.3 3.9.6 4.6zM0 181.3s-.1 37.4 38.4 37.4h30l22.4 217.2s0 44.3 44.7 44.3h288.9s44.7-.4 44.7-44.3l22.4-217.2h30s38.4 1.2 38.4-37.4c0 0 .1-37.4-38.4-37.4h-30.1c-7.3-25.6-30.2-74.3-119.4-74.3h-28V50.5s-2.7-18.4-21.1-18.4h-85.8s-21.1 0-21.1 18.4v19.1h-28.1s-105 4.2-120.5 74.3h-29S0 142.7 0 181.3z"],patreon:[512,512,[],"f3d9","M489.6 200.2c0 92.5-75.2 167.7-167.7 167.7-92.7 0-168.2-75.2-168.2-167.7 0-92.7 75.5-168.2 168.2-168.2 92.5 0 167.7 75.4 167.7 168.2zM22.4 480h82.1V32H22.4v448z"],paypal:[384,512,[],"f1ed","M111.4 295.9c-3.5 19.2-17.4 108.7-21.5 134-.3 1.8-1 2.5-3 2.5H12.3c-7.6 0-13.1-6.6-12.1-13.9L58.8 46.6c1.5-9.6 10.1-16.9 20-16.9 152.3 0 165.1-3.7 204 11.4 60.1 23.3 65.6 79.5 44 140.3-21.5 62.6-72.5 89.5-140.1 90.3-43.4.7-69.5-7-75.3 24.2zM357.1 152c-1.8-1.3-2.5-1.8-3 1.3-2 11.4-5.1 22.5-8.8 33.6-39.9 113.8-150.5 103.9-204.5 103.9-6.1 0-10.1 3.3-10.9 9.4-22.6 140.4-27.1 169.7-27.1 169.7-1 7.1 3.5 12.9 10.6 12.9h63.5c8.6 0 15.7-6.3 17.4-14.9.7-5.4-1.1 6.1 14.4-91.3 4.6-22 14.3-19.7 29.3-19.7 71 0 126.4-28.8 142.9-112.3 6.5-34.8 4.6-71.4-23.8-92.6z"],periscope:[448,512,[],"f3da","M370 63.6C331.4 22.6 280.5 0 226.6 0 111.9 0 18.5 96.2 18.5 214.4c0 75.1 57.8 159.8 82.7 192.7C137.8 455.5 192.6 512 226.6 512c41.6 0 112.9-94.2 120.9-105 24.6-33.1 82-118.3 82-192.6 0-56.5-21.1-110.1-59.5-150.8zM226.6 493.9c-42.5 0-190-167.3-190-279.4 0-107.4 83.9-196.3 190-196.3 100.8 0 184.7 89 184.7 196.3.1 112.1-147.4 279.4-184.7 279.4zM338 206.8c0 59.1-51.1 109.7-110.8 109.7-100.6 0-150.7-108.2-92.9-181.8v.4c0 24.5 20.1 44.4 44.8 44.4 24.7 0 44.8-19.9 44.8-44.4 0-18.2-11.1-33.8-26.9-40.7 76.6-19.2 141 39.3 141 112.4z"],phabricator:[496,512,[],"f3db","M323 262.1l-.1-13s21.7-19.8 21.1-21.2l-9.5-20c-.6-1.4-29.5-.5-29.5-.5l-9.4-9.3s.2-28.5-1.2-29.1l-20.1-9.2c-1.4-.6-20.7 21-20.7 21l-13.1-.2s-20.5-21.4-21.9-20.8l-20 8.3c-1.4.5.2 28.9.2 28.9l-9.1 9.1s-29.2-.9-29.7.4l-8.1 19.8c-.6 1.4 21 21 21 21l.1 12.9s-21.7 19.8-21.1 21.2l9.5 20c.6 1.4 29.5.5 29.5.5l9.4 9.3s-.2 31.8 1.2 32.3l20.1 8.3c1.4.6 20.7-23.5 20.7-23.5l13.1.2s20.5 23.8 21.8 23.3l20-7.5c1.4-.6-.2-32.1-.2-32.1l9.1-9.1s29.2.9 29.7-.5l8.1-19.8c.7-1.1-20.9-20.7-20.9-20.7zm-44.9-8.7c.7 17.1-12.8 31.6-30.1 32.4-17.3.8-32.1-12.5-32.8-29.6-.7-17.1 12.8-31.6 30.1-32.3 17.3-.8 32.1 12.5 32.8 29.5zm201.2-37.9l-97-97-.1.1c-75.1-73.3-195.4-72.8-269.8 1.6-50.9 51-27.8 27.9-95.7 95.3-22.3 22.3-22.3 58.7 0 81 69.9 69.4 46.4 46 97.4 97l.1-.1c75.1 73.3 195.4 72.9 269.8-1.6 51-50.9 27.9-27.9 95.3-95.3 22.3-22.3 22.3-58.7 0-81zM140.4 363.8c-59.6-59.5-59.6-156 0-215.5 59.5-59.6 156-59.5 215.6 0 59.5 59.5 59.6 156 0 215.6-59.6 59.5-156 59.4-215.6-.1z"],"phoenix-framework":[640,512,[],"f3dc","M213.2 339.2c3.8-.1 22.9-1.4 25.6-2.2-2.4-2.7-43.6-1-68.1-49.7-4.3-8.7-7.5-17.6-6.4-27.6 2.9-25.5 32.9-30 52.1-18.5 36 21.6 63.4 91.5 113.8 97.6 37.1 4.5 84.7-17 108.3-45.4-.6-.1-.8-.2-1-.1-.4.1-.8.2-1.1.3-33.4 12.1-94.4 9.7-134.8-14.8-37.7-22.8-53.2-58.8-51.9-74.7 1.8-21.4 22.9-23.2 36-19.6 14.4 4 24.4 17.6 39 27.4 15.6 10.4 33 13.7 51.3 10.3 14.9-2.7 34.4-12.3 36.5-14.5-1.1-.1-1.8-.1-2.5-.2-6.2-.6-12.4-.8-18.6-1.7C280.1 189.3 262.5 42 138.7 32.5c-44.4-3.4-99.6 8.1-136.5 35-.8.6-1.5 1.2-2.2 1.8.1.2.1.3.2.5.8-.1 1.6-.1 2.4-.2 6.3-1 12.5-.8 18.8.3 23.9 4.3 47.8 23.1 56 76.6 5.3 34.3-.7 50.9 8 86.2 18.9 77.2 91 107.8 127.8 106.5zM75.4 59.5c-.9-1-.9-1.2-1.3-2 12.1-2.6 24.3-4.1 36.7-4.8-1.1 14.7-22.3 21.4-35.4 6.8zm197.2 350.9c-42.9 1.2-92.1-26.8-123.7-61.5-4.6-5-16.8-20.3-18.6-23.4l.4-.4c6.6 4.1 25.7 18.7 54.9 27.1 24.2 7 48.1 6.3 71.7-3.3 22.7-9.3 41-.5 43.1 2.9-18.5 3.8-20.1 4.4-24.1 7.9-5.1 4.4-4.6 11.7 7 17.2 26.2 12.4 63-2.8 97.3 25.4 2.4 2 8.1 7.8 10.1 10.7-.1.2-.3.3-.4.5-4.8-1.5-16.5-7.5-40.2-9.3-24.7-2-46.3 5.4-77.5 6.2zm175-252.2c16.4-5.2 41.4-13.4 66.6-3.3 16.1 6.5 26.2 18.7 32.1 34.7 3.5 9.4 5.1 19.7 5.1 28.8-.2 0-.4 0-.6.1-.2-.4-.4-.9-.5-1.3-5-22-29.9-43.8-67.7-29.9-50.2 18.6-130.5 9.7-177.2-48-.7-.9-2.4-1.7-1.3-3.2.1-.2 2.1.6 3 1.3 18.1 13.5 38.3 21.9 60.4 26.2 30.6 5.9 54.7 2.6 80.1-5.4zm102.8 117.6c-32.4.2-33.8 50.2-103.7 64.4-18.3 3.7-38.7 4.6-45 4.2v-.4c2.8-1.5 14.7-2.6 29.7-16.6 7.9-7.3 15.3-15.2 22.8-22.9 19.6-20.3 41.5-42.3 82-39 23.1 1.8 29.3 8.2 36.2 12.7.3.2.4.5.7.9-.5 0-.7.1-.9 0-7-2.7-14.3-3.3-21.8-3.3zm-12.3-24.2c-.1.2-.1.4-.2.6-29-4.4-48.1-7.9-68.6 4-17 9.9-31.5 20.6-62.1 24.4-27.1 3.4-45.2 2.4-66.2-8-.3-.2-.6-.4-1-.6 0-.2.1-.3.1-.5 24.9 3.8 36.5 5.2 55.6-5.9 22.4-12.9 40.2-26.7 71.4-31 29.6-3.9 51.3 2.7 71 17zM269 91.9c-.6-.6-1.1-1.2-2.1-2.3 7.6 0 29.7-1.2 53.4 8.4 19.7 8 32.3 21.1 50.3 33 11.1 7.3 23.5 9.3 36.5 8.1 4.3-.4 8.5-1.2 12.8-1.7.4-.1.9 0 1.5.3-.6.4-1.2.9-1.8 1.2-8.1 4-16.7 6.3-25.6 7.2-26.1 2.6-50.4-3.7-73.5-15.4-19.4-10-36.5-23-51.5-38.8zm371.8 238.7c-3.5 3.1-22.7 11.6-42.8 5.3-12.3-3.9-19.5-14.9-31.6-24.1-10-7.6-20.9-7.9-28.2-8.4.6-.8.9-1.2 1.2-1.4 14.8-9.2 30.5-12.2 47.4-6.5 12.5 4.2 19.3 13.5 30.4 24.2 10.8 10.4 21 9.9 23.2 10.5.1-.1.2.1.4.4zM428 467.8c2.2 1.2 1.6 1.5 1.5 2-18.5-1.4-33.9-7.6-46.8-22.2-21.8-24.7-41.8-27.9-48.7-29.7.5-.2.8-.4 1.1-.4 13.1.1 26.2.7 39 3.9 25.3 6.4 35 25.4 41.6 35.4 3.2 4.7 7.4 8.3 12.3 11z"],"pied-piper":[640,512,[],"f2ae","M640 24.9c-80.8 53.6-89.4 92.5-96.4 104.4-6.7 12.2-11.7 60.3-23.3 83.6-11.7 23.6-54.2 42.2-66.1 50-11.7 7.8-28.3 38.1-41.9 64.2-108.1-4.4-167.4 38.8-259.2 93.6 29.4-9.7 43.3-16.7 43.3-16.7 94.2-36 139.3-68.3 281.1-49.2 1.1 0 1.9.6 2.8.8 3.9 2.2 5.3 6.9 3.1 10.8l-53.9 95.8c-2.5 4.7-7.8 7.2-13.1 6.1-126.8-23.8-226.9 17.3-318.9 18.6C24.1 488 0 453.4 0 451.8c0-1.1.6-1.7 1.7-1.7 0 0 38.3 0 103.1-15.3C178.4 294.5 244 245.4 315.4 245.4c0 0 71.7 0 90.6 61.9 22.8-39.7 28.3-49.2 28.3-49.2 5.3-9.4 35-77.2 86.4-141.4 51.5-64 90.4-79.9 119.3-91.8z"],"pied-piper-alt":[576,512,[],"f1a8","M242 187c6.3-11.8 13.2-17 25.9-21.8 27.3-10.3 40.2-30.5 58.9-51.1 11.9 8.4 12 24.6 31.6 23v21.8l6.3.3c37.4-14.4 74.7-30.2 106.6-54.6 48.3-36.8 52.9-50 81.3-100l2-2.6c-.6 14.1-6.3 27.3-12.4 39.9-30.5 63.8-78.7 100.3-146.8 116.7-12.4 2.9-26.4 3.2-37.6 8.9 1.4 9.8 13.2 18.1 13.2 23 0 3.4-5.5 7.2-7.5 8.6-11.2-12.9-16.1-19.3-22.7-22.1-7.6-3.5-63.9-6.4-98.8 10zm137.9 256.9c-19 0-64.1 9.5-79.9 19.8l6.9 45.1c35.7 6.1 70.1 3.6 106-9.8-4.8-10-23.5-55.1-33-55.1zM244 246c-3.2-2-6.3-2.9-10.1-2.9-6.6 0-12.6 3.2-19.3 3.7l1.7 4.9L244 246zm-12.6 31.8l24.1 61.2 21-13.8-31.3-50.9-13.8 3.5zM555.5 0l-.6 1.1-.3.9.6-.6.3-1.4zm-59.2 382.1c-33.9-56.9-75.3-118.4-150-115.5l-.3-6c-1.1-13.5 32.8 3.2 35.1-31l-14.4 7.2c-19.8-45.7-8.6-54.3-65.5-54.3-14.7 0-26.7 1.7-41.4 4.6 2.9 18.6 2.2 36.7-10.9 50.3l19.5 5.5c-1.7 3.2-2.9 6.3-2.9 9.8 0 21 42.8 2.9 42.8 33.6 0 18.4-36.8 60.1-54.9 60.1-8 0-53.7-50-53.4-60.1l.3-4.6 52.3-11.5c13-2.6 12.3-22.7-2.9-22.7-3.7 0-43.1 9.2-49.4 10.6-2-5.2-7.5-14.1-13.8-14.1-3.2 0-6.3 3.2-9.5 4-9.2 2.6-31 2.9-21.5 20.1L15.9 298.5c-5.5 1.1-8.9 6.3-8.9 11.8 0 6 5.5 10.9 11.5 10.9 8 0 131.3-28.4 147.4-32.2 2.6 3.2 4.6 6.3 7.8 8.6 20.1 14.4 59.8 85.9 76.4 85.9 24.1 0 58-22.4 71.3-41.9 3.2-4.3 6.9-7.5 12.4-6.9.6 13.8-31.6 34.2-33 43.7-1.4 10.2-1 35.2-.3 41.1 26.7 8.1 52-3.6 77.9-2.9 4.3-21 10.6-41.9 9.8-63.5l-.3-9.5c-1.4-34.2-10.9-38.5-34.8-58.6-1.1-1.1-2.6-2.6-3.7-4 2.2-1.4 1.1-1 4.6-1.7 88.5 0 56.3 183.6 111.5 229.9 33.1-15 72.5-27.9 103.5-47.2-29-25.6-52.6-45.7-72.7-79.9zm-196.2 46v27.3l11.8-3.4-2.9-23.8h-8.9zm76.1 2.9c0-1.4-.6-3.2-.9-4.6-26.8 0-36.9 3.8-59.5 6.3l2 12.4c9-1.5 58.4-6.6 58.4-14.1z"],"pied-piper-pp":[448,512,[],"f1a7","M205.3 174.6c0 21.1-14.2 38.1-31.7 38.1-7.1 0-12.8-1.2-17.2-3.7v-68c4.4-2.7 10.1-4.2 17.2-4.2 17.5 0 31.7 16.9 31.7 37.8zm52.6 67c-7.1 0-12.8 1.5-17.2 4.2v68c4.4 2.5 10.1 3.7 17.2 3.7 17.4 0 31.7-16.9 31.7-37.8 0-21.1-14.3-38.1-31.7-38.1zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zM185 255.1c41 0 74.2-35.6 74.2-79.6 0-44-33.2-79.6-74.2-79.6-12 0-24.1 3.2-34.6 8.8h-45.7V311l51.8-10.1v-50.6c8.6 3.1 18.1 4.8 28.5 4.8zm158.4 25.3c0-44-33.2-79.6-73.9-79.6-3.2 0-6.4.2-9.6.7-3.7 12.5-10.1 23.8-19.2 33.4-13.8 15-32.2 23.8-51.8 24.8V416l51.8-10.1v-50.6c8.6 3.2 18.2 4.7 28.7 4.7 40.8 0 74-35.6 74-79.6z"],pinterest:[496,512,[],"f0d2","M496 256c0 137-111 248-248 248-25.6 0-50.2-3.9-73.4-11.1 10.1-16.5 25.2-43.5 30.8-65 3-11.6 15.4-59 15.4-59 8.1 15.4 31.7 28.5 56.8 28.5 74.8 0 128.7-68.8 128.7-154.3 0-81.9-66.9-143.2-152.9-143.2-107 0-163.9 71.8-163.9 150.1 0 36.4 19.4 81.7 50.3 96.1 4.7 2.2 7.2 1.2 8.3-3.3.8-3.4 5-20.3 6.9-28.1.6-2.5.3-4.7-1.7-7.1-10.1-12.5-18.3-35.3-18.3-56.6 0-54.7 41.4-107.6 112-107.6 60.9 0 103.6 41.5 103.6 100.9 0 67.1-33.9 113.6-78 113.6-24.3 0-42.6-20.1-36.7-44.8 7-29.5 20.5-61.3 20.5-82.6 0-19-10.2-34.9-31.4-34.9-24.9 0-44.9 25.7-44.9 60.2 0 22 7.4 36.8 7.4 36.8s-24.5 103.8-29 123.2c-5 21.4-3 51.6-.9 71.2C65.4 450.9 0 361.1 0 256 0 119 111 8 248 8s248 111 248 248z"],"pinterest-p":[384,512,[],"f231","M204 6.5C101.4 6.5 0 74.9 0 185.6 0 256 39.6 296 63.6 296c9.9 0 15.6-27.6 15.6-35.4 0-9.3-23.7-29.1-23.7-67.8 0-80.4 61.2-137.4 140.4-137.4 68.1 0 118.5 38.7 118.5 109.8 0 53.1-21.3 152.7-90.3 152.7-24.9 0-46.2-18-46.2-43.8 0-37.8 26.4-74.4 26.4-113.4 0-66.2-93.9-54.2-93.9 25.8 0 16.8 2.1 35.4 9.6 50.7-13.8 59.4-42 147.9-42 209.1 0 18.9 2.7 37.5 4.5 56.4 3.4 3.8 1.7 3.4 6.9 1.5 50.4-69 48.6-82.5 71.4-172.8 12.3 23.4 44.1 36 69.3 36 106.2 0 153.9-103.5 153.9-196.8C384 71.3 298.2 6.5 204 6.5z"],"pinterest-square":[448,512,[],"f0d3","M448 80v352c0 26.5-21.5 48-48 48H154.4c9.8-16.4 22.4-40 27.4-59.3 3-11.5 15.3-58.4 15.3-58.4 8 15.3 31.4 28.2 56.3 28.2 74.1 0 127.4-68.1 127.4-152.7 0-81.1-66.2-141.8-151.4-141.8-106 0-162.2 71.1-162.2 148.6 0 36 19.2 80.8 49.8 95.1 4.7 2.2 7.1 1.2 8.2-3.3.8-3.4 5-20.1 6.8-27.8.6-2.5.3-4.6-1.7-7-10.1-12.3-18.3-34.9-18.3-56 0-54.2 41-106.6 110.9-106.6 60.3 0 102.6 41.1 102.6 99.9 0 66.4-33.5 112.4-77.2 112.4-24.1 0-42.1-19.9-36.4-44.4 6.9-29.2 20.3-60.7 20.3-81.8 0-53-75.5-45.7-75.5 25 0 21.7 7.3 36.5 7.3 36.5-31.4 132.8-36.1 134.5-29.6 192.6l2.2.8H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48z"],playstation:[576,512,[],"f3df","M570.9 372.3c-11.3 14.2-38.8 24.3-38.8 24.3L327 470.2v-54.3l150.9-53.8c17.1-6.1 19.8-14.8 5.8-19.4-13.9-4.6-39.1-3.3-56.2 2.9L327 381.1v-56.4c23.2-7.8 47.1-13.6 75.7-16.8 40.9-4.5 90.9.6 130.2 15.5 44.2 14 49.2 34.7 38 48.9zm-224.4-92.5v-139c0-16.3-3-31.3-18.3-35.6-11.7-3.8-19 7.1-19 23.4v347.9l-93.8-29.8V32c39.9 7.4 98 24.9 129.2 35.4C424.1 94.7 451 128.7 451 205.2c0 74.5-46 102.8-104.5 74.6zM43.2 410.2c-45.4-12.8-53-39.5-32.3-54.8 19.1-14.2 51.7-24.9 51.7-24.9l134.5-47.8v54.5l-96.8 34.6c-17.1 6.1-19.7 14.8-5.8 19.4 13.9 4.6 39.1 3.3 56.2-2.9l46.4-16.9v48.8c-51.6 9.3-101.4 7.3-153.9-10z"],"product-hunt":[512,512,[],"f288","M326.3 218.8c0 20.5-16.7 37.2-37.2 37.2h-70.3v-74.4h70.3c20.5 0 37.2 16.7 37.2 37.2zM504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-128.1-37.2c0-47.9-38.9-86.8-86.8-86.8H169.2v248h49.6v-74.4h70.3c47.9 0 86.8-38.9 86.8-86.8z"],pushed:[432,512,[],"f3e1","M407 111.9l-98.5-9 14-33.4c10.4-23.5-10.8-40.4-28.7-37L22.5 76.9c-15.1 2.7-26 18.3-21.4 36.6l105.1 348.3c6.5 21.3 36.7 24.2 47.7 7l35.3-80.8 235.2-231.3c16.4-16.8 4.3-42.9-17.4-44.8zM297.6 53.6c5.1-.7 7.5 2.5 5.2 7.4L286 100.9 108.6 84.6l189-31zM22.7 107.9c-3.1-5.1 1-10 6.1-9.1l248.7 22.7-96.9 230.7L22.7 107.9zM136 456.4c-2.6 4-7.9 3.1-9.4-1.2L43.5 179.7l127.7 197.6c-7 15-35.2 79.1-35.2 79.1zm272.8-314.5L210.1 337.3l89.7-213.7 106.4 9.7c4 1.1 5.7 5.3 2.6 8.6z"],python:[448,512,[],"f3e2","M167.8 36.4c-45.2 8-53.4 24.7-53.4 55.6v40.7h106.9v13.6h-147c-31.1 0-58.3 18.7-66.8 54.2-9.8 40.7-10.2 66.1 0 108.6 7.6 31.6 25.7 54.2 56.8 54.2H101v-48.8c0-35.3 30.5-66.4 66.8-66.4h106.8c29.7 0 53.4-24.5 53.4-54.3V91.9c0-29-24.4-50.7-53.4-55.6-35.8-5.9-74.7-5.6-106.8.1zm-6.7 28.4c11 0 20.1 9.2 20.1 20.4s-9 20.3-20.1 20.3c-11.1 0-20.1-9.1-20.1-20.3.1-11.3 9-20.4 20.1-20.4zm185.2 81.4v47.5c0 36.8-31.2 67.8-66.8 67.8H172.7c-29.2 0-53.4 25-53.4 54.3v101.8c0 29 25.2 46 53.4 54.3 33.8 9.9 66.3 11.7 106.8 0 26.9-7.8 53.4-23.5 53.4-54.3v-40.7H226.2v-13.6h160.2c31.1 0 42.6-21.7 53.4-54.2 11.2-33.5 10.7-65.7 0-108.6-7.7-30.9-22.3-54.2-53.4-54.2h-40.1zM286.2 404c11.1 0 20.1 9.1 20.1 20.3 0 11.3-9 20.4-20.1 20.4-11 0-20.1-9.2-20.1-20.4.1-11.3 9.1-20.3 20.1-20.3z"],qq:[448,512,[],"f1d6","M433.754 420.445c-11.526 1.393-44.86-52.741-44.86-52.741 0 31.345-16.136 72.247-51.051 101.786 16.842 5.192 54.843 19.167 45.803 34.421-7.316 12.343-125.51 7.881-159.632 4.037-34.122 3.844-152.316 8.306-159.632-4.037-9.045-15.25 28.918-29.214 45.783-34.415-34.92-29.539-51.059-70.445-51.059-101.792 0 0-33.334 54.134-44.859 52.741-5.37-.65-12.424-29.644 9.347-99.704 10.261-33.024 21.995-60.478 40.144-105.779C60.683 98.063 108.982.006 224 0c113.737.006 163.156 96.133 160.264 214.963 18.118 45.223 29.912 72.85 40.144 105.778 21.768 70.06 14.716 99.053 9.346 99.704z"],quora:[448,512,[],"f2c4","M440.5 386.7h-29.3c-1.5 13.5-10.5 30.8-33 30.8-20.5 0-35.3-14.2-49.5-35.8 44.2-34.2 74.7-87.5 74.7-153C403.5 111.2 306.8 32 205 32 105.3 32 7.3 111.7 7.3 228.7c0 134.1 131.3 221.6 249 189C276 451.3 302 480 351.5 480c81.8 0 90.8-75.3 89-93.3zM297 329.2C277.5 300 253.3 277 205.5 277c-30.5 0-54.3 10-69 22.8l12.2 24.3c6.2-3 13-4 19.8-4 35.5 0 53.7 30.8 69.2 61.3-10 3-20.7 4.2-32.7 4.2-75 0-107.5-53-107.5-156.7C97.5 124.5 130 71 205 71c76.2 0 108.7 53.5 108.7 157.7.1 41.8-5.4 75.6-16.7 100.5z"],ravelry:[512,512,[],"f2d9","M407.4 61.5C331.6 22.1 257.8 31 182.9 66c-11.3 5.2-15.5 10.6-19.9 19-10.3 19.2-16.2 37.4-19.9 52.7-21.2 25.6-36.4 56.1-43.3 89.9-10.6 18-20.9 41.4-23.1 71.4 0 0-.7 7.6-.5 7.9-35.3-4.6-76.2-27-76.2-27 9.1 14.5 61.3 32.3 76.3 37.9 0 0 1.7 98 64.5 131.2-11.3-17.2-13.3-20.2-13.3-20.2S94.8 369 100.4 324.7c.7 0 1.5.2 2.2.2 23.9 87.4 103.2 151.4 196.9 151.4 6.2 0 12.1-.2 18-.7 14 1.5 27.6.5 40.1-3.9 6.9-2.2 13.8-6.4 20.2-10.8 70.2-39.1 100.9-82 123.1-147.7 5.4-16 8.1-35.5 9.8-52.2 8.7-82.3-30.6-161.6-103.3-199.5zM138.8 163.2s-1.2 12.3-.7 19.7c-3.4 2.5-10.1 8.1-18.2 16.7 5.2-12.8 11.3-25.1 18.9-36.4zm-31.2 121.9c4.4-17.2 13.3-39.1 29.8-55.1 0 0 1.7 48 15.8 90.1l-41.4-6.9c-2.2-9.2-3.5-18.5-4.2-28.1zm7.9 42.8c14.8 3.2 34 7.6 43.1 9.1 27.3 76.8 108.3 124.3 108.3 124.3 1 .5 1.7.7 2.7 1-73.1-11.6-132.7-64.7-154.1-134.4zM386 444.1c-14.5 4.7-36.2 8.4-64.7 3.7 0 0-91.1-23.1-127.5-107.8 38.2.7 52.4-.2 78-3.9 39.4-5.7 79-16.2 115-33 11.8-5.4 11.1-19.4 9.6-29.8-2-12.8-11.1-12.1-21.4-4.7 0 0-82 58.6-189.8 53.7-18.7-32-26.8-110.8-26.8-110.8 41.4-35.2 83.2-59.6 168.4-52.4.2-6.4 3-27.1-20.4-28.1 0 0-93.5-11.1-146 33.5 2.5-16.5 5.9-29.3 11.1-39.4 34.2-30.8 79-49.5 128.3-49.5 106.4 0 193 87.1 193 194.5-.2 76-43.8 142-106.8 174z"],react:[512,512,[],"f41b","M418.2 177.2c-5.4-1.8-10.8-3.5-16.2-5.1.9-3.7 1.7-7.4 2.5-11.1 12.3-59.6 4.2-107.5-23.1-123.3-26.3-15.1-69.2.6-112.6 38.4-4.3 3.7-8.5 7.6-12.5 11.5-2.7-2.6-5.5-5.2-8.3-7.7-45.5-40.4-91.1-57.4-118.4-41.5-26.2 15.2-34 60.3-23 116.7 1.1 5.6 2.3 11.1 3.7 16.7-6.4 1.8-12.7 3.8-18.6 5.9C38.3 196.2 0 225.4 0 255.6c0 31.2 40.8 62.5 96.3 81.5 4.5 1.5 9 3 13.6 4.3-1.5 6-2.8 11.9-4 18-10.5 55.5-2.3 99.5 23.9 114.6 27 15.6 72.4-.4 116.6-39.1 3.5-3.1 7-6.3 10.5-9.7 4.4 4.3 9 8.4 13.6 12.4 42.8 36.8 85.1 51.7 111.2 36.6 27-15.6 35.8-62.9 24.4-120.5-.9-4.4-1.9-8.9-3-13.5 3.2-.9 6.3-1.9 9.4-2.9 57.7-19.1 99.5-50 99.5-81.7 0-30.3-39.4-59.7-93.8-78.4zM282.9 92.3c37.2-32.4 71.9-45.1 87.7-36 16.9 9.7 23.4 48.9 12.8 100.4-.7 3.4-1.4 6.7-2.3 10-22.2-5-44.7-8.6-67.3-10.6-13-18.6-27.2-36.4-42.6-53.1 3.9-3.7 7.7-7.2 11.7-10.7zm-130 189.1c4.6 8.8 9.3 17.5 14.3 26.1 5.1 8.7 10.3 17.4 15.8 25.9-15.6-1.7-31.1-4.2-46.4-7.5 4.4-14.4 9.9-29.3 16.3-44.5zm0-50.6c-6.3-14.9-11.6-29.5-16-43.6 14.4-3.2 29.7-5.8 45.6-7.8-5.3 8.3-10.5 16.8-15.4 25.4-4.9 8.5-9.7 17.2-14.2 26zm11.4 25.3c6.6-13.8 13.8-27.3 21.4-40.6 7.6-13.3 15.8-26.2 24.4-38.9 15-1.1 30.3-1.7 45.9-1.7 15.6 0 31 .6 45.9 1.7 8.5 12.6 16.6 25.5 24.3 38.7 7.7 13.2 14.9 26.7 21.7 40.4-6.7 13.8-13.9 27.4-21.6 40.8-7.6 13.3-15.7 26.2-24.2 39-14.9 1.1-30.4 1.6-46.1 1.6-15.7 0-30.9-.5-45.6-1.4-8.7-12.7-16.9-25.7-24.6-39-7.7-13.3-14.8-26.8-21.5-40.6zm180.6 51.2c5.1-8.8 9.9-17.7 14.6-26.7 6.4 14.5 12 29.2 16.9 44.3-15.5 3.5-31.2 6.2-47 8 5.4-8.4 10.5-17 15.5-25.6zm14.4-76.5c-4.7-8.8-9.5-17.6-14.5-26.2-4.9-8.5-10-16.9-15.3-25.2 16.1 2 31.5 4.7 45.9 8-4.6 14.8-10 29.2-16.1 43.4zM256.2 118.3c10.5 11.4 20.4 23.4 29.6 35.8-19.8-.9-39.7-.9-59.5 0 9.8-12.9 19.9-24.9 29.9-35.8zM140.2 57c16.8-9.8 54.1 4.2 93.4 39 2.5 2.2 5 4.6 7.6 7-15.5 16.7-29.8 34.5-42.9 53.1-22.6 2-45 5.5-67.2 10.4-1.3-5.1-2.4-10.3-3.5-15.5-9.4-48.4-3.2-84.9 12.6-94zm-24.5 263.6c-4.2-1.2-8.3-2.5-12.4-3.9-21.3-6.7-45.5-17.3-63-31.2-10.1-7-16.9-17.8-18.8-29.9 0-18.3 31.6-41.7 77.2-57.6 5.7-2 11.5-3.8 17.3-5.5 6.8 21.7 15 43 24.5 63.6-9.6 20.9-17.9 42.5-24.8 64.5zm116.6 98c-16.5 15.1-35.6 27.1-56.4 35.3-11.1 5.3-23.9 5.8-35.3 1.3-15.9-9.2-22.5-44.5-13.5-92 1.1-5.6 2.3-11.2 3.7-16.7 22.4 4.8 45 8.1 67.9 9.8 13.2 18.7 27.7 36.6 43.2 53.4-3.2 3.1-6.4 6.1-9.6 8.9zm24.5-24.3c-10.2-11-20.4-23.2-30.3-36.3 9.6.4 19.5.6 29.5.6 10.3 0 20.4-.2 30.4-.7-9.2 12.7-19.1 24.8-29.6 36.4zm130.7 30c-.9 12.2-6.9 23.6-16.5 31.3-15.9 9.2-49.8-2.8-86.4-34.2-4.2-3.6-8.4-7.5-12.7-11.5 15.3-16.9 29.4-34.8 42.2-53.6 22.9-1.9 45.7-5.4 68.2-10.5 1 4.1 1.9 8.2 2.7 12.2 4.9 21.6 5.7 44.1 2.5 66.3zm18.2-107.5c-2.8.9-5.6 1.8-8.5 2.6-7-21.8-15.6-43.1-25.5-63.8 9.6-20.4 17.7-41.4 24.5-62.9 5.2 1.5 10.2 3.1 15 4.7 46.6 16 79.3 39.8 79.3 58 0 19.6-34.9 44.9-84.8 61.4zM256 210.2c25.3 0 45.8 20.5 45.8 45.8 0 25.3-20.5 45.8-45.8 45.8-25.3 0-45.8-20.5-45.8-45.8 0-25.3 20.5-45.8 45.8-45.8"],rebel:[512,512,[],"f1d0","M256.5 504C117.2 504 9 387.8 13.2 249.9 16 170.7 56.4 97.7 129.7 49.5c.3 0 1.9-.6 1.1.8-5.8 5.5-111.3 129.8-14.1 226.4 49.8 49.5 90 2.5 90 2.5 38.5-50.1-.6-125.9-.6-125.9-10-24.9-45.7-40.1-45.7-40.1l28.8-31.8c24.4 10.5 43.2 38.7 43.2 38.7.8-29.6-21.9-61.4-21.9-61.4L255.1 8l44.3 50.1c-20.5 28.8-21.9 62.6-21.9 62.6 13.8-23 43.5-39.3 43.5-39.3l28.5 31.8c-27.4 8.9-45.4 39.9-45.4 39.9-15.8 28.5-27.1 89.4.6 127.3 32.4 44.6 87.7-2.8 87.7-2.8 102.7-91.9-10.5-225-10.5-225-6.1-5.5.8-2.8.8-2.8 50.1 36.5 114.6 84.4 116.2 204.8C500.9 400.2 399 504 256.5 504z"],"red-river":[448,512,[],"f3e3","M353.2 32H94.8C42.4 32 0 74.4 0 126.8v258.4C0 437.6 42.4 480 94.8 480h258.4c52.4 0 94.8-42.4 94.8-94.8V126.8c0-52.4-42.4-94.8-94.8-94.8zM144.9 200.9v56.3c0 27-21.9 48.9-48.9 48.9V151.9c0-13.2 10.7-23.9 23.9-23.9h154.2c0 27-21.9 48.9-48.9 48.9h-56.3c-12.3-.6-24.6 11.6-24 24zm176.3 72h-56.3c-12.3-.6-24.6 11.6-24 24v56.3c0 27-21.9 48.9-48.9 48.9V247.9c0-13.2 10.7-23.9 23.9-23.9h154.2c0 27-21.9 48.9-48.9 48.9z"],reddit:[512,512,[],"f1a1","M201.5 305.5c-13.8 0-24.9-11.1-24.9-24.6 0-13.8 11.1-24.9 24.9-24.9 13.6 0 24.6 11.1 24.6 24.9 0 13.6-11.1 24.6-24.6 24.6zM504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-132.3-41.2c-9.4 0-17.7 3.9-23.8 10-22.4-15.5-52.6-25.5-86.1-26.6l17.4-78.3 55.4 12.5c0 13.6 11.1 24.6 24.6 24.6 13.8 0 24.9-11.3 24.9-24.9s-11.1-24.9-24.9-24.9c-9.7 0-18 5.8-22.1 13.8l-61.2-13.6c-3-.8-6.1 1.4-6.9 4.4l-19.1 86.4c-33.2 1.4-63.1 11.3-85.5 26.8-6.1-6.4-14.7-10.2-24.1-10.2-34.9 0-46.3 46.9-14.4 62.8-1.1 5-1.7 10.2-1.7 15.5 0 52.6 59.2 95.2 132 95.2 73.1 0 132.3-42.6 132.3-95.2 0-5.3-.6-10.8-1.9-15.8 31.3-16 19.8-62.5-14.9-62.5zM302.8 331c-18.2 18.2-76.1 17.9-93.6 0-2.2-2.2-6.1-2.2-8.3 0-2.5 2.5-2.5 6.4 0 8.6 22.8 22.8 87.3 22.8 110.2 0 2.5-2.2 2.5-6.1 0-8.6-2.2-2.2-6.1-2.2-8.3 0zm7.7-75c-13.6 0-24.6 11.1-24.6 24.9 0 13.6 11.1 24.6 24.6 24.6 13.8 0 24.9-11.1 24.9-24.6 0-13.8-11-24.9-24.9-24.9z"],"reddit-alien":[512,512,[],"f281","M440.3 203.5c-15 0-28.2 6.2-37.9 15.9-35.7-24.7-83.8-40.6-137.1-42.3L293 52.3l88.2 19.8c0 21.6 17.6 39.2 39.2 39.2 22 0 39.7-18.1 39.7-39.7s-17.6-39.7-39.7-39.7c-15.4 0-28.7 9.3-35.3 22l-97.4-21.6c-4.9-1.3-9.7 2.2-11 7.1L246.3 177c-52.9 2.2-100.5 18.1-136.3 42.8-9.7-10.1-23.4-16.3-38.4-16.3-55.6 0-73.8 74.6-22.9 100.1-1.8 7.9-2.6 16.3-2.6 24.7 0 83.8 94.4 151.7 210.3 151.7 116.4 0 210.8-67.9 210.8-151.7 0-8.4-.9-17.2-3.1-25.1 49.9-25.6 31.5-99.7-23.8-99.7zM129.4 308.9c0-22 17.6-39.7 39.7-39.7 21.6 0 39.2 17.6 39.2 39.7 0 21.6-17.6 39.2-39.2 39.2-22 .1-39.7-17.6-39.7-39.2zm214.3 93.5c-36.4 36.4-139.1 36.4-175.5 0-4-3.5-4-9.7 0-13.7 3.5-3.5 9.7-3.5 13.2 0 27.8 28.5 120 29 149 0 3.5-3.5 9.7-3.5 13.2 0 4.1 4 4.1 10.2.1 13.7zm-.8-54.2c-21.6 0-39.2-17.6-39.2-39.2 0-22 17.6-39.7 39.2-39.7 22 0 39.7 17.6 39.7 39.7-.1 21.5-17.7 39.2-39.7 39.2z"],"reddit-square":[448,512,[],"f1a2","M283.2 345.5c2.7 2.7 2.7 6.8 0 9.2-24.5 24.5-93.8 24.6-118.4 0-2.7-2.4-2.7-6.5 0-9.2 2.4-2.4 6.5-2.4 8.9 0 18.7 19.2 81 19.6 100.5 0 2.4-2.3 6.6-2.3 9 0zm-91.3-53.8c0-14.9-11.9-26.8-26.5-26.8-14.9 0-26.8 11.9-26.8 26.8 0 14.6 11.9 26.5 26.8 26.5 14.6 0 26.5-11.9 26.5-26.5zm90.7-26.8c-14.6 0-26.5 11.9-26.5 26.8 0 14.6 11.9 26.5 26.5 26.5 14.9 0 26.8-11.9 26.8-26.5 0-14.9-11.9-26.8-26.8-26.8zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-99.7 140.6c-10.1 0-19 4.2-25.6 10.7-24.1-16.7-56.5-27.4-92.5-28.6l18.7-84.2 59.5 13.4c0 14.6 11.9 26.5 26.5 26.5 14.9 0 26.8-12.2 26.8-26.8 0-14.6-11.9-26.8-26.8-26.8-10.4 0-19.3 6.2-23.8 14.9l-65.7-14.6c-3.3-.9-6.5 1.5-7.4 4.8l-20.5 92.8c-35.7 1.5-67.8 12.2-91.9 28.9-6.5-6.8-15.8-11-25.9-11-37.5 0-49.8 50.4-15.5 67.5-1.2 5.4-1.8 11-1.8 16.7 0 56.5 63.7 102.3 141.9 102.3 78.5 0 142.2-45.8 142.2-102.3 0-5.7-.6-11.6-2.1-17 33.6-17.2 21.2-67.2-16.1-67.2z"],rendact:[496,512,[],"f3e4","M248 8C111 8 0 119 0 256s111 248 248 248c18.6 0 36.7-2.1 54.1-5.9-5.6-7.4-10.8-14.4-15.9-21.3-12.4 2.1-25.2 3.3-38.3 3.3C124.3 480 24 379.7 24 256S124.3 32 248 32s224 100.3 224 224c0 71-33 134.2-84.5 175.3-25.9 18.8-39.1 21.4-83.5-44.2-78.7-112.9-48-71.1-73.7-108.3 72.8 8.9 228.5-72 168.6-168.6C314-26.8 15 93.8 59.7 226.4c3.2 9.8 14.4 38.6 45.6 38.6 2 0 2.6-.6 2-1.7-4.4-8.7-20.1-9.8-20.1-37.4 0-40.5 40.5-89.6 100.3-120 66.1-32.3 131.9-30.2 158.2 5.4 27.2 38.3-20.9 119.2-120.4 136.9 7.5-9.4 57-75.2 62.8-84 22.7-34.6 23.6-49 14-59.2-15.5-16.9-29.5-10.3-50.7-11.7-10.8-.9-113.7 181.2-136.4 216.9-5.9 9-21.2 34.1-21.2 50.9 0 21.3 2.8 51.4 20.6 51.4 10.6 0 8-18.7 8-26.6 0-12.9 27.4-49.4 74.8-104.6 20.4 36.1 57.7 114.3 130.2 209.7 98-33.1 168.5-125.8 168.5-235C496 119 385 8 248 8z"],renren:[512,512,[],"f18b","M214 169.1c0 110.4-61 205.4-147.6 247.4C30 373.2 8 317.7 8 256.6 8 133.9 97.1 32.2 214 12.5v156.6zM255 504c-42.9 0-83.3-11-118.5-30.4C193.7 437.5 239.9 382.9 255 319c15.5 63.9 61.7 118.5 118.8 154.7C338.7 493 298.3 504 255 504zm190.6-87.5C359 374.5 298 279.6 298 169.1V12.5c116.9 19.7 206 121.4 206 244.1 0 61.1-22 116.6-58.4 159.9z"],replyd:[448,512,[],"f3e6","M320 480H128C57.6 480 0 422.4 0 352V160C0 89.6 57.6 32 128 32h192c70.4 0 128 57.6 128 128v192c0 70.4-57.6 128-128 128zM193.4 273.2c-6.1-2-11.6-3.1-16.4-3.1-7.2 0-13.5 1.9-18.9 5.6-5.4 3.7-9.6 9-12.8 15.8h-1.1l-4.2-18.3h-28v138.9h36.1v-89.7c1.5-5.4 4.4-9.8 8.7-13.2 4.3-3.4 9.8-5.1 16.2-5.1 4.6 0 9.8 1 15.6 3.1l4.8-34zm115.2 103.4c-3.2 2.4-7.7 4.8-13.7 7.1-6 2.3-12.8 3.5-20.4 3.5-12.2 0-21.1-3-26.5-8.9-5.5-5.9-8.5-14.7-9-26.4h83.3c.9-4.8 1.6-9.4 2.1-13.9.5-4.4.7-8.6.7-12.5 0-10.7-1.6-19.7-4.7-26.9-3.2-7.2-7.3-13-12.5-17.2-5.2-4.3-11.1-7.3-17.8-9.2-6.7-1.8-13.5-2.8-20.6-2.8-21.1 0-37.5 6.1-49.2 18.3s-17.5 30.5-17.5 55c0 22.8 5.2 40.7 15.6 53.7 10.4 13.1 26.8 19.6 49.2 19.6 10.7 0 20.9-1.5 30.4-4.6 9.5-3.1 17.1-6.8 22.6-11.2l-12-23.6zm-21.8-70.3c3.8 5.4 5.3 13.1 4.6 23.1h-51.7c.9-9.4 3.7-17 8.2-22.6 4.5-5.6 11.5-8.5 21-8.5 8.2-.1 14.1 2.6 17.9 8zm79.9 2.5c4.1 3.9 9.4 5.8 16.1 5.8 7 0 12.6-1.9 16.7-5.8s6.1-9.1 6.1-15.6-2-11.6-6.1-15.4c-4.1-3.8-9.6-5.7-16.7-5.7-6.7 0-12 1.9-16.1 5.7-4.1 3.8-6.1 8.9-6.1 15.4s2 11.7 6.1 15.6zm0 100.5c4.1 3.9 9.4 5.8 16.1 5.8 7 0 12.6-1.9 16.7-5.8s6.1-9.1 6.1-15.6-2-11.6-6.1-15.4c-4.1-3.8-9.6-5.7-16.7-5.7-6.7 0-12 1.9-16.1 5.7-4.1 3.8-6.1 8.9-6.1 15.4 0 6.6 2 11.7 6.1 15.6z"],resolving:[496,512,[],"f3e7","M281.2 278.2c46-13.3 49.6-23.5 44-43.4L314 195.5c-6.1-20.9-18.4-28.1-71.1-12.8L54.7 236.8l28.6 98.6 197.9-57.2zM248.5 8C131.4 8 33.2 88.7 7.2 197.5l221.9-63.9c34.8-10.2 54.2-11.7 79.3-8.2 36.3 6.1 52.7 25 61.4 55.2l10.7 37.8c8.2 28.1 1 50.6-23.5 73.6-19.4 17.4-31.2 24.5-61.4 33.2L203 351.8l220.4 27.1 9.7 34.2-48.1 13.3-286.8-37.3 23 80.2c36.8 22 80.3 34.7 126.3 34.7 137 0 248.5-111.4 248.5-248.3C497 119.4 385.5 8 248.5 8zM38.3 388.6L0 256.8c0 48.5 14.3 93.4 38.3 131.8z"],rocketchat:[448,512,[],"f3e8","M448 256.2c0-87.2-99.6-153.3-219.8-153.3-18.8 0-37.3 1.6-55.3 4.8-11.1-10.5-24.2-20-38-27.4C61.2 44.2 0 79.4 0 79.4s56.9 47.1 47.6 88.3c-52.3 52.3-52.5 124.1 0 176.6C56.9 385.6 0 432.6 0 432.6s61.2 35.2 134.9-.8c13.8-7.5 26.9-16.9 38-27.4 18 3.2 36.5 4.8 55.3 4.8 120.3-.1 219.8-65.8 219.8-153zm-219.7 124c-23.7 0-46.3-2.8-67.3-7.8-21.3 25.8-68.1 61.7-113.6 50.1 14.8-16 36.7-43.1 32-87.6-27.3-21.4-43.6-48.7-43.6-78.5 0-68.4 86.2-123.9 192.5-123.9S420.8 188 420.8 256.4c0 68.3-86.2 123.8-192.5 123.8zm25.6-123.9c0 14.2-11.5 25.8-25.6 25.8-14.1 0-25.6-11.5-25.6-25.8 0-14.2 11.5-25.8 25.6-25.8 14.1 0 25.6 11.6 25.6 25.8zm88.9 0c0 14.2-11.4 25.8-25.6 25.8-14.1 0-25.6-11.5-25.6-25.8 0-14.2 11.4-25.8 25.6-25.8 14.1 0 25.6 11.6 25.6 25.8zm-177.9 0c0 14.2-11.4 25.8-25.6 25.8-14.1 0-25.6-11.5-25.6-25.8 0-14.2 11.4-25.8 25.6-25.8 14.2 0 25.6 11.6 25.6 25.8z"],rockrms:[496,512,[],"f3e9","M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm157.4 419.5h-90l-112-131.3c-17.9-20.4-3.9-56.1 26.6-56.1h75.3l-84.6-99.3-84.3 98.9h-90L193.5 67.2c14.4-18.4 41.3-17.3 54.5 0l157.7 185.1c19 22.8 2 57.2-27.6 56.1-.6 0-74.2.2-74.2.2l101.5 118.9z"],safari:[512,512,[],"f267","M236.9 256.8c0-9.1 6.6-17.7 16.3-17.7 8.9 0 17.4 6.4 17.4 16.1 0 9.1-6.4 17.7-16.1 17.7-9 0-17.6-6.7-17.6-16.1zM504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-26.6 0c0-122.3-99.1-221.4-221.4-221.4S34.6 133.7 34.6 256 133.7 477.4 256 477.4 477.4 378.3 477.4 256zm-72.5 96.6c0 3.6 13 10.2 16.3 12.2-27.4 41.5-69.8 71.4-117.9 83.3l-4.4-18.5c-.3-2.5-1.9-2.8-4.2-2.8-1.9 0-3 2.8-2.8 4.2l4.4 18.8c-13.3 2.8-26.8 4.2-40.4 4.2-36.3 0-72-10.2-103-29.1 1.7-2.8 12.2-18 12.2-20.2 0-1.9-1.7-3.6-3.6-3.6-3.9 0-12.2 16.6-14.7 19.9-41.8-27.7-72-70.6-83.6-119.6l19.1-4.2c2.2-.6 2.8-2.2 2.8-4.2 0-1.9-2.8-3-4.4-2.8L62 294.5c-2.5-12.7-3.9-25.5-3.9-38.5 0-37.1 10.5-73.6 30.2-104.9 2.8 1.7 16.1 10.8 18.3 10.8 1.9 0 3.6-1.4 3.6-3.3 0-3.9-14.7-11.3-18-13.6 28.2-41.2 71.1-70.9 119.8-81.9l4.2 18.5c.6 2.2 2.2 2.8 4.2 2.8s3-2.8 2.8-4.4L219 61.7c12.2-2.2 24.6-3.6 37.1-3.6 37.1 0 73.3 10.5 104.9 30.2-1.9 2.8-10.8 15.8-10.8 18 0 1.9 1.4 3.6 3.3 3.6 3.9 0 11.3-14.4 13.3-17.7 41 27.7 70.3 70 81.7 118.2l-15.5 3.3c-2.5.6-2.8 2.2-2.8 4.4 0 1.9 2.8 3 4.2 2.8l15.8-3.6c2.5 12.7 3.9 25.7 3.9 38.7 0 36.3-10 72-28.8 102.7-2.8-1.4-14.4-9.7-16.6-9.7-2.1 0-3.8 1.7-3.8 3.6zm-33.2-242.2c-13 12.2-134.2 123.7-137.6 129.5l-96.6 160.5c12.7-11.9 134.2-124 137.3-129.3l96.9-160.7z"],sass:[640,512,[],"f41e","M551.1 291.9c-22.4.1-41.8 5.5-58 13.5-5.9-11.9-12-22.3-13-30.1-1.2-9.1-2.5-14.5-1.1-25.3s7.7-26.1 7.6-27.2c-.1-1.1-1.4-6.6-14.3-6.7-12.9-.1-24 2.5-25.3 5.9-1.3 3.4-3.8 11.1-5.3 19.1-2.3 11.7-25.8 53.5-39.1 75.3-4.4-8.5-8.1-16-8.9-22-1.2-9.1-2.5-14.5-1.1-25.3s7.7-26.1 7.6-27.2c-.1-1.1-1.4-6.6-14.3-6.7-12.9-.1-24 2.5-25.3 5.9-1.3 3.4-2.7 11.4-5.3 19.1-2.6 7.7-33.9 77.3-42.1 95.4-4.2 9.2-7.8 16.6-10.4 21.6s-.2.3-.4.9c-2.2 4.3-3.5 6.7-3.5 6.7v.1c-1.7 3.2-3.6 6.1-4.5 6.1-.6 0-1.9-8.4.3-19.9 4.7-24.2 15.8-61.8 15.7-63.1-.1-.7 2.1-7.2-7.3-10.7-9.1-3.3-12.4 2.2-13.2 2.2-.8 0-1.4 2-1.4 2s10.1-42.4-19.4-42.4c-18.4 0-44 20.2-56.6 38.5-7.9 4.3-25 13.6-43 23.5-6.9 3.8-14 7.7-20.7 11.4-.5-.5-.9-1-1.4-1.5-35.8-38.2-101.9-65.2-99.1-116.5 1-18.7 7.5-67.8 127.1-127.4 98-48.8 176.4-35.4 189.9-5.6 19.4 42.5-41.9 121.6-143.7 133-38.8 4.3-59.2-10.7-64.3-16.3-5.3-5.9-6.1-6.2-8.1-5.1-3.3 1.8-1.2 7 0 10.1 3 7.9 15.5 21.9 36.8 28.9 18.7 6.1 64.2 9.5 119.2-11.8C367 196.5 415.1 130.2 401 74.7 386.6 18.3 293.1-.2 204.6 31.2 151.9 49.9 94.9 79.3 53.9 117.6 5.2 163.2-2.6 202.9.6 219.5c11.4 58.9 92.6 97.3 125.1 125.7-1.6.9-3.1 1.7-4.5 2.5-16.3 8.1-78.2 40.5-93.7 74.7-17.5 38.8 2.9 66.6 16.3 70.4 41.8 11.6 84.6-9.3 107.6-43.6s20.2-79.1 9.6-99.5c-.1-.3-.3-.5-.4-.8 4.2-2.5 8.5-5 12.8-7.5 8.3-4.9 16.4-9.4 23.5-13.3-4 10.8-6.9 23.8-8.4 42.6-1.8 22 7.3 50.5 19.1 61.7 5.2 4.9 11.5 5 15.4 5 13.8 0 20-11.4 26.9-25 8.5-16.6 16-35.9 16-35.9s-9.4 52.2 16.3 52.2c9.4 0 18.8-12.1 23-18.3v.1s.2-.4.7-1.2c1-1.5 1.5-2.4 1.5-2.4v-.3c3.8-6.5 12.1-21.4 24.6-46 16.2-31.8 31.7-71.5 31.7-71.5s1.4 9.7 6.2 25.8c2.8 9.5 8.7 19.9 13.4 30-3.8 5.2-6.1 8.2-6.1 8.2s0 .1.1.2c-3 4-6.4 8.3-9.9 12.5-12.8 15.2-28 32.6-30 37.6-2.4 5.9-1.8 10.3 2.8 13.7 3.4 2.6 9.4 3 15.7 2.5 11.5-.8 19.6-3.6 23.5-5.4 6.2-2.2 13.4-5.7 20.2-10.6 12.5-9.2 20.1-22.4 19.4-39.8-.4-9.6-3.5-19.2-7.3-28.2 1.1-1.6 2.3-3.3 3.4-5 19.8-28.9 35.1-60.6 35.1-60.6s1.4 9.7 6.2 25.8c2.4 8.1 7.1 17 11.4 25.7-18.6 15.1-30.1 32.6-34.1 44.1-7.4 21.3-1.6 30.9 9.3 33.1 4.9 1 11.9-1.3 17.1-3.5 6.5-2.2 14.3-5.7 21.6-11.1 12.5-9.2 24.6-22.1 23.8-39.6-.3-7.9-2.5-15.8-5.4-23.4 15.7-6.6 36.1-10.2 62.1-7.2 55.7 6.5 66.6 41.3 64.5 55.8-2.1 14.6-13.8 22.6-17.7 25-3.9 2.4-5.1 3.3-4.8 5.1.5 2.6 2.3 2.5 5.6 1.9 4.6-.8 29.2-11.8 30.3-38.7 1.6-34-31.1-71.4-89-71.1zM121.8 436.6c-18.4 20.1-44.2 27.7-55.3 21.3C54.6 451 59.3 421.4 82 400c13.8-13 31.6-25 43.4-32.4 2.7-1.6 6.6-4 11.4-6.9.8-.5 1.2-.7 1.2-.7.9-.6 1.9-1.1 2.9-1.7 8.3 30.4.3 57.2-19.1 78.3zm134.4-91.4c-6.4 15.7-19.9 55.7-28.1 53.6-7-1.8-11.3-32.3-1.4-62.3 5-15.1 15.6-33.1 21.9-40.1 10.1-11.3 21.2-14.9 23.8-10.4 3.5 5.9-12.2 49.4-16.2 59.2zm111 53c-2.7 1.4-5.2 2.3-6.4 1.6-.9-.5 1.1-2.4 1.1-2.4s13.9-14.9 19.4-21.7c3.2-4 6.9-8.7 10.9-13.9 0 .5.1 1 .1 1.6-.1 17.9-17.3 30-25.1 34.8zm85.6-19.5c-2-1.4-1.7-6.1 5-20.7 2.6-5.7 8.6-15.3 19-24.5 1.2 3.8 1.9 7.4 1.9 10.8-.1 22.5-16.2 30.9-25.9 34.4z"],schlix:[448,512,[],"f3ea","M350.5 157.7l-54.2-46.1 73.4-39 78.3 44.2-97.5 40.9zM192 122.1l45.7-28.2 34.7 34.6-55.4 29-25-35.4zm-65.1 6.6l31.9-22.1L176 135l-36.7 22.5-12.4-28.8zm-23.3 88.2l-8.8-34.8 29.6-18.3 13.1 35.3-33.9 17.8zm-21.2-83.7l23.9-18.1 8.9 24-26.7 18.3-6.1-24.2zM59 206.5l-3.6-28.4 22.3-15.5 6.1 28.7L59 206.5zm-30.6 16.6l20.8-12.8 3.3 33.4-22.9 12-1.2-32.6zM1.4 268l19.2-10.2.4 38.2-21 8.8L1.4 268zm59.1 59.3l-28.3 8.3-1.6-46.8 25.1-10.7 4.8 49.2zM99 263.2l-31.1 13-5.2-40.8L90.1 221l8.9 42.2zM123.2 377l-41.6 5.9-8.1-63.5 35.2-10.8 14.5 68.4zm28.5-139.9l21.2 57.1-46.2 13.6-13.7-54.1 38.7-16.6zm85.7 230.5l-70.9-3.3-24.3-95.8 55.2-8.6 40 107.7zm-84.9-279.7l42.2-22.4 28 45.9-50.8 21.3-19.4-44.8zm41 94.9l61.3-18.7 52.8 86.6-79.8 11.3-34.3-79.2zm51.4-85.6l67.3-28.8 65.5 65.4-88.6 26.2-44.2-62.8z"],scribd:[384,512,[],"f28a","M42.3 252.7c-16.1-19-24.7-45.9-24.8-79.9 0-100.4 75.2-153.1 167.2-153.1 98.6-1.6 156.8 49 184.3 70.6l-50.5 72.1-37.3-24.6 26.9-38.6c-36.5-24-79.4-36.5-123-35.8-50.7-.8-111.7 27.2-111.7 76.2 0 18.7 11.2 20.7 28.6 15.6 23.3-5.3 41.9.6 55.8 14 26.4 24.3 23.2 67.6-.7 91.9-29.2 29.5-85.2 27.3-114.8-8.4zm317.7 5.9c-15.5-18.8-38.9-29.4-63.2-28.6-38.1-2-71.1 28-70.5 67.2-.7 16.8 6 33 18.4 44.3 14.1 13.9 33 19.7 56.3 14.4 17.4-5.1 28.6-3.1 28.6 15.6 0 4.3-.5 8.5-1.4 12.7-16.7 40.9-59.5 64.4-121.4 64.4-51.9.2-102.4-16.4-144.1-47.3l33.7-39.4-35.6-27.4L0 406.3l15.4 13.8c52.5 46.8 120.4 72.5 190.7 72.2 51.4 0 94.4-10.5 133.6-44.1 57.1-51.4 54.2-149.2 20.3-189.6z"],searchengin:[460,512,[],"f3eb","M220.6 130.3l-67.2 28.2V43.2L98.7 233.5l54.7-24.2v130.3l67.2-209.3zm-83.2-96.7l-1.3 4.7-15.2 52.9C80.6 106.7 52 145.8 52 191.5c0 52.3 34.3 95.9 83.4 105.5v53.6C57.5 340.1 0 272.4 0 191.6c0-80.5 59.8-147.2 137.4-158zm311.4 447.2c-11.2 11.2-23.1 12.3-28.6 10.5-5.4-1.8-27.1-19.9-60.4-44.4-33.3-24.6-33.6-35.7-43-56.7-9.4-20.9-30.4-42.6-57.5-52.4l-9.7-14.7c-24.7 16.9-53 26.9-81.3 28.7l2.1-6.6 15.9-49.5c46.5-11.9 80.9-54 80.9-104.2 0-54.5-38.4-102.1-96-107.1V32.3C254.4 37.4 320 106.8 320 191.6c0 33.6-11.2 64.7-29 90.4l14.6 9.6c9.8 27.1 31.5 48 52.4 57.4s32.2 9.7 56.8 43c24.6 33.2 42.7 54.9 44.5 60.3s.7 17.3-10.5 28.5zm-9.9-17.9c0-4.4-3.6-8-8-8s-8 3.6-8 8 3.6 8 8 8 8-3.6 8-8z"],sellcast:[448,512,[],"f2da","M353.4 32H94.7C42.6 32 0 74.6 0 126.6v258.7C0 437.4 42.6 480 94.7 480h258.7c52.1 0 94.7-42.6 94.7-94.6V126.6c0-52-42.6-94.6-94.7-94.6zm-50 316.4c-27.9 48.2-89.9 64.9-138.2 37.2-22.9 39.8-54.9 8.6-42.3-13.2l15.7-27.2c5.9-10.3 19.2-13.9 29.5-7.9 18.6 10.8-.1-.1 18.5 10.7 27.6 15.9 63.4 6.3 79.4-21.3 15.9-27.6 6.3-63.4-21.3-79.4-17.8-10.2-.6-.4-18.6-10.6-24.6-14.2-3.4-51.9 21.6-37.5 18.6 10.8-.1-.1 18.5 10.7 48.4 28 65.1 90.3 37.2 138.5zm21.8-208.8c-17 29.5-16.3 28.8-19 31.5-6.5 6.5-16.3 8.7-26.5 3.6-18.6-10.8.1.1-18.5-10.7-27.6-15.9-63.4-6.3-79.4 21.3s-6.3 63.4 21.3 79.4c0 0 18.5 10.6 18.6 10.6 24.6 14.2 3.4 51.9-21.6 37.5-18.6-10.8.1.1-18.5-10.7-48.2-27.8-64.9-90.1-37.1-138.4 27.9-48.2 89.9-64.9 138.2-37.2l4.8-8.4c14.3-24.9 52-3.3 37.7 21.5z"],sellsy:[640,512,[],"f213","M539.71 237.308c3.064-12.257 4.29-24.821 4.29-37.384C544 107.382 468.618 32 376.076 32c-77.22 0-144.634 53.012-163.02 127.781-15.322-13.176-34.934-20.53-55.157-20.53-46.271 0-83.962 37.69-83.962 83.961 0 7.354.92 15.015 3.065 22.369-42.9 20.225-70.785 63.738-70.785 111.234C6.216 424.843 61.68 480 129.401 480h381.198c67.72 0 123.184-55.157 123.184-123.184.001-56.384-38.916-106.025-94.073-119.508zM199.88 401.554c0 8.274-7.048 15.321-15.321 15.321H153.61c-8.274 0-15.321-7.048-15.321-15.321V290.626c0-8.273 7.048-15.321 15.321-15.321h30.949c8.274 0 15.321 7.048 15.321 15.321v110.928zm89.477 0c0 8.274-7.048 15.321-15.322 15.321h-30.949c-8.274 0-15.321-7.048-15.321-15.321V270.096c0-8.274 7.048-15.321 15.321-15.321h30.949c8.274 0 15.322 7.048 15.322 15.321v131.458zm89.477 0c0 8.274-7.047 15.321-15.321 15.321h-30.949c-8.274 0-15.322-7.048-15.322-15.321V238.84c0-8.274 7.048-15.321 15.322-15.321h30.949c8.274 0 15.321 7.048 15.321 15.321v162.714zm87.027 0c0 8.274-7.048 15.321-15.322 15.321h-28.497c-8.274 0-15.321-7.048-15.321-15.321V176.941c0-8.579 7.047-15.628 15.321-15.628h28.497c8.274 0 15.322 7.048 15.322 15.628v224.613z"],servicestack:[496,512,[],"f3ec","M88 216c81.7 10.2 273.7 102.3 304 232H0c99.5-8.1 184.5-137 88-232zm32-152c32.3 35.6 47.7 83.9 46.4 133.6C249.3 231.3 373.7 321.3 400 448h96C455.3 231.9 222.8 79.5 120 64z"],shirtsinbulk:[448,512,[],"f214","M395.208 221.583H406v33.542h-10.792v-33.542zm0-9.625H406v-33.542h-10.792v33.542zm0 86.333H406V264.75h-10.792v33.541zM358.75 135.25h-33.542v10.5h33.542v-10.5zm36.458 206.208H406v-33.542h-10.792v33.542zM311.5 135.25h-33.542v10.5H311.5v-10.5zm-47.25 0H231v10.5h33.25v-10.5zm-47.25 0h-33.25v10.5H217v-10.5zm178.208 33.542H406V135.25h-33.542v10.5h22.75v23.042zm-255.792 259l30.625 13.417 4.375-9.917-30.625-13.417-4.375 9.917zM179.083 445l30.334 13.708 4.374-9.916-30.333-13.417-4.375 9.625zm216.125-60.375H406v-33.542h-10.792v33.542zm-334.833 8.167L91 406.208l4.375-9.624-30.625-13.709-4.375 9.917zm39.666 17.499l30.625 13.417 4.375-9.917-30.625-13.416-4.375 9.916zm132.417 38.501l4.375 9.916L267.459 445l-4.375-9.625-30.626 13.417zm118.417-52.208l4.375 9.624 30.624-13.416-4.374-9.917-30.625 13.709zM311.5 413.791l4.375 9.917 30.625-13.417-4.374-9.916-30.626 13.416zm-39.667 17.501l4.375 9.917 30.625-13.417-4.375-9.917-30.625 13.417zM311.5 46.583h-33.542v10.5H311.5v-10.5zm94.209 0h-33.251v10.5h33.251v-10.5zm-188.709 0h-33.25v10.5H217v-10.5zm141.75 0h-33.542v10.5h33.542v-10.5zm-94.5 0H231v10.5h33.25v-10.5zM448 3.708v406l-226.334 98.584L0 409.708v-406h448zm-29.166 116.958H29.166V390.75l192.792 85.75 196.875-85.75V120.666zm0-87.791H29.166V91.5h389.667V32.875zM75.542 46.583H42.291v10.5h33.251v-10.5zm94.5 0H136.5v10.5h33.542v-10.5zm-47.251 0H89.25v10.5h33.542v-10.5zm7.584 236.542c0-50.167 41.125-91.292 91.292-91.292 50.458 0 91.292 41.125 91.292 91.292 0 50.458-40.833 91.292-91.292 91.292-50.167-.001-91.292-40.834-91.292-91.292zm120.75 18.084c0 13.125-23.917 14.291-32.666 14.291-12.25 0-29.75-2.625-35.875-14.875h-.875L172.666 319c14.876 9.333 29.167 12.25 47.25 12.25 19.542 0 51.042-5.833 51.042-31.209 0-48.125-78.458-16.333-78.458-37.916 0-13.125 20.708-14.875 29.75-14.875 10.791 0 29.166 3.208 35.583 13.124h.875l8.751-16.916c-15.167-6.125-27.417-11.959-44.334-11.959-20.125 0-49.583 6.417-49.583 31.792 0 44.334 77.583 11.959 77.583 37.918zM122.791 135.25H89.25v10.5h33.542v-10.5zm-69.999 10.5h22.75v-10.5H42v33.542h10.792V145.75zm0 32.666H42v33.542h10.792v-33.542zm117.25-43.166H136.5v10.5h33.542v-10.5zm-117.25 86.333H42v33.542h10.792v-33.542zm0 86.334H42v33.542h10.792v-33.542zm0-43.167H42v33.542h10.792V264.75zm0 86.333H42v33.542h10.792v-33.542z"],simplybuilt:[512,512,[],"f215","M481.2 64h-106c-14.5 0-26.6 11.8-26.6 26.3v39.6H163.3V90.3c0-14.5-12-26.3-26.6-26.3h-106C16.1 64 4.3 75.8 4.3 90.3v331.4c0 14.5 11.8 26.3 26.6 26.3h450.4c14.8 0 26.6-11.8 26.6-26.3V90.3c-.2-14.5-12-26.3-26.7-26.3zM149.8 355.8c-36.6 0-66.4-29.7-66.4-66.4 0-36.9 29.7-66.6 66.4-66.6 36.9 0 66.6 29.7 66.6 66.6 0 36.7-29.7 66.4-66.6 66.4zm212.4 0c-36.9 0-66.6-29.7-66.6-66.6 0-36.6 29.7-66.4 66.6-66.4 36.6 0 66.4 29.7 66.4 66.4 0 36.9-29.8 66.6-66.4 66.6z"],sistrix:[448,512,[],"f3ee","M448 449L301.2 300.2c20-27.9 31.9-62.2 31.9-99.2 0-93.1-74.7-168.9-166.5-168.9C74.7 32 0 107.8 0 200.9s74.7 168.9 166.5 168.9c39.8 0 76.3-14.2 105-37.9l146 148.1 30.5-31zM166.5 330.8c-70.6 0-128.1-58.3-128.1-129.9S95.9 71 166.5 71s128.1 58.3 128.1 129.9-57.4 129.9-128.1 129.9z"],skyatlas:[576,512,[],"f216","M545.7 318.5c0 56.2-44.8 97.5-100.2 97.5-141.5 0-167.6-212.9-306.7-212.9-125.2 0-125.4 180.9 4.8 180.9 36.2 0 77.5-15.2 106.8-36.2 4.8-3.5 14.4-13.9 19.5-13.9s9.3 4.3 9.3 9.3c0 6.7-11.2 16.3-16 20.5-34.9 30.4-85.5 52.2-131.9 52.2C60.2 416 0 365.6 0 292.4s57.6-127.1 130.3-127.1c158 0 189.7 209.7 308.5 209.7 85.2 0 80.8-119.1 2.9-119.1-14.9 0-29.8 9.9-40 9.9-7.2 0-13.6-6.1-13.6-13.3 0-9.9 4.5-20.2 4.5-30.9 0-56.8-43.4-97.8-99.7-97.8-45.3 0-68.2 31.4-75.7 31.4-5.3 0-9.6-4.3-9.6-9.6 0-4.8 3.5-8.8 6.7-12.3C235.9 108.8 269.5 96 302 96c67.7 0 118.6 49.8 118.6 117.5 0 5.9-.3 11.7-1.1 17.6 10.1-2.7 20.5-4 30.6-4 51.9 0 95.6 38.6 95.6 91.4z"],skype:[448,512,[],"f17e","M424.7 299.8c2.9-14 4.7-28.9 4.7-43.8 0-113.5-91.9-205.3-205.3-205.3-14.9 0-29.7 1.7-43.8 4.7C161.3 40.7 137.7 32 112 32 50.2 32 0 82.2 0 144c0 25.7 8.7 49.3 23.3 68.2-2.9 14-4.7 28.9-4.7 43.8 0 113.5 91.9 205.3 205.3 205.3 14.9 0 29.7-1.7 43.8-4.7 19 14.6 42.6 23.3 68.2 23.3 61.8 0 112-50.2 112-112 .1-25.6-8.6-49.2-23.2-68.1zm-194.6 91.5c-65.6 0-120.5-29.2-120.5-65 0-16 9-30.6 29.5-30.6 31.2 0 34.1 44.9 88.1 44.9 25.7 0 42.3-11.4 42.3-26.3 0-18.7-16-21.6-42-28-62.5-15.4-117.8-22-117.8-87.2 0-59.2 58.6-81.1 109.1-81.1 55.1 0 110.8 21.9 110.8 55.4 0 16.9-11.4 31.8-30.3 31.8-28.3 0-29.2-33.5-75-33.5-25.7 0-42 7-42 22.5 0 19.8 20.8 21.8 69.1 33 41.4 9.3 90.7 26.8 90.7 77.6 0 59.1-57.1 86.5-112 86.5z"],slack:[448,512,[],"f198","M244.2 217.5l19.3 57.7-59.8 20-19.3-57.7 59.8-20zm41.4 243.7C131.6 507.4 65 471.6 18.8 317.6S8.4 97 162.4 50.8C316.4 4.6 383 40.4 429.2 194.4c46.2 154 10.4 220.6-143.6 266.8zM366.2 265c-3.9-12.2-17.2-18.6-29.4-14.7l-29 9.7-19.3-57.7 29-9.7c12.2-3.9 18.6-17.2 14.7-29.4-3.9-12.2-17.2-18.6-29.4-14.7l-29 9.7-10-30.1c-3.9-12.2-17.2-18.6-29.4-14.7-12.2 3.9-18.6 17.2-14.7 29.4l10 30.1-59.8 20.1-10-30.1c-3.9-12.2-17.2-18.6-29.4-14.7-12.2 3.9-18.6 17.2-14.7 29.4l10 30.1-29 9.7c-12.2 3.9-18.6 17.2-14.7 29.4 3.2 9.3 12.2 15.4 21.5 15.8 4.3.6 7.7-1 36.9-10.7l19.3 57.7-29 9.7c-12.2 3.9-18.6 17.2-14.7 29.4 3.2 9.3 12.2 15.4 21.5 15.8 4.3.6 7.7-1 36.9-10.7l10 30.1c3.7 10.8 15.8 18.6 29.4 14.7 12.2-3.9 18.6-17.2 14.7-29.4l-10-30.1 59.8-20.1 10 30.1c3.7 10.8 15.8 18.6 29.4 14.7 12.2-3.9 18.6-17.2 14.7-29.4l-10-30.1 29-9.7c12.2-4.2 18.6-17.5 14.7-29.6z"],"slack-hash":[448,512,[],"f3ef","M446.2 270.4c-6.2-19-26.9-29.1-46-22.9l-45.4 15.1-30.3-90 45.4-15.1c19.1-6.2 29.1-26.8 23-45.9-6.2-19-26.9-29.1-46-22.9l-45.4 15.1-15.7-47c-6.2-19-26.9-29.1-46-22.9-19.1 6.2-29.1 26.8-23 45.9l15.7 47-93.4 31.2-15.7-47c-6.2-19-26.9-29.1-46-22.9-19.1 6.2-29.1 26.8-23 45.9l15.7 47-45.3 15c-19.1 6.2-29.1 26.8-23 45.9 5 14.5 19.1 24 33.6 24.6 6.8 1 12-1.6 57.7-16.8l30.3 90L78 354.8c-19 6.2-29.1 26.9-23 45.9 5 14.5 19.1 24 33.6 24.6 6.8 1 12-1.6 57.7-16.8l15.7 47c5.9 16.9 24.7 29 46 22.9 19.1-6.2 29.1-26.8 23-45.9l-15.7-47 93.6-31.3 15.7 47c5.9 16.9 24.7 29 46 22.9 19.1-6.2 29.1-26.8 23-45.9l-15.7-47 45.4-15.1c19-6 29.1-26.7 22.9-45.7zm-254.1 47.2l-30.3-90.2 93.5-31.3 30.3 90.2-93.5 31.3z"],slideshare:[512,512,[],"f1e7","M249.429 211.436c0 31.716-27.715 57.717-61.717 57.717-34.001 0-61.716-26.001-61.716-57.717 0-32.001 27.715-57.716 61.716-57.716 34.001 0 61.717 25.715 61.717 57.716zm254.294 50.002c-18.286 22.573-53.144 50.288-106.289 72.003C453.722 525.163 260 555.735 263.143 457.446c0 1.714-.286-52.859-.286-93.432-4.285-.858-8.571-2-13.714-3.143 0 40.858-.286 98.289-.286 96.575C252 555.735 58.278 525.163 114.566 333.441c-53.145-21.715-88.003-49.43-106.29-72.003-9.143-13.714.858-28.287 16.001-17.715 2 1.428 4.285 2.857 6.285 4.285V49.716C30.563 22.287 51.135 0 76.565 0h359.157c25.429 0 46.002 22.287 46.002 49.716v198.293l6-4.285c15.143-10.573 25.143 4 15.999 17.714zm-46.572-189.15c0-32.858-10.572-45.716-40.859-45.716H98.566c-31.716 0-40.573 10.858-40.573 45.716v192.293c67.717 35.43 125.72 29.144 157.435 28.001 13.429-.286 22.001 2.286 27.144 7.715 1.689 1.687 10.023 9.446 20.287 17.143 1.143-15.715 10.001-25.715 33.716-24.858 32.287 1.428 91.718 7.715 160.577-29.716V72.288zM331.146 153.72c-34.002 0-61.716 25.715-61.716 57.716 0 31.716 27.715 57.717 61.716 57.717 34.287 0 61.716-26.001 61.716-57.717 0-32.001-27.429-57.716-61.716-57.716z"],snapchat:[496,512,[],"f2ab","M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm169.5 338.9c-3.5 8.1-18.1 14-44.8 18.2-1.4 1.9-2.5 9.8-4.3 15.9-1.1 3.7-3.7 5.9-8.1 5.9h-.2c-6.2 0-12.8-2.9-25.8-2.9-17.6 0-23.7 4-37.4 13.7-14.5 10.3-28.4 19.1-49.2 18.2-21 1.6-38.6-11.2-48.5-18.2-13.8-9.7-19.8-13.7-37.4-13.7-12.5 0-20.4 3.1-25.8 3.1-5.4 0-7.5-3.3-8.3-6-1.8-6.1-2.9-14.1-4.3-16-13.8-2.1-44.8-7.5-45.5-21.4-.2-3.6 2.3-6.8 5.9-7.4 46.3-7.6 67.1-55.1 68-57.1 0-.1.1-.2.2-.3 2.5-5 3-9.2 1.6-12.5-3.4-7.9-17.9-10.7-24-13.2-15.8-6.2-18-13.4-17-18.3 1.6-8.5 14.4-13.8 21.9-10.3 5.9 2.8 11.2 4.2 15.7 4.2 3.3 0 5.5-.8 6.6-1.4-1.4-23.9-4.7-58 3.8-77.1C183.1 100 230.7 96 244.7 96c.6 0 6.1-.1 6.7-.1 34.7 0 68 17.8 84.3 54.3 8.5 19.1 5.2 53.1 3.8 77.1 1.1.6 2.9 1.3 5.7 1.4 4.3-.2 9.2-1.6 14.7-4.2 4-1.9 9.6-1.6 13.6 0 6.3 2.3 10.3 6.8 10.4 11.9.1 6.5-5.7 12.1-17.2 16.6-1.4.6-3.1 1.1-4.9 1.7-6.5 2.1-16.4 5.2-19 11.5-1.4 3.3-.8 7.5 1.6 12.5.1.1.1.2.2.3.9 2 21.7 49.5 68 57.1 4 1 7.1 5.5 4.9 10.8z"],"snapchat-ghost":[512,512,[],"f2ac","M510.846 392.673c-5.211 12.157-27.239 21.089-67.36 27.318-2.064 2.786-3.775 14.686-6.507 23.956-1.625 5.566-5.623 8.869-12.128 8.869l-.297-.005c-9.395 0-19.203-4.323-38.852-4.323-26.521 0-35.662 6.043-56.254 20.588-21.832 15.438-42.771 28.764-74.027 27.399-31.646 2.334-58.025-16.908-72.871-27.404-20.714-14.643-29.828-20.582-56.241-20.582-18.864 0-30.736 4.72-38.852 4.72-8.073 0-11.213-4.922-12.422-9.04-2.703-9.189-4.404-21.263-6.523-24.13-20.679-3.209-67.31-11.344-68.498-32.15a10.627 10.627 0 0 1 8.877-11.069c69.583-11.455 100.924-82.901 102.227-85.934.074-.176.155-.344.237-.515 3.713-7.537 4.544-13.849 2.463-18.753-5.05-11.896-26.872-16.164-36.053-19.796-23.715-9.366-27.015-20.128-25.612-27.504 2.437-12.836 21.725-20.735 33.002-15.453 8.919 4.181 16.843 6.297 23.547 6.297 5.022 0 8.212-1.204 9.96-2.171-2.043-35.936-7.101-87.29 5.687-115.969C158.122 21.304 229.705 15.42 250.826 15.42c.944 0 9.141-.089 10.11-.089 52.148 0 102.254 26.78 126.723 81.643 12.777 28.65 7.749 79.792 5.695 116.009 1.582.872 4.357 1.942 8.599 2.139 6.397-.286 13.815-2.389 22.069-6.257 6.085-2.846 14.406-2.461 20.48.058l.029.01c9.476 3.385 15.439 10.215 15.589 17.87.184 9.747-8.522 18.165-25.878 25.018-2.118.835-4.694 1.655-7.434 2.525-9.797 3.106-24.6 7.805-28.616 17.271-2.079 4.904-1.256 11.211 2.46 18.748.087.168.166.342.239.515 1.301 3.03 32.615 74.46 102.23 85.934 6.427 1.058 11.163 7.877 7.725 15.859z"],"snapchat-square":[448,512,[],"f2ad","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-6.5 314.9c-3.5 8.1-18.1 14-44.8 18.2-1.4 1.9-2.5 9.8-4.3 15.9-1.1 3.7-3.7 5.9-8.1 5.9h-.2c-6.2 0-12.8-2.9-25.8-2.9-17.6 0-23.7 4-37.4 13.7-14.5 10.3-28.4 19.1-49.2 18.2-21 1.6-38.6-11.2-48.5-18.2-13.8-9.7-19.8-13.7-37.4-13.7-12.5 0-20.4 3.1-25.8 3.1-5.4 0-7.5-3.3-8.3-6-1.8-6.1-2.9-14.1-4.3-16-13.8-2.1-44.8-7.5-45.5-21.4-.2-3.6 2.3-6.8 5.9-7.4 46.3-7.6 67.1-55.1 68-57.1 0-.1.1-.2.2-.3 2.5-5 3-9.2 1.6-12.5-3.4-7.9-17.9-10.7-24-13.2-15.8-6.2-18-13.4-17-18.3 1.6-8.5 14.4-13.8 21.9-10.3 5.9 2.8 11.2 4.2 15.7 4.2 3.3 0 5.5-.8 6.6-1.4-1.4-23.9-4.7-58 3.8-77.1C159.1 100 206.7 96 220.7 96c.6 0 6.1-.1 6.7-.1 34.7 0 68 17.8 84.3 54.3 8.5 19.1 5.2 53.1 3.8 77.1 1.1.6 2.9 1.3 5.7 1.4 4.3-.2 9.2-1.6 14.7-4.2 4-1.9 9.6-1.6 13.6 0 6.3 2.3 10.3 6.8 10.4 11.9.1 6.5-5.7 12.1-17.2 16.6-1.4.6-3.1 1.1-4.9 1.7-6.5 2.1-16.4 5.2-19 11.5-1.4 3.3-.8 7.5 1.6 12.5.1.1.1.2.2.3.9 2 21.7 49.5 68 57.1 4 1 7.1 5.5 4.9 10.8z"],soundcloud:[640,512,[],"f1be","M111.4 256.3l5.8 65-5.8 68.3c-.3 2.5-2.2 4.4-4.4 4.4s-4.2-1.9-4.2-4.4l-5.6-68.3 5.6-65c0-2.2 1.9-4.2 4.2-4.2 2.2 0 4.1 2 4.4 4.2zm21.4-45.6c-2.8 0-4.7 2.2-5 5l-5 105.6 5 68.3c.3 2.8 2.2 5 5 5 2.5 0 4.7-2.2 4.7-5l5.8-68.3-5.8-105.6c0-2.8-2.2-5-4.7-5zm25.5-24.1c-3.1 0-5.3 2.2-5.6 5.3l-4.4 130 4.4 67.8c.3 3.1 2.5 5.3 5.6 5.3 2.8 0 5.3-2.2 5.3-5.3l5.3-67.8-5.3-130c0-3.1-2.5-5.3-5.3-5.3zM7.2 283.2c-1.4 0-2.2 1.1-2.5 2.5L0 321.3l4.7 35c.3 1.4 1.1 2.5 2.5 2.5s2.2-1.1 2.5-2.5l5.6-35-5.6-35.6c-.3-1.4-1.1-2.5-2.5-2.5zm23.6-21.9c-1.4 0-2.5 1.1-2.5 2.5l-6.4 57.5 6.4 56.1c0 1.7 1.1 2.8 2.5 2.8s2.5-1.1 2.8-2.5l7.2-56.4-7.2-57.5c-.3-1.4-1.4-2.5-2.8-2.5zm25.3-11.4c-1.7 0-3.1 1.4-3.3 3.3L47 321.3l5.8 65.8c.3 1.7 1.7 3.1 3.3 3.1 1.7 0 3.1-1.4 3.1-3.1l6.9-65.8-6.9-68.1c0-1.9-1.4-3.3-3.1-3.3zm25.3-2.2c-1.9 0-3.6 1.4-3.6 3.6l-5.8 70 5.8 67.8c0 2.2 1.7 3.6 3.6 3.6s3.6-1.4 3.9-3.6l6.4-67.8-6.4-70c-.3-2.2-2-3.6-3.9-3.6zm241.4-110.9c-1.1-.8-2.8-1.4-4.2-1.4-2.2 0-4.2.8-5.6 1.9-1.9 1.7-3.1 4.2-3.3 6.7v.8l-3.3 176.7 1.7 32.5 1.7 31.7c.3 4.7 4.2 8.6 8.9 8.6s8.6-3.9 8.6-8.6l3.9-64.2-3.9-177.5c-.4-3-2-5.8-4.5-7.2zm-26.7 15.3c-1.4-.8-2.8-1.4-4.4-1.4s-3.1.6-4.4 1.4c-2.2 1.4-3.6 3.9-3.6 6.7l-.3 1.7-2.8 160.8s0 .3 3.1 65.6v.3c0 1.7.6 3.3 1.7 4.7 1.7 1.9 3.9 3.1 6.4 3.1 2.2 0 4.2-1.1 5.6-2.5 1.7-1.4 2.5-3.3 2.5-5.6l.3-6.7 3.1-58.6-3.3-162.8c-.3-2.8-1.7-5.3-3.9-6.7zm-111.4 22.5c-3.1 0-5.8 2.8-5.8 6.1l-4.4 140.6 4.4 67.2c.3 3.3 2.8 5.8 5.8 5.8 3.3 0 5.8-2.5 6.1-5.8l5-67.2-5-140.6c-.2-3.3-2.7-6.1-6.1-6.1zm376.7 62.8c-10.8 0-21.1 2.2-30.6 6.1-6.4-70.8-65.8-126.4-138.3-126.4-17.8 0-35 3.3-50.3 9.4-6.1 2.2-7.8 4.4-7.8 9.2v249.7c0 5 3.9 8.6 8.6 9.2h218.3c43.3 0 78.6-35 78.6-78.3.1-43.6-35.2-78.9-78.5-78.9zm-296.7-60.3c-4.2 0-7.5 3.3-7.8 7.8l-3.3 136.7 3.3 65.6c.3 4.2 3.6 7.5 7.8 7.5 4.2 0 7.5-3.3 7.5-7.5l3.9-65.6-3.9-136.7c-.3-4.5-3.3-7.8-7.5-7.8zm-53.6-7.8c-3.3 0-6.4 3.1-6.4 6.7l-3.9 145.3 3.9 66.9c.3 3.6 3.1 6.4 6.4 6.4 3.6 0 6.4-2.8 6.7-6.4l4.4-66.9-4.4-145.3c-.3-3.6-3.1-6.7-6.7-6.7zm26.7 3.4c-3.9 0-6.9 3.1-6.9 6.9L227 321.3l3.9 66.4c.3 3.9 3.1 6.9 6.9 6.9s6.9-3.1 6.9-6.9l4.2-66.4-4.2-141.7c0-3.9-3-6.9-6.9-6.9z"],speakap:[448,512,[],"f3f3","M352 32H96C43.2 32 0 75.2 0 128v256c0 52.8 43.2 96 96 96h256c52.8 0 96-43.2 96-96V128c0-52.8-43.2-96-96-96zM221 382.9c-39.6 0-81.9-17.8-81.9-53.7V302H179v17.8c0 15.1 19.5 24.5 41.9 24.5 24.2 0 41.3-10.4 41.3-29.5 0-23.8-27.2-31.9-54.7-42.6-31.9-12.4-63.1-26.2-63.1-69.1 0-48 38.6-66.4 79.9-66.4 37.6 0 75.5 14.1 75.5 41.9v31.2h-39.9v-16.1c0-12.1-17.8-18.5-35.6-18.5-19.5 0-35.6 8.1-35.6 26.2 0 22.1 22.5 29.2 47 38.9 35.9 12.4 71.1 27.2 71.1 71.5.1 48.6-40.8 71.1-85.8 71.1z"],spotify:[496,512,[],"f1bc","M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8zm100.7 364.9c-4.2 0-6.8-1.3-10.7-3.6-62.4-37.6-135-39.2-206.7-24.5-3.9 1-9 2.6-11.9 2.6-9.7 0-15.8-7.7-15.8-15.8 0-10.3 6.1-15.2 13.6-16.8 81.9-18.1 165.6-16.5 237 26.2 6.1 3.9 9.7 7.4 9.7 16.5s-7.1 15.4-15.2 15.4zm26.9-65.6c-5.2 0-8.7-2.3-12.3-4.2-62.5-37-155.7-51.9-238.6-29.4-4.8 1.3-7.4 2.6-11.9 2.6-10.7 0-19.4-8.7-19.4-19.4s5.2-17.8 15.5-20.7c27.8-7.8 56.2-13.6 97.8-13.6 64.9 0 127.6 16.1 177 45.5 8.1 4.8 11.3 11 11.3 19.7-.1 10.8-8.5 19.5-19.4 19.5zm31-76.2c-5.2 0-8.4-1.3-12.9-3.9-71.2-42.5-198.5-52.7-280.9-29.7-3.6 1-8.1 2.6-12.9 2.6-13.2 0-23.3-10.3-23.3-23.6 0-13.6 8.4-21.3 17.4-23.9 35.2-10.3 74.6-15.2 117.5-15.2 73 0 149.5 15.2 205.4 47.8 7.8 4.5 12.9 10.7 12.9 22.6 0 13.6-11 23.3-23.2 23.3z"],"stack-exchange":[448,512,[],"f18d","M43.5 322.8h361.1V342c0 33-25.7 59.5-57.2 59.5h-16.6L254.9 480v-78.5H100.6c-31.5 0-57.2-26.5-57.2-59.5v-19.2zm0-20.7h361.1v-74.4H43.5v74.4zm0-95.7h361.1V132H43.5v74.4zM347.4 32H100.6c-31.5 0-57.2 26.5-57.2 59.2v19.5h361.1V91.2c0-32.7-25.6-59.2-57.1-59.2z"],"stack-overflow":[384,512,[],"f16c","M293.7 300l-181.2-84.5 16.7-36.5 181.3 84.7-16.8 36.3zm48-76L188.2 95.7l-25.5 30.8 153.5 128.3 25.5-30.8zm39.6-31.7L262 32l-32 24 119.3 160.3 32-24zM290.7 311L95 269.7 86.8 309l195.7 41 8.2-39zm31.6 129H42.7V320h-40v160h359.5V320h-40v120zm-39.8-80h-200v39.7h200V360z"],staylinked:[440,512,[],"f3f5","M201.6 127.4c4.1-3.2 10.3-3 13.8.5l170 167.3-2.7-2.7 44.3 41.3c3.7 3.5 3.3 9-.7 12.2l-198 163.9c-9.9 7.6-17.3.8-17.3.8L2.3 314.6c-3.5-3.5-3-9 1.2-12.2l45.8-34.9c4.2-3.2 10.4-3 13.9.5l151.9 147.5c3.7 3.5 10 3.7 14.2.4l93.2-74c4.1-3.2 4.5-8.7.9-12.2l-84-81.3c-3.6-3.5-9.9-3.7-14-.5l-.1.1c-4.1 3.2-10.4 3-14-.5l-68.1-64.3c-3.5-3.5-3.1-9 1.1-12.2l57.3-43.6m14.8 257.3c3.7 3.5 10.1 3.7 14.3.4l50.2-38.8-.3-.3 7.7-6c4.2-3.2 4.6-8.7.9-12.2l-57.1-54.4c-3.6-3.5-10-3.7-14.2-.5l-.1.1c-4.2 3.2-10.5 3.1-14.2-.4L109 180.8c-3.6-3.5-3.1-8.9 1.1-12.2l92.2-71.5c4.1-3.2 10.3-3 13.9.5l160.4 159c3.7 3.5 10 3.7 14.1.5l45.8-35.8c4.1-3.2 4.4-8.7.7-12.2L226.7 2.5c-1.5-1.2-8-5.5-16.3 1.1L3.6 165.7c-4.2 3.2-4.8 8.7-1.2 12.2l42.3 41.7"],steam:[496,512,[],"f1b6","M496 256c0 137-111.2 248-248.4 248-113.8 0-209.6-76.3-239-180.4l95.2 39.3c6.4 32.1 34.9 56.4 68.9 56.4 39.2 0 71.9-32.4 70.2-73.5l84.5-60.2c52.1 1.3 95.8-40.9 95.8-93.5 0-51.6-42-93.5-93.7-93.5s-93.7 42-93.7 93.5v1.2L176.6 279c-15.5-.9-30.7 3.4-43.5 12.1L0 236.1C10.2 108.4 117.1 8 247.6 8 384.8 8 496 119 496 256zM155.7 384.3l-30.5-12.6a52.79 52.79 0 0 0 27.2 25.8c26.9 11.2 57.8-1.6 69-28.4 5.4-13 5.5-27.3.1-40.3-5.4-13-15.5-23.2-28.5-28.6-12.9-5.4-26.7-5.2-38.9-.6l31.5 13c19.8 8.2 29.2 30.9 20.9 50.7-8.3 19.9-31 29.2-50.8 21zm173.8-129.9c-34.4 0-62.4-28-62.4-62.3s28-62.3 62.4-62.3 62.4 28 62.4 62.3-27.9 62.3-62.4 62.3zm.1-15.6c25.9 0 46.9-21 46.9-46.8 0-25.9-21-46.8-46.9-46.8s-46.9 21-46.9 46.8c.1 25.8 21.1 46.8 46.9 46.8z"],"steam-square":[448,512,[],"f1b7","M185.2 356.5c7.7-18.5-1-39.7-19.6-47.4l-29.5-12.2c11.4-4.3 24.3-4.5 36.4.5 12.2 5.1 21.6 14.6 26.7 26.7 5 12.2 5 25.6-.1 37.7-10.5 25.1-39.4 37-64.6 26.5-11.6-4.8-20.4-13.6-25.4-24.2l28.5 11.8c18.6 7.8 39.9-.9 47.6-19.4zM400 32H48C21.5 32 0 53.5 0 80v160.7l116.6 48.1c12-8.2 26.2-12.1 40.7-11.3l55.4-80.2v-1.1c0-48.2 39.3-87.5 87.6-87.5s87.6 39.3 87.6 87.5c0 49.2-40.9 88.7-89.6 87.5l-79 56.3c1.6 38.5-29.1 68.8-65.7 68.8-31.8 0-58.5-22.7-64.5-52.7L0 319.2V432c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-99.7 222.5c-32.2 0-58.4-26.1-58.4-58.3s26.2-58.3 58.4-58.3 58.4 26.2 58.4 58.3-26.2 58.3-58.4 58.3zm.1-14.6c24.2 0 43.9-19.6 43.9-43.8 0-24.2-19.6-43.8-43.9-43.8-24.2 0-43.9 19.6-43.9 43.8 0 24.2 19.7 43.8 43.9 43.8z"],"steam-symbol":[448,512,[],"f3f6","M395.5 177.5c0 33.8-27.5 61-61 61-33.8 0-61-27.3-61-61s27.3-61 61-61c33.5 0 61 27.2 61 61zm52.5.2c0 63-51 113.8-113.7 113.8L225 371.3c-4 43-40.5 76.8-84.5 76.8-40.5 0-74.7-28.8-83-67L0 358V250.7L97.2 290c15.1-9.2 32.2-13.3 52-11.5l71-101.7c.5-62.3 51.5-112.8 114-112.8C397 64 448 115 448 177.7zM203 363c0-34.7-27.8-62.5-62.5-62.5-4.5 0-9 .5-13.5 1.5l26 10.5c25.5 10.2 38 39 27.7 64.5-10.2 25.5-39.2 38-64.7 27.5-10.2-4-20.5-8.3-30.7-12.2 10.5 19.7 31.2 33.2 55.2 33.2 34.7 0 62.5-27.8 62.5-62.5zm207.5-185.3c0-42-34.3-76.2-76.2-76.2-42.3 0-76.5 34.2-76.5 76.2 0 42.2 34.3 76.2 76.5 76.2 41.9.1 76.2-33.9 76.2-76.2z"],"sticker-mule":[576,512,[],"f3f7","M353.1 509.8c-5.9 2.9-32.1 3.2-36.5-.5-4.1-3-2.2-11.9-1.5-15 2.2-15-2.5-7.9-9.8-11.5-3.1-1.5-4.1-5.5-4.6-10-.5-1.5-1-2.5-1.5-3.5-1.7-10.7 6.8-33.6 8.2-43.4 4.9-23.7-.7-37.2 1.5-46.9 3.7-16.2 4.1-3.5 4.1-29.9-1.4-25.9 3.3-36.9.5-38.9-14.8 0-64.3 10.7-112.2 2-46.1-8.9-59.4-29-65.4-30.9-10.3-4.5-23.2.5-27.3 7-.1.1-35 70.6-39.6 87.8-6.2 20.5-.5 47.4 4.1 66.8 0 .1 4.5 14.6 10.3 19.5 2.1 1.5 5.1 2.5 7.2 4.5 2.8 2.7 9.4 15.2 9.8 16 2.6 4.5 3.6 8-1.5 10.5-3.6 2-9.3 2.5-14.4 2.5-2.6.5-1.5 3.5-3.1 5-2.9 2.8-20.7 6.1-29.9 2.5-2.6-1-5.7-3-6.2-5-1.5-4 2.1-9-1-12.5-4.5-2.9-13.1-2-17-12-2.2-5.4-2.6-7.6-2.6-49.4 0-9.7-5.9-38.7-8.2-46.9-1.5-5.5-1.5-11.5 0-16 .3-.9 4.1-4.6 4.1-13-1-1.5-4.6-.5-5.1-1.5-10.4-80.6-5.9-79-7.7-98.3-1.5-16-10.9-43.9-6.7-64.3.5-2.4 3.4-21 24.2-38.9 31-26.7 48.4-38.3 159-11.5 1.1.4 66.3 21.1 110.7-9 15.5-11.3 28.8-11.3 35.5-16 .1-.1 61.7-52.1 87-65.3 47.2-29.4 69.9-16.7 75.1-18 4.7-1 13.4-25.8 17-25.8 5.5 0 1.6 20.2 3.6 25.9.5 2 3.6 5 6.2 5 2.3 0 1.7-.8 10.3-5 8.4-5.4 14.9-17.6 20.6-17 11.7 1.6-19 41.6-19 46.9 0 2 .2.8 4.6 9.5 2.6 5.5 4.6 13.5 6.2 20 8.3 29.7 5.7 14.6 13.4 36.9 20.2 50.1 20.6 45.2 20.6 52.9 0 7.5-4.1 11-7.2 16.5-1.5 3-4.6 7.5-7.2 8-2.7.7 7-1.5-13.4 2.5-7.2 1-13.4-4.5-14.9-9.5-1.6-4.7 2.8-10.1-11.8-22.9-10.3-10-21.1-11.3-31.9-17-9.8-5.7-11.9 1-18 8-18 22.9-34 46.9-52 69.8-11.8 15-24.2 30.4-33.5 47.4-3.9 6.8-9.5 28.1-10.3 29.9-6.2 17.7-5.5 25.8-16.5 68.3-3.1 10-5.7 21.4-8.7 32.4-2.2 6.8-7.4 49.3-.5 59.4 2.1 3.5 8.7 4.5 11.3 8 .1.1 9.6 18.2 9.3 20 0 6.1-9.4 5.6-11.3 6.5-4.8 2.9-3.8 5.9-6.4 7.4"],strava:[369,512,[],"f428","M301.6 292l-43.9 88.2-44.6-88.2h-67.6l112.2 220 111.5-220h-67.6zM151.4 0L0 292h89.2l62.2-116.1L213.1 292h88.5L151.4 0z"],stripe:[640,512,[],"f429","M640 233.6c0-45.5-22-81.4-64.2-81.4s-67.9 35.9-67.9 81.1c0 53.5 30.3 78.2 73.5 78.2 21.2 0 37.1-4.8 49.2-11.5v-33.4c-12.1 6.1-26 9.8-43.6 9.8-17.3 0-32.5-6.1-34.5-26.9h86.9c.2-2.3.6-11.6.6-15.9m-87.9-16.8c0-20 12.3-28.4 23.4-28.4 10.9 0 22.5 8.4 22.5 28.4h-45.9zm-112.9-64.6c-17.4 0-28.6 8.2-34.8 13.9l-2.3-11H363v204.8l44.4-9.4.1-50.2c6.4 4.7 15.9 11.2 31.4 11.2 31.8 0 60.8-23.2 60.8-79.6.1-51.6-29.3-79.7-60.5-79.7m-10.6 122.5c-10.4 0-16.6-3.8-20.9-8.4l-.3-66c4.6-5.1 11-8.8 21.2-8.8 16.2 0 27.4 18.2 27.4 41.4.1 23.9-10.9 41.8-27.4 41.8M346.4 96v36.2l-44.6 9.5v-36.2l44.6-9.5m-44.5 59.2h44.6v153.2h-44.6V155.2zm-47.8 13.1c10.4-19.1 31.1-15.2 37.1-13.1V196c-5.7-1.8-23.4-4.5-33.9 9.3v103.1H213V155.2h38.4l2.7 13.1m-89-13.1h33.7V193h-33.7v63.2c0 26.2 28 18 33.7 15.7v33.8c-5.9 3.2-16.6 5.9-31.2 5.9-26.3 0-46.1-17-46.1-43.3l.2-142.4 43.3-9.2.1 38.5zM44.9 200.3c0 20 67.9 10.5 67.9 63.4 0 32-25.4 47.8-62.3 47.8-15.3 0-32-3-48.5-10.1v-40c14.9 8.1 33.9 14.2 48.6 14.2 9.9 0 17-2.7 17-10.9 0-21.2-67.5-13.2-67.5-62.4 0-31.4 24-50.2 60-50.2 14.7 0 29.4 2.3 44.1 8.1V202c-13.5-7.3-30.7-11.4-44.2-11.4-9.3.1-15.1 2.8-15.1 9.7"],"stripe-s":[362,512,[],"f42a","M144.3 154.6c0-22.3 18.6-30.9 48.4-30.9 43.4 0 98.5 13.3 141.9 36.7V26.1C287.3 7.2 240.1 0 192.8 0 77.1 0 0 60.4 0 161.4c0 157.9 216.8 132.3 216.8 200.4 0 26.4-22.9 34.9-54.7 34.9-47.2 0-108.2-19.5-156.1-45.5v128.5c53 22.8 106.8 32.4 156 32.4 118.6 0 200.3-51 200.3-153.6 0-170.2-218-139.7-218-203.9"],studiovinari:[512,512,[],"f3f8","M480.3 187.7l4.2 28v28l-25.1 44.1-39.8 78.4-56.1 67.5-79.1 37.8-17.7 24.5-7.7 12-9.6 4s17.3-63.6 19.4-63.6c2.1 0 20.3.7 20.3.7l66.7-38.6-92.5 26.1-55.9 36.8-22.8 28-6.6 1.4 20.8-73.6 6.9-5.5 20.7 12.9 88.3-45.2 56.8-51.5 14.8-68.4-125.4 23.3 15.2-18.2-173.4-53.3 81.9-10.5-166-122.9L133.5 108 32.2 0l252.9 126.6-31.5-38L378 163 234.7 64l18.7 38.4-49.6-18.1L158.3 0l194.6 122L310 66.2l108 96.4 12-8.9-21-16.4 4.2-37.8L451 89.1l29.2 24.7 11.5 4.2-7 6.2 8.5 12-13.1 7.4-10.3 20.2 10.5 23.9z"],stumbleupon:[512,512,[],"f1a4","M502.9 266v69.7c0 62.1-50.3 112.4-112.4 112.4-61.8 0-112.4-49.8-112.4-111.3v-70.2l34.3 16 51.1-15.2V338c0 14.7 12 26.5 26.7 26.5S417 352.7 417 338v-72h85.9zm-224.7-58.2l34.3 16 51.1-15.2V173c0-60.5-51.1-109-112.1-109-60.8 0-112.1 48.2-112.1 108.2v162.4c0 14.9-12 26.7-26.7 26.7S86 349.5 86 334.6V266H0v69.7C0 397.7 50.3 448 112.4 448c61.6 0 112.4-49.5 112.4-110.8V176.9c0-14.7 12-26.7 26.7-26.7s26.7 12 26.7 26.7v30.9z"],"stumbleupon-circle":[496,512,[],"f1a3","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 177.5c-9.8 0-17.8 8-17.8 17.8v106.9c0 40.9-33.9 73.9-74.9 73.9-41.4 0-74.9-33.5-74.9-74.9v-46.5h57.3v45.8c0 10 8 17.8 17.8 17.8s17.8-7.9 17.8-17.8V200.1c0-40 34.2-72.1 74.7-72.1 40.7 0 74.7 32.3 74.7 72.6v23.7l-34.1 10.1-22.9-10.7v-20.6c.1-9.6-7.9-17.6-17.7-17.6zm167.6 123.6c0 41.4-33.5 74.9-74.9 74.9-41.2 0-74.9-33.2-74.9-74.2V263l22.9 10.7 34.1-10.1v47.1c0 9.8 8 17.6 17.8 17.6s17.8-7.9 17.8-17.6v-48h57.3c-.1 45.9-.1 46.4-.1 46.4z"],superpowers:[448,512,[],"f2dd","M448 32c-83.3 11-166.8 22-250 33-92 12.5-163.3 86.7-169 180-3.3 55.5 18 109.5 57.8 148.2L0 480c83.3-11 166.5-22 249.8-33 91.8-12.5 163.3-86.8 168.7-179.8 3.5-55.5-18-109.5-57.7-148.2L448 32zm-79.7 232.3c-4.2 79.5-74 139.2-152.8 134.5-79.5-4.7-140.7-71-136.3-151 4.5-79.2 74.3-139.3 153-134.5 79.3 4.7 140.5 71 136.1 151z"],supple:[640,512,[],"f3f9","M640 262.5c0 64.1-109 116.1-243.5 116.1-24.8 0-48.6-1.8-71.1-5 7.7.4 15.5.6 23.4.6 134.5 0 243.5-56.9 243.5-127.1 0-29.4-19.1-56.4-51.2-78 60 21.1 98.9 55.1 98.9 93.4zM47.7 227.9c-.1-70.2 108.8-127.3 243.3-127.6 7.9 0 15.6.2 23.3.5-22.5-3.2-46.3-4.9-71-4.9C108.8 96.3-.1 148.5 0 212.6c.1 38.3 39.1 72.3 99.3 93.3-32.3-21.5-51.5-48.6-51.6-78zm60.2 39.9s10.5 13.2 29.3 13.2c17.9 0 28.4-11.5 28.4-25.1 0-28-40.2-25.1-40.2-39.7 0-5.4 5.3-9.1 12.5-9.1 5.7 0 11.3 2.6 11.3 6.6v3.9h14.2v-7.9c0-12.1-15.4-16.8-25.4-16.8-16.5 0-28.5 10.2-28.5 24.1 0 26.6 40.2 25.4 40.2 39.9 0 6.6-5.8 10.1-12.3 10.1-11.9 0-20.7-10.1-20.7-10.1l-8.8 10.9zm120.8-73.6v54.4c0 11.3-7.1 17.8-17.8 17.8-10.7 0-17.8-6.5-17.8-17.7v-54.5h-15.8v55c0 18.9 13.4 31.9 33.7 31.9 20.1 0 33.4-13 33.4-31.9v-55h-15.7zm34.4 85.4h15.8v-29.5h15.5c16 0 27.2-11.5 27.2-28.1s-11.2-27.8-27.2-27.8h-39.1v13.4h7.8v72zm15.8-43v-29.1h12.9c8.7 0 13.7 5.7 13.7 14.4 0 8.9-5.1 14.7-14 14.7h-12.6zm57 43h15.8v-29.5h15.5c16 0 27.2-11.5 27.2-28.1s-11.2-27.8-27.2-27.8h-39.1v13.4h7.8v72zm15.7-43v-29.1h12.9c8.7 0 13.7 5.7 13.7 14.4 0 8.9-5 14.7-14 14.7h-12.6zm57.1 34.8c0 5.8 2.4 8.2 8.2 8.2h37.6c5.8 0 8.2-2.4 8.2-8.2v-13h-14.3v5.2c0 1.7-1 2.6-2.6 2.6h-18.6c-1.7 0-2.6-1-2.6-2.6v-61.2c0-5.7-2.4-8.2-8.2-8.2H401v13.4h5.2c1.7 0 2.6 1 2.6 2.6v61.2zm63.4 0c0 5.8 2.4 8.2 8.2 8.2H519c5.7 0 8.2-2.4 8.2-8.2v-13h-14.3v5.2c0 1.7-1 2.6-2.6 2.6h-19.7c-1.7 0-2.6-1-2.6-2.6v-20.3h27.7v-13.4H488v-22.4h19.2c1.7 0 2.6 1 2.6 2.6v5.2H524v-13c0-5.7-2.5-8.2-8.2-8.2h-51.6v13.4h7.8v63.9zm58.9-76v5.9h1.6v-5.9h2.7v-1.2h-7v1.2h2.7zm5.7-1.2v7.1h1.5v-5.7l2.3 5.7h1.3l2.3-5.7v5.7h1.5v-7.1h-2.3l-2.1 5.1-2.1-5.1h-2.4z"],telegram:[496,512,[],"f2c6","M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm121.8 169.9l-40.7 191.8c-3 13.6-11.1 16.9-22.4 10.5l-62-45.7-29.9 28.8c-3.3 3.3-6.1 6.1-12.5 6.1l4.4-63.1 114.9-103.8c5-4.4-1.1-6.9-7.7-2.5l-142 89.4-61.2-19.1c-13.3-4.2-13.6-13.3 2.8-19.7l239.1-92.2c11.1-4 20.8 2.7 17.2 19.5z"],"telegram-plane":[448,512,[],"f3fe","M446.7 98.6l-67.6 318.8c-5.1 22.5-18.4 28.1-37.3 17.5l-103-75.9-49.7 47.8c-5.5 5.5-10.1 10.1-20.7 10.1l7.4-104.9 190.9-172.5c8.3-7.4-1.8-11.5-12.9-4.1L117.8 284 16.2 252.2c-22.1-6.9-22.5-22.1 4.6-32.7L418.2 66.4c18.4-6.9 34.5 4.1 28.5 32.2z"],"tencent-weibo":[384,512,[],"f1d5","M72.3 495.8c1.4 19.9-27.6 22.2-29.7 2.9C31 368.8 73.7 259.2 144 185.5c-15.6-34 9.2-77.1 50.6-77.1 30.3 0 55.1 24.6 55.1 55.1 0 44-49.5 70.8-86.9 45.1-65.7 71.3-101.4 169.8-90.5 287.2zM192 .1C66.1.1-12.3 134.3 43.7 242.4 52.4 259.8 79 246.9 70 229 23.7 136.4 91 29.8 192 29.8c75.4 0 136.9 61.4 136.9 136.9 0 90.8-86.9 153.9-167.7 133.1-19.1-4.1-25.6 24.4-6.6 29.1 110.7 23.2 204-60 204-162.3C358.6 74.7 284 .1 192 .1z"],themeisle:[512,512,[],"f2b2","M208 88.286c0-10 6.286-21.714 17.715-21.714 11.142 0 17.714 11.714 17.714 21.714 0 10.285-6.572 21.714-17.714 21.714C214.286 110 208 98.571 208 88.286zm304 160c0 36.001-11.429 102.286-36.286 129.714-22.858 24.858-87.428 61.143-120.857 70.572l-1.143.286v32.571c0 16.286-12.572 30.571-29.143 30.571-10 0-19.429-5.714-24.572-14.286-5.427 8.572-14.856 14.286-24.856 14.286-10 0-19.429-5.714-24.858-14.286-5.142 8.572-14.571 14.286-24.57 14.286-10.286 0-19.429-5.714-24.858-14.286-5.143 8.572-14.571 14.286-24.571 14.286-18.857 0-29.429-15.714-29.429-32.857-16.286 12.285-35.715 19.428-56.571 19.428-22 0-43.429-8.285-60.286-22.857 10.285-.286 20.571-2.286 30.285-5.714-20.857-5.714-39.428-18.857-52-36.286 21.37 4.645 46.209 1.673 67.143-11.143-22-22-56.571-58.857-68.572-87.428C1.143 321.714 0 303.714 0 289.429c0-49.714 20.286-160 86.286-160 10.571 0 18.857 4.858 23.143 14.857a158.792 158.792 0 0 1 12-15.428c2-2.572 5.714-5.429 7.143-8.286 7.999-12.571 11.714-21.142 21.714-34C182.571 45.428 232 17.143 285.143 17.143c6 0 12 .285 17.714 1.143C313.714 6.571 328.857 0 344.572 0c14.571 0 29.714 6 40 16.286.857.858 1.428 2.286 1.428 3.428 0 3.714-10.285 13.429-12.857 16.286 4.286 1.429 15.714 6.858 15.714 12 0 2.857-2.857 5.143-4.571 7.143 31.429 27.714 49.429 67.143 56.286 108 4.286-5.143 10.285-8.572 17.143-8.572 10.571 0 20.857 7.144 28.571 14.001C507.143 187.143 512 221.714 512 248.286zM188 89.428c0 18.286 12.571 37.143 32.286 37.143 19.714 0 32.285-18.857 32.285-37.143 0-18-12.571-36.857-32.285-36.857-19.715 0-32.286 18.858-32.286 36.857zM237.714 194c0-19.714 3.714-39.143 8.571-58.286-52.039 79.534-13.531 184.571 68.858 184.571 21.428 0 42.571-7.714 60-20 2-7.429 3.714-14.857 3.714-22.572 0-14.286-6.286-21.428-20.572-21.428-4.571 0-9.143.857-13.429 1.714-63.343 12.668-107.142 3.669-107.142-63.999zm-41.142 254.858c0-11.143-8.858-20.857-20.286-20.857-11.429 0-20 9.715-20 20.857v32.571c0 11.143 8.571 21.142 20 21.142 11.428 0 20.286-9.715 20.286-21.142v-32.571zm49.143 0c0-11.143-8.572-20.857-20-20.857-11.429 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.857 21.142 20.286 21.142 11.428 0 20-10 20-21.142v-32.571zm49.713 0c0-11.143-8.857-20.857-20.285-20.857-11.429 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.857 21.142 20.286 21.142 11.428 0 20.285-9.715 20.285-21.142v-32.571zm49.715 0c0-11.143-8.857-20.857-20.286-20.857-11.428 0-20.286 9.715-20.286 20.857v32.571c0 11.143 8.858 21.142 20.286 21.142 11.429 0 20.286-10 20.286-21.142v-32.571zM421.714 286c-30.857 59.142-90.285 102.572-158.571 102.572-96.571 0-160.571-84.572-160.571-176.572 0-16.857 2-33.429 6-49.714-20 33.715-29.714 72.572-29.714 111.429 0 60.286 24.857 121.715 71.429 160.857 5.143-9.714 14.857-16.286 26-16.286 10 0 19.428 5.714 24.571 14.286 5.429-8.571 14.571-14.286 24.858-14.286 10 0 19.428 5.714 24.571 14.286 5.429-8.571 14.857-14.286 24.858-14.286 10 0 19.428 5.714 24.857 14.286 5.143-8.571 14.571-14.286 24.572-14.286 10.857 0 20.857 6.572 25.714 16 43.427-36.286 68.569-92 71.426-148.286zm10.572-99.714c0-53.714-34.571-105.714-92.572-105.714-30.285 0-58.571 15.143-78.857 36.857C240.862 183.812 233.41 254 302.286 254c28.805 0 97.357-28.538 84.286 36.857 28.857-26 45.714-65.714 45.714-104.571z"],trello:[448,512,[],"f181","M392 32H56C25.1 32 0 57.1 0 88v336c0 30.9 25.1 56 56 56h336c30.9 0 56-25.1 56-56V88c0-30.9-25.1-56-56-56zM194.9 371.4c0 14.8-12 26.9-26.9 26.9H85.1c-14.8 0-26.9-12-26.9-26.9V117.1c0-14.8 12-26.9 26.9-26.9H168c14.8 0 26.9 12 26.9 26.9v254.3zm194.9-112c0 14.8-12 26.9-26.9 26.9H280c-14.8 0-26.9-12-26.9-26.9V117.1c0-14.8 12-26.9 26.9-26.9h82.9c14.8 0 26.9 12 26.9 26.9v142.3z"],tripadvisor:[576,512,[],"f262","M166.4 280.521c0 13.236-10.73 23.966-23.966 23.966s-23.966-10.73-23.966-23.966 10.73-23.966 23.966-23.966 23.966 10.729 23.966 23.966zm264.962-23.956c-13.23 0-23.956 10.725-23.956 23.956 0 13.23 10.725 23.956 23.956 23.956 13.23 0 23.956-10.725 23.956-23.956-.001-13.231-10.726-23.956-23.956-23.956zm89.388 139.49c-62.667 49.104-153.276 38.109-202.379-24.559l-30.979 46.325-30.683-45.939c-48.277 60.39-135.622 71.891-197.885 26.055-64.058-47.158-77.759-137.316-30.601-201.374A186.762 186.762 0 0 0 0 139.416l90.286-.05a358.48 358.48 0 0 1 197.065-54.03 350.382 350.382 0 0 1 192.181 53.349l96.218.074a185.713 185.713 0 0 0-28.352 57.649c46.793 62.747 34.964 151.37-26.648 199.647zM259.366 281.761c-.007-63.557-51.535-115.075-115.092-115.068C80.717 166.7 29.2 218.228 29.206 281.785c.007 63.557 51.535 115.075 115.092 115.068 63.513-.075 114.984-51.539 115.068-115.052v-.04zm28.591-10.455c5.433-73.44 65.51-130.884 139.12-133.022a339.146 339.146 0 0 0-139.727-27.812 356.31 356.31 0 0 0-140.164 27.253c74.344 1.582 135.299 59.424 140.771 133.581zm251.706-28.767c-21.992-59.634-88.162-90.148-147.795-68.157-59.634 21.992-90.148 88.162-68.157 147.795v.032c22.038 59.607 88.198 90.091 147.827 68.113 59.615-22.004 90.113-88.162 68.125-147.783zm-326.039 37.975v.115c-.057 39.328-31.986 71.163-71.314 71.106-39.328-.057-71.163-31.986-71.106-71.314.057-39.328 31.986-71.163 71.314-71.106 39.259.116 71.042 31.94 71.106 71.199zm-24.512 0v-.084c-.051-25.784-20.994-46.645-46.778-46.594-25.784.051-46.645 20.994-46.594 46.777.051 25.784 20.994 46.645 46.777 46.594 25.726-.113 46.537-20.968 46.595-46.693zm313.423 0v.048c-.02 39.328-31.918 71.194-71.247 71.173s-71.194-31.918-71.173-71.247c.02-39.328 31.918-71.194 71.247-71.173 39.29.066 71.121 31.909 71.173 71.199zm-24.504-.008c-.009-25.784-20.918-46.679-46.702-46.67-25.784.009-46.679 20.918-46.67 46.702.009 25.784 20.918 46.678 46.702 46.67 25.765-.046 46.636-20.928 46.67-46.693v-.009z"],tumblr:[320,512,[],"f173","M309.8 480.3c-13.6 14.5-50 31.7-97.4 31.7-120.8 0-147-88.8-147-140.6v-144H17.9c-5.5 0-10-4.5-10-10v-68c0-7.2 4.5-13.6 11.3-16 62-21.8 81.5-76 84.3-117.1.8-11 6.5-16.3 16.1-16.3h70.9c5.5 0 10 4.5 10 10v115.2h83c5.5 0 10 4.4 10 9.9v81.7c0 5.5-4.5 10-10 10h-83.4V360c0 34.2 23.7 53.6 68 35.8 4.8-1.9 9-3.2 12.7-2.2 3.5.9 5.8 3.4 7.4 7.9l22 64.3c1.8 5 3.3 10.6-.4 14.5z"],"tumblr-square":[448,512,[],"f174","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-82.3 364.2c-8.5 9.1-31.2 19.8-60.9 19.8-75.5 0-91.9-55.5-91.9-87.9v-90h-29.7c-3.4 0-6.2-2.8-6.2-6.2v-42.5c0-4.5 2.8-8.5 7.1-10 38.8-13.7 50.9-47.5 52.7-73.2.5-6.9 4.1-10.2 10-10.2h44.3c3.4 0 6.2 2.8 6.2 6.2v72h51.9c3.4 0 6.2 2.8 6.2 6.2v51.1c0 3.4-2.8 6.2-6.2 6.2h-52.1V321c0 21.4 14.8 33.5 42.5 22.4 3-1.2 5.6-2 8-1.4 2.2.5 3.6 2.1 4.6 4.9l13.8 40.2c1 3.2 2 6.7-.3 9.1z"],twitch:[448,512,[],"f1e8","M40.1 32L10 108.9v314.3h107V480h60.2l56.8-56.8h87l117-117V32H40.1zm357.8 254.1L331 353H224l-56.8 56.8V353H76.9V72.1h321v214zM331 149v116.9h-40.1V149H331zm-107 0v116.9h-40.1V149H224z"],twitter:[512,512,[],"f099","M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"],"twitter-square":[448,512,[],"f081","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-48.9 158.8c.2 2.8.2 5.7.2 8.5 0 86.7-66 186.6-186.6 186.6-37.2 0-71.7-10.8-100.7-29.4 5.3.6 10.4.8 15.8.8 30.7 0 58.9-10.4 81.4-28-28.8-.6-53-19.5-61.3-45.5 10.1 1.5 19.2 1.5 29.6-1.2-30-6.1-52.5-32.5-52.5-64.4v-.8c8.7 4.9 18.9 7.9 29.6 8.3a65.447 65.447 0 0 1-29.2-54.6c0-12.2 3.2-23.4 8.9-33.1 32.3 39.8 80.8 65.8 135.2 68.6-9.3-44.5 24-80.6 64-80.6 18.9 0 35.9 7.9 47.9 20.7 14.8-2.8 29-8.3 41.6-15.8-4.9 15.2-15.2 28-28.8 36.1 13.2-1.4 26-5.1 37.8-10.2-8.9 13.1-20.1 24.7-32.9 34z"],typo3:[433,512,[],"f42b","M330.8 341c-7 2.3-11.6 2.3-18.5 2.3-57.2 0-140.6-198.5-140.6-264.9 0-24.7 5.4-32.4 13.9-39.4-69.5 8.5-149.3 34-176.3 66.4-5.4 7.7-9.3 20.8-9.3 37.1C0 246 106.8 480 184.1 480c36.3 0 97.3-59.5 146.7-139M294.5 32c71.8 0 138.8 11.6 138.8 52.5 0 82.6-52.5 182.3-78.8 182.3-47.9 0-101.7-132.1-101.7-198.5 0-30.9 11.6-36.3 41.7-36.3"],uber:[448,512,[],"f402","M414.1 32H33.9C15.2 32 0 47.2 0 65.9V446c0 18.8 15.2 34 33.9 34H414c18.7 0 33.9-15.2 33.9-33.9V65.9C448 47.2 432.8 32 414.1 32zM237.6 391.1C163 398.6 96.4 344.2 88.9 269.6h94.4V290c0 3.7 3 6.8 6.8 6.8H258c3.7 0 6.8-3 6.8-6.8v-67.9c0-3.7-3-6.8-6.8-6.8h-67.9c-3.7 0-6.8 3-6.8 6.8v20.4H88.9c7-69.4 65.4-122.2 135.1-122.2 69.7 0 128.1 52.8 135.1 122.2 7.5 74.5-46.9 141.1-121.5 148.6z"],uikit:[448,512,[],"f403","M443.9 128v256L218 512 0 384V169.7l87.6 45.1v117l133.5 75.5 135.8-75.5v-151l-101.1-57.6 87.6-53.1L443.9 128zM308.6 49.1L223.8 0l-88.6 54.8 86 47.3 87.4-53z"],uniregistry:[384,512,[],"f404","M281.1 220.1H384v-14.8H281.1v14.8zm0-37.1H384v-12.4H281.1V183zm0 74.2H384v-17.3H281.1v17.3zm-157.7 86.7H8.5c2.6 8.5 5.8 16.8 9.6 24.8h138.3c-12.9-5.7-24.1-14.2-33-24.8m145.7-12.4h109.7c1.8-7.3 3.1-14.7 3.9-22.3H278.3c-2.1 7.9-5.2 15.4-9.2 22.3m-41.5 37.1H367c3.7-8 5.8-16.2 8.5-24.8h-115c-8.8 10.7-20.1 19.2-32.9 24.8M384 32H281.1v2.5H384V32zM192 480c39.5 0 76.2-11.8 106.8-32.2H85.3C115.8 468.2 152.5 480 192 480m89.1-334.2H384V136H281.1v9.8zm0-37.1H384v-7.4H281.1v7.4zm0-37.1H384v-4.9H281.1v4.9zm-178.2 99H0V183h102.9v-12.4zM38.8 405.7h305.3c6.7-8.5 12.6-17.6 17.8-27.2H23c5.2 9.6 9.2 18.7 15.8 27.2m64.1-118.8v-12.4H0v12.4c0 2.5 0 5 .1 7.4h103.1c-.2-2.4-.3-4.9-.3-7.4m178.2 0c0 2.5-.1 5-.4 7.4h103.1c.1-2.5.2-4.9.2-7.4v-12.4H281.1v12.4zm-203 156h227.7c11.8-8.7 22.7-18.6 32.2-29.7H44.9c9.6 11 21.4 21 33.2 29.7m24.8-376.2H0v4.9h102.9v-4.9zm0-34.7H0v2.5h102.9V32zm0 173.3H0v14.8h102.9v-14.8zm0 34.6H0v17.3h102.9v-17.3zm0-103.9H0v9.9h102.9V136zm0-34.7H0v7.4h102.9v-7.4zm2.8 207.9H1.3c.9 7.6 2.2 15 3.9 22.3h109.7c-4-6.9-7.2-14.4-9.2-22.3"],untappd:[640,512,[],"f405","M401.3 49.9c-79.8 160.1-84.6 152.5-87.9 173.2l-5.2 32.8c-1.9 12-6.6 23.5-13.7 33.4L145.6 497.1c-7.6 10.6-20.4 16.2-33.4 14.6-40.3-5-77.8-32.2-95.3-68.5-5.7-11.8-4.5-25.8 3.1-36.4l148.9-207.9c7.1-9.9 16.4-18 27.2-23.7l29.3-15.5c18.5-9.8 9.7-11.9 135.6-138.9 1-4.8 1-7.3 3.6-8 3-.7 6.6-1 6.3-4.6l-.4-4.6c-.2-1.9 1.3-3.6 3.2-3.6 4.5-.1 13.2 1.2 25.6 10 12.3 8.9 16.4 16.8 17.7 21.1.6 1.8-.6 3.7-2.4 4.2l-4.5 1.1c-3.4.9-2.5 4.4-2.3 7.4.1 2.8-2.3 3.6-6.5 6.1zM230.1 36.4c3.4.9 2.5 4.4 2.3 7.4-.2 2.7 2.1 3.5 6.4 6 7.9 15.9 15.3 30.5 22.2 44 .7 1.3 2.3 1.5 3.3.5 11.2-12 24.6-26.2 40.5-42.6 1.3-1.4 1.4-3.5.1-4.9-8-8.2-16.5-16.9-25.6-26.1-1-4.7-1-7.3-3.6-8-3-.8-6.6-1-6.3-4.6.3-3.3 1.4-8.1-2.8-8.2-4.5-.1-13.2 1.1-25.6 10-12.3 8.9-16.4 16.8-17.7 21.1-1.4 4.2 3.6 4.6 6.8 5.4zM620 406.7L471.2 198.8c-13.2-18.5-26.6-23.4-56.4-39.1-11.2-5.9-14.2-10.9-30.5-28.9-1-1.1-2.9-.9-3.6.5-46.3 88.8-47.1 82.8-49 94.8-1.7 10.7-1.3 20 .3 29.8 1.9 12 6.6 23.5 13.7 33.4l148.9 207.9c7.6 10.6 20.2 16.2 33.1 14.7 40.3-4.9 78-32 95.7-68.6 5.4-11.9 4.3-25.9-3.4-36.6z"],usb:[640,512,[],"f287","M641.5 256c0 3.1-1.7 6.1-4.5 7.5L547.9 317c-1.4.8-2.8 1.4-4.5 1.4-1.4 0-3.1-.3-4.5-1.1-2.8-1.7-4.5-4.5-4.5-7.8v-35.6H295.7c25.3 39.6 40.5 106.9 69.6 106.9H392V354c0-5 3.9-8.9 8.9-8.9H490c5 0 8.9 3.9 8.9 8.9v89.1c0 5-3.9 8.9-8.9 8.9h-89.1c-5 0-8.9-3.9-8.9-8.9v-26.7h-26.7c-75.4 0-81.1-142.5-124.7-142.5H140.3c-8.1 30.6-35.9 53.5-69 53.5C32 327.3 0 295.3 0 256s32-71.3 71.3-71.3c33.1 0 61 22.8 69 53.5 39.1 0 43.9 9.5 74.6-60.4C255 88.7 273 95.7 323.8 95.7c7.5-20.9 27-35.6 50.4-35.6 29.5 0 53.5 23.9 53.5 53.5s-23.9 53.5-53.5 53.5c-23.4 0-42.9-14.8-50.4-35.6H294c-29.1 0-44.3 67.4-69.6 106.9h310.1v-35.6c0-3.3 1.7-6.1 4.5-7.8 2.8-1.7 6.4-1.4 8.9.3l89.1 53.5c2.8 1.1 4.5 4.1 4.5 7.2z"],ussunnah:[512,512,[],"f407","M156.8 285.1l5.7 14.4h-8.2c-1.3-3.2-3.1-7.7-3.8-9.5-2.5-6.3-1.1-8.4 0-10 1.9-2.7 3.2-4.4 3.6-5.2 0 2.2.8 5.7 2.7 10.3zm297.3 18.8c-2.1 13.8-5.7 27.1-10.5 39.7l43 23.4-44.8-18.8c-5.3 13.2-12 25.6-19.9 37.2l34.2 30.2-36.8-26.4c-8.4 11.8-18 22.6-28.7 32.3l24.9 34.7-28.1-31.8c-11 9.6-23.1 18-36.1 25.1l15.7 37.2-19.3-35.3c-13.1 6.8-27 12.1-41.6 15.9l6.7 38.4-10.5-37.4c-14.3 3.4-29.2 5.3-44.5 5.4L256 512l-1.9-38.4c-15.3-.1-30.2-2-44.5-5.3L199 505.6l6.7-38.2c-14.6-3.7-28.6-9.1-41.7-15.8l-19.2 35.1 15.6-37c-13-7-25.2-15.4-36.2-25.1l-27.9 31.6 24.7-34.4c-10.7-9.7-20.4-20.5-28.8-32.3l-36.5 26.2 33.9-29.9c-7.9-11.6-14.6-24.1-20-37.3l-44.4 18.7L67.8 344c-4.8-12.7-8.4-26.1-10.5-39.9l-51 9 50.3-14.2c-1.1-8.5-1.7-17.1-1.7-25.9 0-4.7.2-9.4.5-14.1L0 256l56-2.8c1.3-13.1 3.8-25.8 7.5-38.1L6.4 199l58.9 10.4c4-12 9.1-23.5 15.2-34.4l-55.1-30 58.3 24.6C90 159 97.2 149.2 105.3 140L55.8 96.4l53.9 38.7c8.1-8.6 17-16.5 26.6-23.6l-40-55.6 45.6 51.6c9.5-6.6 19.7-12.3 30.3-17.2l-27.3-64.9 33.8 62.1c10.5-4.4 21.4-7.9 32.7-10.4L199 6.4l19.5 69.2c11-2.1 22.3-3.2 33.8-3.4L256 0l3.6 72.2c11.5.2 22.8 1.4 33.8 3.5L313 6.4l-12.4 70.7c11.3 2.6 22.2 6.1 32.6 10.5l33.9-62.2-27.4 65.1c10.6 4.9 20.7 10.7 30.2 17.2l45.8-51.8-40.1 55.9c9.5 7.1 18.4 15 26.5 23.6l54.2-38.9-49.7 43.9c8 9.1 15.2 18.9 21.5 29.4l58.7-24.7-55.5 30.2c6.1 10.9 11.1 22.3 15.1 34.3l59.3-10.4-57.5 16.2c3.7 12.2 6.2 24.9 7.5 37.9L512 256l-56 2.8c.3 4.6.5 9.3.5 14.1 0 8.7-.6 17.3-1.6 25.8l50.7 14.3-51.5-9.1zm-21.8-31c0-97.5-79-176.5-176.5-176.5s-176.5 79-176.5 176.5 79 176.5 176.5 176.5 176.5-79 176.5-176.5zm-24 0c0 84.3-68.3 152.6-152.6 152.6s-152.6-68.3-152.6-152.6 68.3-152.6 152.6-152.6 152.6 68.3 152.6 152.6zM195 241c0 2.1 1.3 3.8 3.6 5.1 3.3 1.9 6.2 4.6 8.2 8.2 2.8-5.7 4.3-9.5 4.3-11.2 0-2.2-1.1-4.4-3.2-7-2.1-2.5-3.2-5.2-3.3-7.7-6.5 6.8-9.6 10.9-9.6 12.6zm-40.7-19c0 2.1 1.3 3.8 3.6 5.1 3.5 1.9 6.2 4.6 8.2 8.2 2.8-5.7 4.3-9.5 4.3-11.2 0-2.2-1.1-4.4-3.2-7-2.1-2.5-3.2-5.2-3.3-7.7-6.5 6.8-9.6 10.9-9.6 12.6zm-19 0c0 2.1 1.3 3.8 3.6 5.1 3.3 1.9 6.2 4.6 8.2 8.2 2.8-5.7 4.3-9.5 4.3-11.2 0-2.2-1.1-4.4-3.2-7-2.1-2.5-3.2-5.2-3.3-7.7-6.4 6.8-9.6 10.9-9.6 12.6zm204.9 87.9c-8.4-3-8.7-6.8-8.7-15.6V182c-8.2 12.5-14.2 18.6-18 18.6 6.3 14.4 9.5 23.9 9.5 28.3v64.3c0 2.2-2.2 6.5-4.7 6.5h-18c-2.8-7.5-10.2-26.9-15.3-40.3-2 2.5-7.2 9.2-10.7 13.7 2.4 1.6 4.1 3.6 5.2 6.3 2.6 6.7 6.4 16.5 7.9 20.2h-9.2c-3.9-10.4-9.6-25.4-11.8-31.1-2 2.5-7.2 9.2-10.7 13.7 2.4 1.6 4.1 3.6 5.2 6.3.8 2 2.8 7.3 4.3 10.9H256c-1.5-4.1-5.6-14.6-8.4-22-2 2.5-7.2 9.2-10.7 13.7 2.5 1.6 4.3 3.6 5.2 6.3.2.6.5 1.4.6 1.7H225c-4.6-13.9-11.4-27.7-11.4-34.1 0-2.2.3-5.1 1.1-8.2-8.8 10.8-14 15.9-14 25 0 7.5 10.4 28.3 10.4 33.3 0 1.7-.5 3.3-1.4 4.9-9.6-12.7-15.5-20.7-18.8-20.7h-12l-11.2-28c-3.8-9.6-5.7-16-5.7-18.8 0-3.8.5-7.7 1.7-12.2-1 1.3-3.7 4.7-5.5 7.1-.8-2.1-3.1-7.7-4.6-11.5-2.1 2.5-7.5 9.1-11.2 13.6.9 2.3 3.3 8.1 4.9 12.2-2.5 3.3-9.1 11.8-13.6 17.7-4 5.3-5.8 13.3-2.7 21.8 2.5 6.7 2 7.9-1.7 14.1H191c5.5 0 14.3 14 15.5 22 13.2-16 15.4-19.6 16.8-21.6h107c3.9 0 7.2-1.9 9.9-5.8zm20.1-26.6V181.7c-9 12.5-15.9 18.6-20.7 18.6 7.1 14.4 10.7 23.9 10.7 28.3v66.3c0 17.5 8.6 20.4 24 20.4 8.1 0 12.5-.8 13.7-2.7-4.3-1.6-7.6-2.5-9.9-3.3-8.1-3.2-17.8-7.4-17.8-26z"],vaadin:[448,512,[],"f408","M224.5 140.7c1.5-17.6 4.9-52.7 49.8-52.7h98.6c20.7 0 32.1-7.8 32.1-21.6V54.1c0-12.2 9.3-22.1 21.5-22.1S448 41.9 448 54.1v36.5c0 42.9-21.5 62-66.8 62H280.7c-30.1 0-33 14.7-33 27.1 0 1.3-.1 2.5-.2 3.7-.7 12.3-10.9 22.2-23.4 22.2s-22.7-9.8-23.4-22.2c-.1-1.2-.2-2.4-.2-3.7 0-12.3-3-27.1-33-27.1H66.8c-45.3 0-66.8-19.1-66.8-62V54.1C0 41.9 9.4 32 21.6 32s21.5 9.9 21.5 22.1v12.3C43.1 80.2 54.5 88 75.2 88h98.6c44.8 0 48.3 35.1 49.8 52.7h.9zM224 456c11.5 0 21.4-7 25.7-16.3 1.1-1.8 97.1-169.6 98.2-171.4 11.9-19.6-3.2-44.3-27.2-44.3-13.9 0-23.3 6.4-29.8 20.3L224 362l-66.9-117.7c-6.4-13.9-15.9-20.3-29.8-20.3-24 0-39.1 24.6-27.2 44.3 1.1 1.9 97.1 169.6 98.2 171.4 4.3 9.3 14.2 16.3 25.7 16.3z"],viacoin:[384,512,[],"f237","M384 32h-64l-80.7 192h-94.5L64 32H0l48 112H0v48h68.5l13.8 32H0v48h102.8L192 480l89.2-208H384v-48h-82.3l13.8-32H384v-48h-48l48-112zM192 336l-27-64h54l-27 64z"],viadeo:[448,512,[],"f2a9","M276.2 150.5v.7C258.3 98.6 233.6 47.8 205.4 0c43.3 29.2 67 100 70.8 150.5zm32.7 121.7c7.6 18.2 11 37.5 11 57 0 77.7-57.8 141-137.8 139.4l3.8-.3c74.2-46.7 109.3-118.6 109.3-205.1 0-38.1-6.5-75.9-18.9-112 1 11.7 1 23.7 1 35.4 0 91.8-18.1 241.6-116.6 280C95 455.2 49.4 398 49.4 329.2c0-75.6 57.4-142.3 135.4-142.3 16.8 0 33.7 3.1 49.1 9.6 1.7-15.1 6.5-29.9 13.4-43.3-19.9-7.2-41.2-10.7-62.5-10.7-161.5 0-238.7 195.9-129.9 313.7 67.9 74.6 192 73.9 259.8 0 56.6-61.3 60.9-142.4 36.4-201-12.7 8-27.1 13.9-42.2 17zM418.1 11.7c-31 66.5-81.3 47.2-115.8 80.1-12.4 12-20.6 34-20.6 50.5 0 14.1 4.5 27.1 12 38.8 47.4-11 98.3-46 118.2-90.7-.7 5.5-4.8 14.4-7.2 19.2-20.3 35.7-64.6 65.6-99.7 84.9 14.8 14.4 33.7 25.8 55 25.8 79 0 110.1-134.6 58.1-208.6z"],"viadeo-square":[448,512,[],"f2aa","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM280.7 381.2c-42.4 46.2-120 46.6-162.4 0-68-73.6-19.8-196.1 81.2-196.1 13.3 0 26.6 2.1 39.1 6.7-4.3 8.4-7.3 17.6-8.4 27.1-9.7-4.1-20.2-6-30.7-6-48.8 0-84.6 41.7-84.6 88.9 0 43 28.5 78.7 69.5 85.9 61.5-24 72.9-117.6 72.9-175 0-7.3 0-14.8-.6-22.1-11.2-32.9-26.6-64.6-44.2-94.5 27.1 18.3 41.9 62.5 44.2 94.1v.4c7.7 22.5 11.8 46.2 11.8 70 0 54.1-21.9 99-68.3 128.2l-2.4.2c50 1 86.2-38.6 86.2-87.2 0-12.2-2.1-24.3-6.9-35.7 9.5-1.9 18.5-5.6 26.4-10.5 15.3 36.6 12.6 87.3-22.8 125.6zM309 233.7c-13.3 0-25.1-7.1-34.4-16.1 21.9-12 49.6-30.7 62.3-53 1.5-3 4.1-8.6 4.5-12-12.5 27.9-44.2 49.8-73.9 56.7-4.7-7.3-7.5-15.5-7.5-24.3 0-10.3 5.2-24.1 12.9-31.6 21.6-20.5 53-8.5 72.4-50 32.5 46.2 13.1 130.3-36.3 130.3z"],viber:[512,512,[],"f409","M430.7 49.9C418 38.2 366.6.9 252.1.4c0 0-135.1-8.1-200.9 52.3C14.6 89.3 1.7 142.9.3 209.4c-1.4 66.5-3.1 191.1 117 224.9h.1l-.1 51.6s-.8 20.9 13 25.1c16.6 5.2 26.4-10.7 42.3-27.8 8.7-9.4 20.7-23.2 29.8-33.7 82.2 6.9 145.3-8.9 152.5-11.2 16.6-5.4 110.5-17.4 125.7-142 15.8-128.5-7.6-209.7-49.9-246.4zM444.6 287c-12.9 104-89 110.6-103 115.1-6 1.9-61.5 15.7-131.2 11.2 0 0-52 62.7-68.2 79-5.3 5.3-11.1 4.8-11-5.7 0-6.9.4-85.7.4-85.7-.1 0-.1 0 0 0C29.9 372.7 35.8 266.6 37 211.1c1.1-55.5 11.6-101 42.6-131.6C135.3 29 250 36.5 250 36.5c96.9.4 143.3 29.6 154.1 39.4 35.7 30.6 53.9 103.8 40.5 211.1zm-138.9-80.8c.4 8.6-12.5 9.2-12.9.6-1.1-22-11.4-32.7-32.6-33.9-8.6-.5-7.8-13.4.7-12.9 27.9 1.5 43.4 17.5 44.8 46.2zm20.3 11.3c1-42.4-25.5-75.6-75.8-79.3-8.5-.6-7.6-13.5.9-12.9 58 4.2 88.9 44.1 87.8 92.5-.2 8.6-13.1 8.2-12.9-.3zm46.9 13.4c.1 8.6-12.9 8.7-12.9.1-.6-81.5-54.9-125.9-120.8-126.4-8.5-.1-8.5-12.9 0-12.9 73.8.5 133.1 51.4 133.7 139.2zM361.7 329v.2c-10.8 19-31 40-51.8 33.3l-.2-.3c-21.1-5.9-70.8-31.5-102.2-56.5-16.2-12.8-31-27.9-42.4-42.4-10.3-12.9-20.7-28.2-30.8-46.6-21.3-38.5-26-55.7-26-55.7-6.7-20.8 14.2-41 33.3-51.8h.2c9.2-4.8 18-3.2 23.9 3.9 0 0 12.4 14.8 17.7 22.1 5 6.8 11.7 17.7 15.2 23.8 6.1 10.9 2.3 22-3.7 26.6l-12 9.6c-6.1 4.9-5.3 14-5.3 14s17.8 67.3 84.3 84.3c0 0 9.1.8 14-5.3l9.6-12c4.6-6 15.7-9.8 26.6-3.7 14.7 8.3 33.4 21.2 45.8 32.9 7 5.7 8.6 14.4 3.8 23.6z"],vimeo:[448,512,[],"f40a","M403.2 32H44.8C20.1 32 0 52.1 0 76.8v358.4C0 459.9 20.1 480 44.8 480h358.4c24.7 0 44.8-20.1 44.8-44.8V76.8c0-24.7-20.1-44.8-44.8-44.8zM377 180.8c-1.4 31.5-23.4 74.7-66 129.4-44 57.2-81.3 85.8-111.7 85.8-18.9 0-34.8-17.4-47.9-52.3-25.5-93.3-36.4-148-57.4-148-2.4 0-10.9 5.1-25.4 15.2l-15.2-19.6c37.3-32.8 72.9-69.2 95.2-71.2 25.2-2.4 40.7 14.8 46.5 51.7 20.7 131.2 29.9 151 67.6 91.6 13.5-21.4 20.8-37.7 21.8-48.9 3.5-33.2-25.9-30.9-45.8-22.4 15.9-52.1 46.3-77.4 91.2-76 33.3.9 49 22.5 47.1 64.7z"],"vimeo-square":[448,512,[],"f194","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-16.2 149.6c-1.4 31.1-23.2 73.8-65.3 127.9-43.5 56.5-80.3 84.8-110.4 84.8-18.7 0-34.4-17.2-47.3-51.6-25.2-92.3-35.9-146.4-56.7-146.4-2.4 0-10.8 5-25.1 15.1L64 192c36.9-32.4 72.1-68.4 94.1-70.4 24.9-2.4 40.2 14.6 46 51.1 20.5 129.6 29.6 149.2 66.8 90.5 13.4-21.2 20.6-37.2 21.5-48.3 3.4-32.8-25.6-30.6-45.2-22.2 15.7-51.5 45.8-76.5 90.1-75.1 32.9 1 48.4 22.4 46.5 64z"],"vimeo-v":[448,512,[],"f27d","M447.8 153.6c-2 43.6-32.4 103.3-91.4 179.1-60.9 79.2-112.4 118.8-154.6 118.8-26.1 0-48.2-24.1-66.3-72.3C100.3 250 85.3 174.3 56.2 174.3c-3.4 0-15.1 7.1-35.2 21.1L0 168.2c51.6-45.3 100.9-95.7 131.8-98.5 34.9-3.4 56.3 20.5 64.4 71.5 28.7 181.5 41.4 208.9 93.6 126.7 18.7-29.6 28.8-52.1 30.2-67.6 4.8-45.9-35.8-42.8-63.3-31 22-72.1 64.1-107.1 126.2-105.1 45.8 1.2 67.5 31.1 64.9 89.4z"],vine:[384,512,[],"f1ca","M384 254.7v52.1c-18.4 4.2-36.9 6.1-52.1 6.1-36.9 77.4-103 143.8-125.1 156.2-14 7.9-27.1 8.4-42.7-.8C137 452 34.2 367.7 0 102.7h74.5C93.2 261.8 139 343.4 189.3 404.5c27.9-27.9 54.8-65.1 75.6-106.9-49.8-25.3-80.1-80.9-80.1-145.6 0-65.6 37.7-115.1 102.2-115.1 114.9 0 106.2 127.9 81.6 181.5 0 0-46.4 9.2-63.5-20.5 3.4-11.3 8.2-30.8 8.2-48.5 0-31.3-11.3-46.6-28.4-46.6-18.2 0-30.8 17.1-30.8 50 .1 79.2 59.4 118.7 129.9 101.9z"],vk:[576,512,[],"f189","M545 117.7c3.7-12.5 0-21.7-17.8-21.7h-58.9c-15 0-21.9 7.9-25.6 16.7 0 0-30 73.1-72.4 120.5-13.7 13.7-20 18.1-27.5 18.1-3.7 0-9.4-4.4-9.4-16.9V117.7c0-15-4.2-21.7-16.6-21.7h-92.6c-9.4 0-15 7-15 13.5 0 14.2 21.2 17.5 23.4 57.5v86.8c0 19-3.4 22.5-10.9 22.5-20 0-68.6-73.4-97.4-157.4-5.8-16.3-11.5-22.9-26.6-22.9H38.8c-16.8 0-20.2 7.9-20.2 16.7 0 15.6 20 93.1 93.1 195.5C160.4 378.1 229 416 291.4 416c37.5 0 42.1-8.4 42.1-22.9 0-66.8-3.4-73.1 15.4-73.1 8.7 0 23.7 4.4 58.7 38.1 40 40 46.6 57.9 69 57.9h58.9c16.8 0 25.3-8.4 20.4-25-11.2-34.9-86.9-106.7-90.3-111.5-8.7-11.2-6.2-16.2 0-26.2.1-.1 72-101.3 79.4-135.6z"],vnv:[640,512,[],"f40b","M104.9 352c-34.1 0-46.4-30.4-46.4-30.4L2.6 210.1S-7.8 192 13 192h32.8c10.4 0 13.2 8.7 18.8 18.1l36.7 74.5s5.2 13.1 21.1 13.1 21.1-13.1 21.1-13.1l36.7-74.5c5.6-9.5 8.4-18.1 18.8-18.1h32.8c20.8 0 10.4 18.1 10.4 18.1l-55.8 111.5S174.2 352 140 352h-35.1zm395 0c-34.1 0-46.4-30.4-46.4-30.4l-55.9-111.5S387.2 192 408 192h32.8c10.4 0 13.2 8.7 18.8 18.1l36.7 74.5s5.2 13.1 21.1 13.1 21.1-13.1 21.1-13.1l36.8-74.5c5.6-9.5 8.4-18.1 18.8-18.1H627c20.8 0 10.4 18.1 10.4 18.1l-55.9 111.5S569.3 352 535.1 352h-35.2zM337.6 192c34.1 0 46.4 30.4 46.4 30.4l55.9 111.5s10.4 18.1-10.4 18.1h-32.8c-10.4 0-13.2-8.7-18.8-18.1l-36.7-74.5s-5.2-13.1-21.1-13.1c-15.9 0-21.1 13.1-21.1 13.1l-36.7 74.5c-5.6 9.4-8.4 18.1-18.8 18.1h-32.9c-20.8 0-10.4-18.1-10.4-18.1l55.9-111.5s12.2-30.4 46.4-30.4h35.1z"],vuejs:[448,512,[],"f41f","M356.9 64.3H280l-56 88.6-48-88.6H0L224 448 448 64.3h-91.1zm-301.2 32h53.8L224 294.5 338.4 96.3h53.8L224 384.5 55.7 96.3z"],weibo:[512,512,[],"f18a","M407 177.6c7.6-24-13.4-46.8-37.4-41.7-22 4.8-28.8-28.1-7.1-32.8 50.1-10.9 92.3 37.1 76.5 84.8-6.8 21.2-38.8 10.8-32-10.3zM214.8 446.7C108.5 446.7 0 395.3 0 310.4c0-44.3 28-95.4 76.3-143.7C176 67 279.5 65.8 249.9 161c-4 13.1 12.3 5.7 12.3 6 79.5-33.6 140.5-16.8 114 51.4-3.7 9.4 1.1 10.9 8.3 13.1 135.7 42.3 34.8 215.2-169.7 215.2zm143.7-146.3c-5.4-55.7-78.5-94-163.4-85.7-84.8 8.6-148.8 60.3-143.4 116s78.5 94 163.4 85.7c84.8-8.6 148.8-60.3 143.4-116zM347.9 35.1c-25.9 5.6-16.8 43.7 8.3 38.3 72.3-15.2 134.8 52.8 111.7 124-7.4 24.2 29.1 37 37.4 12 31.9-99.8-55.1-195.9-157.4-174.3zm-78.5 311c-17.1 38.8-66.8 60-109.1 46.3-40.8-13.1-58-53.4-40.3-89.7 17.7-35.4 63.1-55.4 103.4-45.1 42 10.8 63.1 50.2 46 88.5zm-86.3-30c-12.9-5.4-30 .3-38 12.9-8.3 12.9-4.3 28 8.6 34 13.1 6 30.8.3 39.1-12.9 8-13.1 3.7-28.3-9.7-34zm32.6-13.4c-5.1-1.7-11.4.6-14.3 5.4-2.9 5.1-1.4 10.6 3.7 12.9 5.1 2 11.7-.3 14.6-5.4 2.8-5.2 1.1-10.9-4-12.9z"],weixin:[576,512,[],"f1d7","M372.3 167.6c6.4 0 12.6.3 18.8 1.1C374.4 90.3 290.3 32 194.7 32 87.6 32 0 104.8 0 197.4c0 53.4 29.3 97.5 77.9 131.6l-19.3 58.6 68-34.1c24.4 4.8 43.8 9.7 68.2 9.7 6.2 0 12.1-.3 18.3-.8-4-12.9-6.2-26.6-6.2-40.8-.1-84.9 73-154 165.4-154zm-104.5-52.9c14.5 0 24.2 9.7 24.2 24.4 0 14.5-9.7 24.2-24.2 24.2-14.8 0-29.3-9.7-29.3-24.2 0-14.7 14.5-24.4 29.3-24.4zm-136.5 48.6c-14.5 0-29.3-9.7-29.3-24.2 0-14.8 14.8-24.4 29.3-24.4 14.8 0 24.4 9.7 24.4 24.4.1 14.6-9.6 24.2-24.4 24.2zm418.8 156.1c0-77.9-77.9-141.3-165.4-141.3-92.7 0-165.4 63.4-165.4 141.3S292 460.7 384.6 460.7c19.3 0 38.9-5.1 58.6-9.9l53.4 29.3-14.8-48.6c39.3-29.4 68.3-68.3 68.3-112.1zm-219.2-24.5c-9.7 0-19.3-9.7-19.3-19.6 0-9.7 9.7-19.3 19.3-19.3 14.8 0 24.4 9.7 24.4 19.3 0 10-9.6 19.6-24.4 19.6zm107.2 0c-9.7 0-19.3-9.7-19.3-19.6 0-9.7 9.7-19.3 19.3-19.3 14.5 0 24.4 9.7 24.4 19.3 0 10-9.9 19.6-24.4 19.6z"],whatsapp:[448,512,[],"f232","M380.9 97.1C339 55.1 283.2 32 223.9 32c-122.4 0-222 99.6-222 222 0 39.1 10.2 77.3 29.6 111L0 480l117.7-30.9c32.4 17.7 68.9 27 106.1 27h.1c122.3 0 224.1-99.6 224.1-222 0-59.3-25.2-115-67.1-157zm-157 341.6c-33.2 0-65.7-8.9-94-25.7l-6.7-4-69.8 18.3L72 359.2l-4.4-7c-18.5-29.4-28.2-63.3-28.2-98.2 0-101.7 82.8-184.5 184.6-184.5 49.3 0 95.6 19.2 130.4 54.1 34.8 34.9 56.2 81.2 56.1 130.5 0 101.8-84.9 184.6-186.6 184.6zm101.2-138.2c-5.5-2.8-32.8-16.2-37.9-18-5.1-1.9-8.8-2.8-12.5 2.8-3.7 5.6-14.3 18-17.6 21.8-3.2 3.7-6.5 4.2-12 1.4-32.6-16.3-54-29.1-75.5-66-5.7-9.8 5.7-9.1 16.3-30.3 1.8-3.7.9-6.9-.5-9.7-1.4-2.8-12.5-30.1-17.1-41.2-4.5-10.8-9.1-9.3-12.5-9.5-3.2-.2-6.9-.2-10.6-.2-3.7 0-9.7 1.4-14.8 6.9-5.1 5.6-19.4 19-19.4 46.3 0 27.3 19.9 53.7 22.6 57.4 2.8 3.7 39.1 59.7 94.8 83.8 35.2 15.2 49 16.5 66.6 13.9 10.7-1.6 32.8-13.4 37.4-26.4 4.6-13 4.6-24.1 3.2-26.4-1.3-2.5-5-3.9-10.5-6.6z"],"whatsapp-square":[448,512,[],"f40c","M224 122.8c-72.7 0-131.8 59.1-131.9 131.8 0 24.9 7 49.2 20.2 70.1l3.1 5-13.3 48.6 49.9-13.1 4.8 2.9c20.2 12 43.4 18.4 67.1 18.4h.1c72.6 0 133.3-59.1 133.3-131.8 0-35.2-15.2-68.3-40.1-93.2-25-25-58-38.7-93.2-38.7zm77.5 188.4c-3.3 9.3-19.1 17.7-26.7 18.8-12.6 1.9-22.4.9-47.5-9.9-39.7-17.2-65.7-57.2-67.7-59.8-2-2.6-16.2-21.5-16.2-41s10.2-29.1 13.9-33.1c3.6-4 7.9-5 10.6-5 2.6 0 5.3 0 7.6.1 2.4.1 5.7-.9 8.9 6.8 3.3 7.9 11.2 27.4 12.2 29.4s1.7 4.3.3 6.9c-7.6 15.2-15.7 14.6-11.6 21.6 15.3 26.3 30.6 35.4 53.9 47.1 4 2 6.3 1.7 8.6-1 2.3-2.6 9.9-11.6 12.5-15.5 2.6-4 5.3-3.3 8.9-2 3.6 1.3 23.1 10.9 27.1 12.9s6.6 3 7.6 4.6c.9 1.9.9 9.9-2.4 19.1zM400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM223.9 413.2c-26.6 0-52.7-6.7-75.8-19.3L64 416l22.5-82.2c-13.9-24-21.2-51.3-21.2-79.3C65.4 167.1 136.5 96 223.9 96c42.4 0 82.2 16.5 112.2 46.5 29.9 30 47.9 69.8 47.9 112.2 0 87.4-72.7 158.5-160.1 158.5z"],whmcs:[448,512,[],"f40d","M448 161v-21.3l-28.5-8.8-2.2-10.4 20.1-20.7L427 80.4l-29 7.5-7.2-7.5 7.5-28.2-19.1-11.6-21.3 21-10.7-3.2-7-26.4h-22.6l-6.2 26.4-12.1 3.2-19.7-21-19.4 11 8.1 27.7-8.1 8.4-28.5-7.5-11 19.1 20.7 21-2.9 10.4-28.5 7.8-.3 21.7 28.8 7.5 2.4 12.1-20.1 19.9 10.4 18.5 29.6-7.5 7.2 8.6-8.1 26.9 19.9 11.6 19.4-20.4 11.6 2.9 6.7 28.5 22.6.3 6.7-28.8 11.6-3.5 20.7 21.6 20.4-12.1-8.8-28 7.8-8.1 28.8 8.8 10.3-20.1-20.9-18.8 2.2-12.1 29.1-7zm-119.2 45.2c-31.3 0-56.8-25.4-56.8-56.8s25.4-56.8 56.8-56.8 56.8 25.4 56.8 56.8c0 31.5-25.4 56.8-56.8 56.8zm72.3 16.4l46.9 14.5V277l-55.1 13.4-4.1 22.7 38.9 35.3-19.2 37.9-54-16.7-14.6 15.2 16.7 52.5-38.3 22.7-38.9-40.5-21.7 6.6-12.6 54-42.4-.5-12.6-53.6-21.7-5.6-36.4 38.4-37.4-21.7 15.2-50.5-13.7-16.1-55.5 14.1-19.7-34.8 37.9-37.4-4.8-22.8-54-14.1.5-40.9L54 219.9l5.7-19.7-38.9-39.4L41.5 125l53.6 14.1 15.2-15.7-15.2-52 36.4-20.7 36.8 39.4L191 84l11.6-52H245l11.6 45.9L234 72l-6.3-1.7-3.3 5.7-11 19.1-3.3 5.6 4.6 4.6 17.2 17.4-.3 1-23.8 6.5-6.2 1.7-.1 6.4-.2 12.9C153.8 161.6 118 204 118 254.7c0 58.3 47.3 105.7 105.7 105.7 50.5 0 92.7-35.4 103.2-82.8l13.2.2 6.9.1 1.6-6.7 5.6-24 1.9-.6 17.1 17.8 4.7 4.9 5.8-3.4 20.4-12.1 5.8-3.5-2-6.5-6.8-21.2z"],"wikipedia-w":[640,512,[],"f266","M640 51.2l-.3 12.2c-28.1.8-45 15.8-55.8 40.3-25 57.8-103.3 240-155.3 358.6H415l-81.9-193.1c-32.5 63.6-68.3 130-99.2 193.1-.3.3-15 0-15-.3C172 352.3 122.8 243.4 75.8 133.4 64.4 106.7 26.4 63.4.2 63.7c0-3.1-.3-10-.3-14.2h161.9v13.9c-19.2 1.1-52.8 13.3-43.3 34.2 21.9 49.7 103.6 240.3 125.6 288.6 15-29.7 57.8-109.2 75.3-142.8-13.9-28.3-58.6-133.9-72.8-160-9.7-17.8-36.1-19.4-55.8-19.7V49.8l142.5.3v13.1c-19.4.6-38.1 7.8-29.4 26.1 18.9 40 30.6 68.1 48.1 104.7 5.6-10.8 34.7-69.4 48.1-100.8 8.9-20.6-3.9-28.6-38.6-29.4.3-3.6 0-10.3.3-13.6 44.4-.3 111.1-.3 123.1-.6v13.6c-22.5.8-45.8 12.8-58.1 31.7l-59.2 122.8c6.4 16.1 63.3 142.8 69.2 156.7L559.2 91.8c-8.6-23.1-36.4-28.1-47.2-28.3V49.6l127.8 1.1.2.5z"],windows:[448,512,[],"f17a","M0 93.7l183.6-25.3v177.4H0V93.7zm0 324.6l183.6 25.3V268.4H0v149.9zm203.8 28L448 480V268.4H203.8v177.9zm0-380.6v180.1H448V32L203.8 65.7z"],wordpress:[512,512,[],"f19a","M61.7 169.4l101.5 278C92.2 413 43.3 340.2 43.3 256c0-30.9 6.6-60.1 18.4-86.6zm337.9 75.9c0-26.3-9.4-44.5-17.5-58.7-10.8-17.5-20.9-32.4-20.9-49.9 0-19.6 14.8-37.8 35.7-37.8.9 0 1.8.1 2.8.2-37.9-34.7-88.3-55.9-143.7-55.9-74.3 0-139.7 38.1-177.8 95.9 5 .2 9.7.3 13.7.3 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l77.5 230.4L249.8 247l-33.1-90.8c-11.5-.7-22.3-2-22.3-2-11.5-.7-10.1-18.2 1.3-17.5 0 0 35.1 2.7 56 2.7 22.2 0 56.7-2.7 56.7-2.7 11.5-.7 12.8 16.2 1.4 17.5 0 0-11.5 1.3-24.3 2l76.9 228.7 21.2-70.9c9-29.4 16-50.5 16-68.7zm-139.9 29.3l-63.8 185.5c19.1 5.6 39.2 8.7 60.1 8.7 24.8 0 48.5-4.3 70.6-12.1-.6-.9-1.1-1.9-1.5-2.9l-65.4-179.2zm183-120.7c.9 6.8 1.4 14 1.4 21.9 0 21.6-4 45.8-16.2 76.2l-65 187.9C426.2 403 468.7 334.5 468.7 256c0-37-9.4-71.8-26-102.1zM504 256c0 136.8-111.3 248-248 248C119.2 504 8 392.7 8 256 8 119.2 119.2 8 256 8c136.7 0 248 111.2 248 248zm-11.4 0c0-130.5-106.2-236.6-236.6-236.6C125.5 19.4 19.4 125.5 19.4 256S125.6 492.6 256 492.6c130.5 0 236.6-106.1 236.6-236.6z"],"wordpress-simple":[512,512,[],"f411","M256 8C119.3 8 8 119.2 8 256c0 136.7 111.3 248 248 248s248-111.3 248-248C504 119.2 392.7 8 256 8zM33 256c0-32.3 6.9-63 19.3-90.7l106.4 291.4C84.3 420.5 33 344.2 33 256zm223 223c-21.9 0-43-3.2-63-9.1l66.9-194.4 68.5 187.8c.5 1.1 1 2.1 1.6 3.1-23.1 8.1-48 12.6-74 12.6zm30.7-327.5c13.4-.7 25.5-2.1 25.5-2.1 12-1.4 10.6-19.1-1.4-18.4 0 0-36.1 2.8-59.4 2.8-21.9 0-58.7-2.8-58.7-2.8-12-.7-13.4 17.7-1.4 18.4 0 0 11.4 1.4 23.4 2.1l34.7 95.2L200.6 393l-81.2-241.5c13.4-.7 25.5-2.1 25.5-2.1 12-1.4 10.6-19.1-1.4-18.4 0 0-36.1 2.8-59.4 2.8-4.2 0-9.1-.1-14.4-.3C109.6 73 178.1 33 256 33c58 0 110.9 22.2 150.6 58.5-1-.1-1.9-.2-2.9-.2-21.9 0-37.4 19.1-37.4 39.6 0 18.4 10.6 33.9 21.9 52.3 8.5 14.8 18.4 33.9 18.4 61.5 0 19.1-7.3 41.2-17 72.1l-22.2 74.3-80.7-239.6zm81.4 297.2l68.1-196.9c12.7-31.8 17-57.2 17-79.9 0-8.2-.5-15.8-1.5-22.9 17.4 31.8 27.3 68.2 27.3 107 0 82.3-44.6 154.1-110.9 192.7z"],wpbeginner:[512,512,[],"f297","M462.799 322.374C519.01 386.682 466.961 480 370.944 480c-39.602 0-78.824-17.687-100.142-50.04-6.887.356-22.702.356-29.59 0C219.848 462.381 180.588 480 141.069 480c-95.49 0-148.348-92.996-91.855-157.626C-29.925 190.523 80.479 32 256.006 32c175.632 0 285.87 158.626 206.793 290.374zm-339.647-82.972h41.529v-58.075h-41.529v58.075zm217.18 86.072v-23.839c-60.506 20.915-132.355 9.198-187.589-33.971l.246 24.897c51.101 46.367 131.746 57.875 187.343 32.913zm-150.753-86.072h166.058v-58.075H189.579v58.075z"],wpexplorer:[512,512,[],"f2de","M512 256c0 141.2-114.7 256-256 256C114.8 512 0 397.3 0 256S114.7 0 256 0s256 114.7 256 256zm-32 0c0-123.2-100.3-224-224-224C132.5 32 32 132.5 32 256s100.5 224 224 224 224-100.5 224-224zM160.9 124.6l86.9 37.1-37.1 86.9-86.9-37.1 37.1-86.9zm110 169.1l46.6 94h-14.6l-50-100-48.9 100h-14l51.1-106.9-22.3-9.4 6-14 68.6 29.1-6 14.3-16.5-7.1zm-11.8-116.3l68.6 29.4-29.4 68.3L230 246l29.1-68.6zm80.3 42.9l54.6 23.1-23.4 54.3-54.3-23.1 23.1-54.3z"],wpforms:[448,512,[],"f298","M448 75.2v361.7c0 24.3-19 43.2-43.2 43.2H43.2C19.3 480 0 461.4 0 436.8V75.2C0 51.1 18.8 32 43.2 32h361.7c24 0 43.1 18.8 43.1 43.2zm-37.3 361.6V75.2c0-3-2.6-5.8-5.8-5.8h-9.3L285.3 144 224 94.1 162.8 144 52.5 69.3h-9.3c-3.2 0-5.8 2.8-5.8 5.8v361.7c0 3 2.6 5.8 5.8 5.8h361.7c3.2.1 5.8-2.7 5.8-5.8zM150.2 186v37H76.7v-37h73.5zm0 74.4v37.3H76.7v-37.3h73.5zm11.1-147.3l54-43.7H96.8l64.5 43.7zm210 72.9v37h-196v-37h196zm0 74.4v37.3h-196v-37.3h196zm-84.6-147.3l64.5-43.7H232.8l53.9 43.7zM371.3 335v37.3h-99.4V335h99.4z"],xbox:[512,512,[],"f412","M369.9 318.2c44.3 54.3 64.7 98.8 54.4 118.7-7.9 15.1-56.7 44.6-92.6 55.9-29.6 9.3-68.4 13.3-100.4 10.2-38.2-3.7-76.9-17.4-110.1-39C93.3 445.8 87 438.3 87 423.4c0-29.9 32.9-82.3 89.2-142.1 32-33.9 76.5-73.7 81.4-72.6 9.4 2.1 84.3 75.1 112.3 109.5zM188.6 143.8c-29.7-26.9-58.1-53.9-86.4-63.4-15.2-5.1-16.3-4.8-28.7 8.1-29.2 30.4-53.5 79.7-60.3 122.4-5.4 34.2-6.1 43.8-4.2 60.5 5.6 50.5 17.3 85.4 40.5 120.9 9.5 14.6 12.1 17.3 9.3 9.9-4.2-11-.3-37.5 9.5-64 14.3-39 53.9-112.9 120.3-194.4zm311.6 63.5C483.3 127.3 432.7 77 425.6 77c-7.3 0-24.2 6.5-36 13.9-23.3 14.5-41 31.4-64.3 52.8C367.7 197 427.5 283.1 448.2 346c6.8 20.7 9.7 41.1 7.4 52.3-1.7 8.5-1.7 8.5 1.4 4.6 6.1-7.7 19.9-31.3 25.4-43.5 7.4-16.2 15-40.2 18.6-58.7 4.3-22.5 3.9-70.8-.8-93.4zM141.3 43C189 40.5 251 77.5 255.6 78.4c.7.1 10.4-4.2 21.6-9.7 63.9-31.1 94-25.8 107.4-25.2-63.9-39.3-152.7-50-233.9-11.7-23.4 11.1-24 11.9-9.4 11.2z"],xing:[384,512,[],"f168","M162.7 210c-1.8 3.3-25.2 44.4-70.1 123.5-4.9 8.3-10.8 12.5-17.7 12.5H9.8c-7.7 0-12.1-7.5-8.5-14.4l69-121.3c.2 0 .2-.1 0-.3l-43.9-75.6c-4.3-7.8.3-14.1 8.5-14.1H100c7.3 0 13.3 4.1 18 12.2l44.7 77.5zM382.6 46.1l-144 253v.3L330.2 466c3.9 7.1.2 14.1-8.5 14.1h-65.2c-7.6 0-13.6-4-18-12.2l-92.4-168.5c3.3-5.8 51.5-90.8 144.8-255.2 4.6-8.1 10.4-12.2 17.5-12.2h65.7c8 0 12.3 6.7 8.5 14.1z"],"xing-square":[448,512,[],"f169","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM140.4 320.2H93.8c-5.5 0-8.7-5.3-6-10.3l49.3-86.7c.1 0 .1-.1 0-.2l-31.4-54c-3-5.6.2-10.1 6-10.1h46.6c5.2 0 9.5 2.9 12.9 8.7l31.9 55.3c-1.3 2.3-18 31.7-50.1 88.2-3.5 6.2-7.7 9.1-12.6 9.1zm219.7-214.1L257.3 286.8v.2l65.5 119c2.8 5.1.1 10.1-6 10.1h-46.6c-5.5 0-9.7-2.9-12.9-8.7l-66-120.3c2.3-4.1 36.8-64.9 103.4-182.3 3.3-5.8 7.4-8.7 12.5-8.7h46.9c5.7-.1 8.8 4.7 6 10z"],"y-combinator":[448,512,[],"f23b","M448 32v448H0V32h448zM236 287.5L313.5 142h-32.7L235 233c-4.7 9.3-9 18.3-12.8 26.8L210 233l-45.2-91h-35l76.7 143.8v94.5H236v-92.8z"],yahoo:[360,512,[],"f19e","M204.9 288l3.5 195.5c-11.3-2-20.9-3.5-28.7-3.5-7.5 0-17 1.5-28.7 3.5l3.5-195.5C105.7 203.7 56.5 113.1 0 28.5 10.6 31.3 20.4 32 29.5 32c8 0 18.1-.7 30.3-3.5 36.4 64.2 72.9 123.2 119.9 200.4 33.2-54.7 80.9-128.1 119.9-200.4 9.8 2.6 19.6 3.5 29.2 3.5 10.2 0 20.6-.9 31.1-3.5C329.4 71.1 243 221.3 204.9 288z"],yandex:[256,512,[],"f413","M153.1 315.8L65.7 512H2l96-209.8c-45.1-22.9-75.2-64.4-75.2-141.1C22.7 53.7 90.8 0 171.7 0H254v512h-55.1V315.8h-45.8zm45.8-269.3h-29.4c-44.4 0-87.4 29.4-87.4 114.6 0 82.3 39.4 108.8 87.4 108.8h29.4V46.5z"],"yandex-international":[320,512,[],"f414","M129.5 512V345.9L18.5 48h55.8l81.8 229.7L250.2 0h51.3L180.8 347.8V512h-51.3z"],yelp:[384,512,[],"f1e9","M136.9 328c-1 .3-109.2 35.7-115.8 35.7-15.2-.9-18.5-16.2-19.9-31.2-1.5-14.2-1.4-29.8.3-46.8 1.9-18.8 5.5-45.1 24.2-44 4.8 0 67.1 25.9 112.7 44.4 17.1 6.8 18.6 35.8-1.5 41.9zm57.9-113.9c1.8 38.2-25.5 48.5-47.2 14.3L41.3 60.4c-1.5-6.6.3-12.4 5.3-17.4C62.2 26.5 146 3.2 168.1 8.9c7.5 1.9 12.1 6.1 13.8 12.6 1.3 8.3 11.5 167.4 12.9 192.6zm-1.4 164.8c0 4.6.2 116.4-1.7 121.5-2.3 6-7 9.7-14.3 11.2-10.1 1.7-27.1-1.9-51-10.7-22-8.1-56.7-21.5-49.3-42.5 2.8-6.9 51.4-62.8 77.3-93.6 12-15.2 39.8-5.5 39 14.1zm180.2-117.8c-5.6 3.7-110.8 28.2-118.1 30.6l.3-.6c-18.1 4.7-35.4-18.5-23.3-34.6 3.7-3.7 65.9-92.4 72.8-97 5.2-3.6 11.3-3.8 18.3-.6 18.4 8.8 55.1 63.1 57.4 84.6-.1 2.9 1.2 11.7-7.4 17.6zm10.1 130.7c-2.7 20.6-44.5 73.4-63.8 81-6.9 2.6-12.9 2-17.7-2-5-3.5-61.8-97.1-64.9-102.3-10.9-16.2 6.8-39.8 25.6-33.2 0 0 110.5 35.7 114.7 39.4 5.2 4.1 7.2 9.8 6.1 17.1z"],yoast:[448,512,[],"f2b1","M91.265 96h186.043l-7.008 18.878H91.265c-39.658 0-71.889 31.556-71.889 70.292v205.373c0 35.401 24.882 70.311 84.001 70.311V480H91.265C41.165 480 0 439.83 0 390.544V185.17C0 135.937 40.709 96 91.265 96zm229.114-56h66.49C243.146 418.092 241.192 438.918 202.18 479.331c-20.779 21.646-49.294 31.719-78.328 32.669v-51.146c49.234-7.662 64.606-49.855 64.606-75.284 0-20.078.577-12.645-82.117-223.219h61.386l50.354 156.58L320.379 40zM448 181.465V480H233.963c6.635-9.621 10.679-16.277 12.112-19.413h182.529V181.465c0-32.543-17.097-51.945-48.194-62.914l6.733-17.578C428.763 114.636 448 144.059 448 181.465z"],youtube:[576,512,[],"f167","M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"]}),t=z||{};t.___FONT_AWESOME___||(t.___FONT_AWESOME___={}),t.___FONT_AWESOME___.styles||(t.___FONT_AWESOME___.styles={}),t.___FONT_AWESOME___.hooks||(t.___FONT_AWESOME___.hooks={}),t.___FONT_AWESOME___.shims||(t.___FONT_AWESOME___.shims=[]);var s=t.___FONT_AWESOME___,r=Object.assign||function(c){for(var l=1;l<arguments.length;l++){var h=arguments[l];for(var v in h)Object.prototype.hasOwnProperty.call(h,v)&&(c[v]=h[v])}return c};!function(c){try{c()}catch(c){}}(function(){c("fab")})}(),function(){"use strict";function c(c){"function"==typeof s.hooks.addPack?s.hooks.addPack(c,m):s.styles[c]=r({},s.styles[c]||{},m)}var l={};try{"undefined"!=typeof window&&(l=window)}catch(c){}var h=(l.navigator||{}).userAgent,v=void 0===h?"":h,z=l,e=(~v.indexOf("MSIE")||v.indexOf("Trident/"),[1,2,3,4,5,6,7,8,9,10]),a=e.concat([11,12,13,14,15,16,17,18,19,20]),m=(["xs","sm","lg","fw","ul","li","border","pull-left","pull-right","spin","pulse","rotate-90","rotate-180","rotate-270","flip-horizontal","flip-vertical","stack","stack-1x","stack-2x","inverse","layers","layers-text","layers-counter"].concat(e.map(function(c){return c+"x"})).concat(a.map(function(c){return"w-"+c})),{"address-book":[448,512,[],"f2b9","M320 320v72c0 13.255-10.745 24-24 24H152c-13.255 0-24-10.745-24-24v-72c0-21.431 14.207-40.266 34.813-46.153l18.064-5.161C193.629 275.884 208.342 280 224 280s30.371-4.116 43.122-11.314l18.064 5.161C305.793 279.734 320 298.569 320 320zm-96-64c35.346 0 64-28.654 64-64s-28.654-64-64-64-64 28.654-64 64 28.654 64 64 64zm192-96v64h20c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-20v64h20c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-20v48c0 26.51-21.49 48-48 48H80c-26.51 0-48-21.49-48-48V48C32 21.49 53.49 0 80 0h288c26.51 0 48 21.49 48 48v48h20c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-20zm-48 298V54a6 6 0 0 0-6-6H86a6 6 0 0 0-6 6v404a6 6 0 0 0 6 6h276a6 6 0 0 0 6-6z"],"address-card":[512,512,[],"f2bb","M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 336H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v276a6 6 0 0 1-6 6zm-54-176H300c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12zm0 80H300c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12zm-284-96c0-30.928 25.072-56 56-56s56 25.072 56 56-25.072 56-56 56-56-25.072-56-56zm136 89.857V340c0 6.627-5.373 12-12 12H108c-6.627 0-12-5.373-12-12v-42.143a24 24 0 0 1 17.104-22.988l13.464-4.039C140.186 281.568 157.351 288 176 288s35.814-6.432 49.433-17.17l13.464 4.039A24 24 0 0 1 256 297.857z"],"arrow-alt-circle-down":[512,512,[],"f358","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm-32-316v116h-67c-10.7 0-16 12.9-8.5 20.5l99 99c4.7 4.7 12.3 4.7 17 0l99-99c7.6-7.6 2.2-20.5-8.5-20.5h-67V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12z"],"arrow-alt-circle-left":[512,512,[],"f359","M8 256c0 137 111 248 248 248s248-111 248-248S393 8 256 8 8 119 8 256zm448 0c0 110.5-89.5 200-200 200S56 366.5 56 256 145.5 56 256 56s200 89.5 200 200zm-72-20v40c0 6.6-5.4 12-12 12H256v67c0 10.7-12.9 16-20.5 8.5l-99-99c-4.7-4.7-4.7-12.3 0-17l99-99c7.6-7.6 20.5-2.2 20.5 8.5v67h116c6.6 0 12 5.4 12 12z"],"arrow-alt-circle-right":[512,512,[],"f35a","M504 256C504 119 393 8 256 8S8 119 8 256s111 248 248 248 248-111 248-248zm-448 0c0-110.5 89.5-200 200-200s200 89.5 200 200-89.5 200-200 200S56 366.5 56 256zm72 20v-40c0-6.6 5.4-12 12-12h116v-67c0-10.7 12.9-16 20.5-8.5l99 99c4.7 4.7 4.7 12.3 0 17l-99 99c-7.6 7.6-20.5 2.2-20.5-8.5v-67H140c-6.6 0-12-5.4-12-12z"],"arrow-alt-circle-up":[512,512,[],"f35b","M256 504c137 0 248-111 248-248S393 8 256 8 8 119 8 256s111 248 248 248zm0-448c110.5 0 200 89.5 200 200s-89.5 200-200 200S56 366.5 56 256 145.5 56 256 56zm20 328h-40c-6.6 0-12-5.4-12-12V256h-67c-10.7 0-16-12.9-8.5-20.5l99-99c4.7-4.7 12.3-4.7 17 0l99 99c7.6 7.6 2.2 20.5-8.5 20.5h-67v116c0 6.6-5.4 12-12 12z"],bell:[448,512,[],"f0f3","M425.403 330.939c-16.989-16.785-34.546-34.143-34.546-116.083 0-83.026-60.958-152.074-140.467-164.762A31.843 31.843 0 0 0 256 32c0-17.673-14.327-32-32-32s-32 14.327-32 32a31.848 31.848 0 0 0 5.609 18.095C118.101 62.783 57.143 131.831 57.143 214.857c0 81.933-17.551 99.292-34.543 116.078C-25.496 378.441 9.726 448 66.919 448H160c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64h93.08c57.19 0 92.415-69.583 44.323-117.061zM224 472c-13.234 0-24-10.766-24-24h48c0 13.234-10.766 24-24 24zm157.092-72H66.9c-16.762 0-25.135-20.39-13.334-32.191 28.585-28.585 51.577-55.724 51.577-152.952C105.143 149.319 158.462 96 224 96s118.857 53.319 118.857 118.857c0 97.65 23.221 124.574 51.568 152.952C406.278 379.661 397.783 400 381.092 400z"],"bell-slash":[576,512,[],"f1f6","M130.9 400c-16.762 0-25.135-20.39-13.334-32.191 25.226-25.226 46.094-49.338 50.649-121.48l-46.777-41.274a168.48 168.48 0 0 0-.296 9.802c0 81.933-17.551 99.292-34.543 116.078C38.504 378.441 73.726 448 130.919 448H224c0 35.346 28.654 64 64 64s64-28.654 64-64h44.777l-54.4-48H130.9zM288 472c-13.234 0-24-10.766-24-24h48c0 13.234-10.766 24-24 24zm283.867.553l-67.931-59.571c13.104-24.118 11.524-56.318-14.532-82.042-16.989-16.785-34.546-34.143-34.546-116.083 0-83.026-60.958-152.074-140.467-164.762A31.848 31.848 0 0 0 320 32c0-17.673-14.327-32-32-32s-32 14.327-32 32a31.848 31.848 0 0 0 5.609 18.095c-41.471 6.618-77.891 28.571-103.249 59.841L36.459 3.037c-5.058-4.436-12.777-3.956-17.24 1.071L3.056 22.313C-1.407 27.34-.925 35.012 4.134 39.447l535.408 469.516c5.058 4.436 12.777 3.956 17.24-1.071l16.163-18.205c4.462-5.027 3.98-12.699-1.078-17.134zM288 96c65.538 0 118.857 53.319 118.857 118.857 0 97.65 23.221 124.574 51.568 152.952 2.908 2.908 4.573 6.328 5.209 9.832L194.482 141.612C216.258 113.867 250.075 96 288 96z"],bookmark:[384,512,[],"f02e","M336 0H48C21.49 0 0 21.49 0 48v464l192-112 192 112V48c0-26.51-21.49-48-48-48zm0 428.43l-144-84-144 84V54a6 6 0 0 1 6-6h276c3.314 0 6 2.683 6 5.996V428.43z"],building:[448,512,[],"f1ad","M128 148v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12zm140 12h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm-128 96h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm128 0h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm-76 84v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm76 12h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm180 124v36H0v-36c0-6.6 5.4-12 12-12h19.5V24c0-13.3 10.7-24 24-24h337c13.3 0 24 10.7 24 24v440H436c6.6 0 12 5.4 12 12zM79.5 463H192v-67c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v67h112.5V49L80 48l-.5 415z"],calendar:[448,512,[],"f133","M400 64h-48V12c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v52H160V12c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v52H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zm-6 400H54c-3.3 0-6-2.7-6-6V160h352v298c0 3.3-2.7 6-6 6z"],"calendar-alt":[448,512,[],"f073","M148 288h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm108-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 96v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm96-260v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"calendar-check":[448,512,[],"f274","M400 64h-48V12c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v52H160V12c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v52H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 400H54a6 6 0 0 1-6-6V160h352v298a6 6 0 0 1-6 6zm-52.849-200.65L198.842 404.519c-4.705 4.667-12.303 4.637-16.971-.068l-75.091-75.699c-4.667-4.705-4.637-12.303.068-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l44.104 44.461 111.072-110.181c4.705-4.667 12.303-4.637 16.971.068l22.536 22.718c4.667 4.705 4.636 12.303-.069 16.97z"],"calendar-minus":[448,512,[],"f272","M124 328c-6.6 0-12-5.4-12-12v-24c0-6.6 5.4-12 12-12h200c6.6 0 12 5.4 12 12v24c0 6.6-5.4 12-12 12H124zm324-216v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"calendar-plus":[448,512,[],"f271","M336 292v24c0 6.6-5.4 12-12 12h-76v76c0 6.6-5.4 12-12 12h-24c-6.6 0-12-5.4-12-12v-76h-76c-6.6 0-12-5.4-12-12v-24c0-6.6 5.4-12 12-12h76v-76c0-6.6 5.4-12 12-12h24c6.6 0 12 5.4 12 12v76h76c6.6 0 12 5.4 12 12zm112-180v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"calendar-times":[448,512,[],"f273","M311.7 374.7l-17 17c-4.7 4.7-12.3 4.7-17 0L224 337.9l-53.7 53.7c-4.7 4.7-12.3 4.7-17 0l-17-17c-4.7-4.7-4.7-12.3 0-17l53.7-53.7-53.7-53.7c-4.7-4.7-4.7-12.3 0-17l17-17c4.7-4.7 12.3-4.7 17 0l53.7 53.7 53.7-53.7c4.7-4.7 12.3-4.7 17 0l17 17c4.7 4.7 4.7 12.3 0 17L257.9 304l53.7 53.7c4.8 4.7 4.8 12.3.1 17zM448 112v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48zm-48 346V160H48v298c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"caret-square-down":[448,512,[],"f150","M125.1 208h197.8c10.7 0 16.1 13 8.5 20.5l-98.9 98.3c-4.7 4.7-12.2 4.7-16.9 0l-98.9-98.3c-7.7-7.5-2.3-20.5 8.4-20.5zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"caret-square-left":[448,512,[],"f191","M272 157.1v197.8c0 10.7-13 16.1-20.5 8.5l-98.3-98.9c-4.7-4.7-4.7-12.2 0-16.9l98.3-98.9c7.5-7.7 20.5-2.3 20.5 8.4zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"caret-square-right":[448,512,[],"f152","M176 354.9V157.1c0-10.7 13-16.1 20.5-8.5l98.3 98.9c4.7 4.7 4.7 12.2 0 16.9l-98.3 98.9c-7.5 7.7-20.5 2.3-20.5-8.4zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"caret-square-up":[448,512,[],"f151","M322.9 304H125.1c-10.7 0-16.1-13-8.5-20.5l98.9-98.3c4.7-4.7 12.2-4.7 16.9 0l98.9 98.3c7.7 7.5 2.3 20.5-8.4 20.5zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"chart-bar":[512,512,[],"f080","M500 400c6.6 0 12 5.4 12 12v24c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h24c6.6 0 12 5.4 12 12v324h452zm-356-60v-72c0-6.6-5.4-12-12-12h-24c-6.6 0-12 5.4-12 12v72c0 6.6 5.4 12 12 12h24c6.6 0 12-5.4 12-12zm96 0V140c0-6.6-5.4-12-12-12h-24c-6.6 0-12 5.4-12 12v200c0 6.6 5.4 12 12 12h24c6.6 0 12-5.4 12-12zm96 0V204c0-6.6-5.4-12-12-12h-24c-6.6 0-12 5.4-12 12v136c0 6.6 5.4 12 12 12h24c6.6 0 12-5.4 12-12zm96 0V108c0-6.6-5.4-12-12-12h-24c-6.6 0-12 5.4-12 12v232c0 6.6 5.4 12 12 12h24c6.6 0 12-5.4 12-12z"],"check-circle":[512,512,[],"f058","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 48c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m140.204 130.267l-22.536-22.718c-4.667-4.705-12.265-4.736-16.97-.068L215.346 303.697l-59.792-60.277c-4.667-4.705-12.265-4.736-16.97-.069l-22.719 22.536c-4.705 4.667-4.736 12.265-.068 16.971l90.781 91.516c4.667 4.705 12.265 4.736 16.97.068l172.589-171.204c4.704-4.668 4.734-12.266.067-16.971z"],"check-square":[448,512,[],"f14a","M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zm0 400H48V80h352v352zm-35.864-241.724L191.547 361.48c-4.705 4.667-12.303 4.637-16.97-.068l-90.781-91.516c-4.667-4.705-4.637-12.303.069-16.971l22.719-22.536c4.705-4.667 12.303-4.637 16.97.069l59.792 60.277 141.352-140.216c4.705-4.667 12.303-4.637 16.97.068l22.536 22.718c4.667 4.706 4.637 12.304-.068 16.971z"],circle:[512,512,[],"f111","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200z"],clipboard:[384,512,[],"f328","M336 64h-80c0-35.29-28.71-64-64-64s-64 28.71-64 64H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 400H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h42v36c0 6.627 5.373 12 12 12h168c6.627 0 12-5.373 12-12v-36h42a6 6 0 0 1 6 6v340a6 6 0 0 1-6 6zM192 40c13.255 0 24 10.745 24 24s-10.745 24-24 24-24-10.745-24-24 10.745-24 24-24"],clock:[512,512,[],"f017","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm61.8-104.4l-84.9-61.7c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v141.7l66.8 48.6c5.4 3.9 6.5 11.4 2.6 16.8L334.6 349c-3.9 5.3-11.4 6.5-16.8 2.6z"],clone:[512,512,[],"f24d","M464 0H144c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h48c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48zM362 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h42v224c0 26.51 21.49 48 48 48h224v42a6 6 0 0 1-6 6zm96-96H150a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v308a6 6 0 0 1-6 6z"],"closed-captioning":[512,512,[],"f20a","M464 64H48C21.5 64 0 85.5 0 112v288c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zm-6 336H54c-3.3 0-6-2.7-6-6V118c0-3.3 2.7-6 6-6h404c3.3 0 6 2.7 6 6v276c0 3.3-2.7 6-6 6zm-211.1-85.7c1.7 2.4 1.5 5.6-.5 7.7-53.6 56.8-172.8 32.1-172.8-67.9 0-97.3 121.7-119.5 172.5-70.1 2.1 2 2.5 3.2 1 5.7l-17.5 30.5c-1.9 3.1-6.2 4-9.1 1.7-40.8-32-94.6-14.9-94.6 31.2 0 48 51 70.5 92.2 32.6 2.8-2.5 7.1-2.1 9.2.9l19.6 27.7zm190.4 0c1.7 2.4 1.5 5.6-.5 7.7-53.6 56.9-172.8 32.1-172.8-67.9 0-97.3 121.7-119.5 172.5-70.1 2.1 2 2.5 3.2 1 5.7L420 220.2c-1.9 3.1-6.2 4-9.1 1.7-40.8-32-94.6-14.9-94.6 31.2 0 48 51 70.5 92.2 32.6 2.8-2.5 7.1-2.1 9.2.9l19.6 27.7z"],comment:[576,512,[],"f075","M288 32C129 32 0 125.1 0 240c0 49.3 23.7 94.5 63.3 130.2-8.7 23.3-22.1 32.7-37.1 43.1C15.1 421-6 433 1.6 456.5c5.1 15.4 20.9 24.7 38.1 23.3 57.7-4.6 111.2-19.2 157-42.5 28.7 6.9 59.4 10.7 91.2 10.7 159.1 0 288-93 288-208C576 125.1 447.1 32 288 32zm0 368c-32.5 0-65.4-4.4-97.3-14-32.3 19-78.7 46-134.7 54 32-24 56.8-61.6 61.2-88.4C79.1 325.6 48 286.7 48 240c0-70.9 86.3-160 240-160s240 89.1 240 160c0 71-86.3 160-240 160z"],"comment-alt":[576,512,[],"f27a","M288 32C129 32 0 125.1 0 240c0 49.3 23.7 94.5 63.3 130.2-8.7 23.3-22.1 32.7-37.1 43.1C15.1 421-6 433 1.6 456.5c5.1 15.4 20.9 24.7 38.1 23.3 57.7-4.6 111.2-19.2 157-42.5 28.7 6.9 59.4 10.7 91.2 10.7 159.1 0 288-93 288-208C576 125.1 447.1 32 288 32zm0 368c-32.5 0-65.4-4.4-97.3-14-32.3 19-78.7 46-134.7 54 32-24 56.8-61.6 61.2-88.4C79.1 325.6 48 286.7 48 240c0-70.9 86.3-160 240-160s240 89.1 240 160c0 71-86.3 160-240 160zm-64-160c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48zm112 0c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48zm112 0c0 26.5-21.5 48-48 48s-48-21.5-48-48 21.5-48 48-48 48 21.5 48 48z"],comments:[576,512,[],"f086","M574.507 443.86c-5.421 21.261-24.57 36.14-46.511 36.14-32.246 0-66.511-9.99-102.1-29.734-50.64 11.626-109.151 7.877-157.96-13.437 41.144-2.919 80.361-12.339 116.331-28.705 16.322-1.22 32.674-4.32 48.631-9.593C454.404 412.365 490.663 432 527.996 432c-32-17.455-43.219-38.958-46.159-58.502 25.443-18.848 46.159-47.183 46.159-81.135 0-10.495-2.383-21.536-7.041-32.467 7.405-25.93 8.656-50.194 5.185-73.938 32.164 30.461 49.856 69.128 49.856 106.405 0 33.893-12.913 65.047-34.976 91.119 2.653 2.038 5.924 4.176 9.962 6.378 19.261 10.508 28.947 32.739 23.525 54zM240.002 80C117.068 80 48.004 152.877 48.004 210.909c0 38.196 24.859 70.072 55.391 91.276-3.527 21.988-16.991 46.179-55.391 65.815 44.8 0 88.31-22.089 114.119-37.653 25.52 7.906 51.883 11.471 77.879 11.471C362.998 341.818 432 268.976 432 210.909 432 152.882 362.943 80 240.002 80m0-48C390.193 32 480 126.026 480 210.909c0 22.745-6.506 46.394-18.816 68.391-11.878 21.226-28.539 40.294-49.523 56.674-21.593 16.857-46.798 30.045-74.913 39.197-29.855 9.719-62.405 14.646-96.746 14.646-24.449 0-48.34-2.687-71.292-8.004C126.311 404.512 85.785 416 48.004 416c-22.18 0-41.472-15.197-46.665-36.761-5.194-21.563 5.064-43.878 24.811-53.976 7.663-3.918 13.324-7.737 17.519-11.294-7.393-7.829-13.952-16.124-19.634-24.844C8.09 264.655.005 238.339.005 210.909.005 126.259 89.508 32 240.002 32z"],compass:[512,512,[],"f14e","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 448c-110.532 0-200-89.451-200-200 0-110.531 89.451-200 200-200 110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200zm91.326-312.131l-33.359 137.779a24.005 24.005 0 0 1-6.772 11.729l-102.64 97.779c-17.104 16.293-45.56.434-39.88-23.024l33.359-137.779a23.997 23.997 0 0 1 6.772-11.729l102.642-97.779c17.285-16.47 45.494-.175 39.878 23.024zM256 224c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32z"],copy:[448,512,[],"f0c5","M433.941 65.941l-51.882-51.882A48 48 0 0 0 348.118 0H176c-26.51 0-48 21.49-48 48v48H48c-26.51 0-48 21.49-48 48v320c0 26.51 21.49 48 48 48h224c26.51 0 48-21.49 48-48v-48h80c26.51 0 48-21.49 48-48V99.882a48 48 0 0 0-14.059-33.941zM266 464H54a6 6 0 0 1-6-6V150a6 6 0 0 1 6-6h74v224c0 26.51 21.49 48 48 48h96v42a6 6 0 0 1-6 6zm128-96H182a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h106v88c0 13.255 10.745 24 24 24h88v202a6 6 0 0 1-6 6zm6-256h-64V48h9.632c1.591 0 3.117.632 4.243 1.757l48.368 48.368a6 6 0 0 1 1.757 4.243V112z"],copyright:[512,512,[],"f1f9","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 448c-110.532 0-200-89.451-200-200 0-110.531 89.451-200 200-200 110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200zm107.351-101.064c-9.614 9.712-45.53 41.396-104.065 41.396-82.43 0-140.484-61.425-140.484-141.567 0-79.152 60.275-139.401 139.762-139.401 55.531 0 88.738 26.62 97.593 34.779a11.965 11.965 0 0 1 1.936 15.322l-18.155 28.113c-3.841 5.95-11.966 7.282-17.499 2.921-8.595-6.776-31.814-22.538-61.708-22.538-48.303 0-77.916 35.33-77.916 80.082 0 41.589 26.888 83.692 78.277 83.692 32.657 0 56.843-19.039 65.726-27.225 5.27-4.857 13.596-4.039 17.82 1.738l19.865 27.17a11.947 11.947 0 0 1-1.152 15.518z"],"credit-card":[576,512,[],"f09d","M527.9 32H48.1C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48.1 48h479.8c26.6 0 48.1-21.5 48.1-48V80c0-26.5-21.5-48-48.1-48zM54.1 80h467.8c3.3 0 6 2.7 6 6v42H48.1V86c0-3.3 2.7-6 6-6zm467.8 352H54.1c-3.3 0-6-2.7-6-6V256h479.8v170c0 3.3-2.7 6-6 6zM192 332v40c0 6.6-5.4 12-12 12h-72c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h72c6.6 0 12 5.4 12 12zm192 0v40c0 6.6-5.4 12-12 12H236c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h136c6.6 0 12 5.4 12 12z"],"dot-circle":[512,512,[],"f192","M256 56c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m0-48C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 168c-44.183 0-80 35.817-80 80s35.817 80 80 80 80-35.817 80-80-35.817-80-80-80z"],edit:[576,512,[],"f044","M402.3 344.9l32-32c5-5 13.7-1.5 13.7 5.7V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h273.5c7.1 0 10.7 8.6 5.7 13.7l-32 32c-1.5 1.5-3.5 2.3-5.7 2.3H48v352h352V350.5c0-2.1.8-4.1 2.3-5.6zm156.6-201.8L296.3 405.7l-90.4 10c-26.2 2.9-48.5-19.2-45.6-45.6l10-90.4L432.9 17.1c22.9-22.9 59.9-22.9 82.7 0l43.2 43.2c22.9 22.9 22.9 60 .1 82.8zM460.1 174L402 115.9 216.2 301.8l-7.3 65.3 65.3-7.3L460.1 174zm64.8-79.7l-43.2-43.2c-4.1-4.1-10.8-4.1-14.8 0L436 82l58.1 58.1 30.9-30.9c4-4.2 4-10.8-.1-14.9z"],envelope:[512,512,[],"f0e0","M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm0 48v40.805c-22.422 18.259-58.168 46.651-134.587 106.49-16.841 13.247-50.201 45.072-73.413 44.701-23.208.375-56.579-31.459-73.413-44.701C106.18 199.465 70.425 171.067 48 152.805V112h416zM48 400V214.398c22.914 18.251 55.409 43.862 104.938 82.646 21.857 17.205 60.134 55.186 103.062 54.955 42.717.231 80.509-37.199 103.053-54.947 49.528-38.783 82.032-64.401 104.947-82.653V400H48z"],"envelope-open":[512,512,[],"f2b6","M494.586 164.516c-4.697-3.883-111.723-89.95-135.251-108.657C337.231 38.191 299.437 0 256 0c-43.205 0-80.636 37.717-103.335 55.859-24.463 19.45-131.07 105.195-135.15 108.549A48.004 48.004 0 0 0 0 201.485V464c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V201.509a48 48 0 0 0-17.414-36.993zM464 458a6 6 0 0 1-6 6H54a6 6 0 0 1-6-6V204.347c0-1.813.816-3.526 2.226-4.665 15.87-12.814 108.793-87.554 132.364-106.293C200.755 78.88 232.398 48 256 48c23.693 0 55.857 31.369 73.41 45.389 23.573 18.741 116.503 93.493 132.366 106.316a5.99 5.99 0 0 1 2.224 4.663V458zm-31.991-187.704c4.249 5.159 3.465 12.795-1.745 16.981-28.975 23.283-59.274 47.597-70.929 56.863C336.636 362.283 299.205 400 256 400c-43.452 0-81.287-38.237-103.335-55.86-11.279-8.967-41.744-33.413-70.927-56.865-5.21-4.187-5.993-11.822-1.745-16.981l15.258-18.528c4.178-5.073 11.657-5.843 16.779-1.726 28.618 23.001 58.566 47.035 70.56 56.571C200.143 320.631 232.307 352 256 352c23.602 0 55.246-30.88 73.41-45.389 11.994-9.535 41.944-33.57 70.563-56.568 5.122-4.116 12.601-3.346 16.778 1.727l15.258 18.526z"],"eye-slash":[576,512,[],"f070","M272.702 359.139c-80.483-9.011-136.212-86.886-116.93-167.042l116.93 167.042zM288 392c-102.556 0-192.092-54.701-240-136 21.755-36.917 52.1-68.342 88.344-91.658l-27.541-39.343C67.001 152.234 31.921 188.741 6.646 231.631a47.999 47.999 0 0 0 0 48.739C63.004 376.006 168.14 440 288 440a332.89 332.89 0 0 0 39.648-2.367l-32.021-45.744A284.16 284.16 0 0 1 288 392zm281.354-111.631c-33.232 56.394-83.421 101.742-143.554 129.492l48.116 68.74c3.801 5.429 2.48 12.912-2.949 16.712L450.23 509.83c-5.429 3.801-12.912 2.48-16.712-2.949L102.084 33.399c-3.801-5.429-2.48-12.912 2.949-16.712L125.77 2.17c5.429-3.801 12.912-2.48 16.712 2.949l55.526 79.325C226.612 76.343 256.808 72 288 72c119.86 0 224.996 63.994 281.354 159.631a48.002 48.002 0 0 1 0 48.738zM528 256c-44.157-74.933-123.677-127.27-216.162-135.007C302.042 131.078 296 144.83 296 160c0 30.928 25.072 56 56 56s56-25.072 56-56l-.001-.042c30.632 57.277 16.739 130.26-36.928 171.719l26.695 38.135C452.626 346.551 498.308 306.386 528 256z"],file:[384,512,[],"f15b","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48z"],"file-alt":[384,512,[],"f15c","M288 248v28c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-28c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm-12 72H108c-6.6 0-12 5.4-12 12v28c0 6.6 5.4 12 12 12h168c6.6 0 12-5.4 12-12v-28c0-6.6-5.4-12-12-12zm108-188.1V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V48C0 21.5 21.5 0 48 0h204.1C264.8 0 277 5.1 286 14.1L369.9 98c9 8.9 14.1 21.2 14.1 33.9zm-128-80V128h76.1L256 51.9zM336 464V176H232c-13.3 0-24-10.7-24-24V48H48v416h288z"],"file-archive":[384,512,[],"f1c6","M369.941 97.941l-83.882-83.882A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V131.882a48 48 0 0 0-14.059-33.941zM256 51.882L332.118 128H256V51.882zM336 464H48V48h79.714v16h32V48H208v104c0 13.255 10.745 24 24 24h104v288zM192.27 96h-32V64h32v32zm-32 0v32h-32V96h32zm0 64v32h-32v-32h32zm32 0h-32v-32h32v32zm1.909 105.678A12 12 0 0 0 182.406 256H160.27v-32h-32v32l-19.69 97.106C101.989 385.611 126.834 416 160 416c33.052 0 57.871-30.192 51.476-62.62l-17.297-87.702zM160.27 390.073c-17.918 0-32.444-12.105-32.444-27.036 0-14.932 14.525-27.036 32.444-27.036s32.444 12.105 32.444 27.036c0 14.931-14.526 27.036-32.444 27.036zm32-166.073h-32v-32h32v32z"],"file-audio":[384,512,[],"f1c7","M369.941 97.941l-83.882-83.882A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V131.882a48 48 0 0 0-14.059-33.941zM332.118 128H256V51.882L332.118 128zM48 464V48h160v104c0 13.255 10.745 24 24 24h104v288H48zm144-76.024c0 10.691-12.926 16.045-20.485 8.485L136 360.486h-28c-6.627 0-12-5.373-12-12v-56c0-6.627 5.373-12 12-12h28l35.515-36.947c7.56-7.56 20.485-2.206 20.485 8.485v135.952zm41.201-47.13c9.051-9.297 9.06-24.133.001-33.439-22.149-22.752 12.235-56.246 34.395-33.481 27.198 27.94 27.212 72.444.001 100.401-21.793 22.386-56.947-10.315-34.397-33.481z"],"file-code":[384,512,[],"f1c9","M369.941 97.941l-83.882-83.882A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V131.882a48 48 0 0 0-14.059-33.941zM332.118 128H256V51.882L332.118 128zM48 464V48h160v104c0 13.255 10.745 24 24 24h104v288H48zm101.677-115.115L116.854 320l32.822-28.885a8.793 8.793 0 0 0 .605-12.624l-17.403-18.564c-3.384-3.613-8.964-3.662-12.438-.401L62.78 313.58c-3.703 3.474-3.704 9.367.001 12.84l57.659 54.055a8.738 8.738 0 0 0 6.012 2.381 8.746 8.746 0 0 0 6.427-2.782l17.403-18.563a8.795 8.795 0 0 0-.605-12.626zm84.284-127.85l-24.401-7.084a8.796 8.796 0 0 0-10.905 5.998L144.04 408.061c-1.353 4.66 1.338 9.552 5.998 10.905l24.403 7.084c4.68 1.355 9.557-1.354 10.905-5.998l54.612-188.112c1.354-4.66-1.337-9.552-5.997-10.905zm87.258 92.545l-57.658-54.055c-3.526-3.307-9.099-3.165-12.439.401l-17.403 18.563a8.795 8.795 0 0 0 .605 12.625L267.146 320l-32.822 28.885a8.793 8.793 0 0 0-.605 12.624l17.403 18.564a8.797 8.797 0 0 0 12.439.401h-.001l57.66-54.055c3.703-3.473 3.703-9.366-.001-12.839z"],"file-excel":[384,512,[],"f1c3","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm212-240h-28.8c-4.4 0-8.4 2.4-10.5 6.3-18 33.1-22.2 42.4-28.6 57.7-13.9-29.1-6.9-17.3-28.6-57.7-2.1-3.9-6.2-6.3-10.6-6.3H124c-9.3 0-15 10-10.4 18l46.3 78-46.3 78c-4.7 8 1.1 18 10.4 18h28.9c4.4 0 8.4-2.4 10.5-6.3 21.7-40 23-45 28.6-57.7 14.9 30.2 5.9 15.9 28.6 57.7 2.1 3.9 6.2 6.3 10.6 6.3H260c9.3 0 15-10 10.4-18L224 320c.7-1.1 30.3-50.5 46.3-78 4.7-8-1.1-18-10.3-18z"],"file-image":[384,512,[],"f1c5","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm32-48h224V288l-23.5-23.5c-4.7-4.7-12.3-4.7-17 0L176 352l-39.5-39.5c-4.7-4.7-12.3-4.7-17 0L80 352v64zm48-240c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z"],"file-pdf":[384,512,[],"f1c1","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm250.2-143.7c-12.2-12-47-8.7-64.4-6.5-17.2-10.5-28.7-25-36.8-46.3 3.9-16.1 10.1-40.6 5.4-56-4.2-26.2-37.8-23.6-42.6-5.9-4.4 16.1-.4 38.5 7 67.1-10 23.9-24.9 56-35.4 74.4-20 10.3-47 26.2-51 46.2-3.3 15.8 26 55.2 76.1-31.2 22.4-7.4 46.8-16.5 68.4-20.1 18.9 10.2 41 17 55.8 17 25.5 0 28-28.2 17.5-38.7zm-198.1 77.8c5.1-13.7 24.5-29.5 30.4-35-19 30.3-30.4 35.7-30.4 35zm81.6-190.6c7.4 0 6.7 32.1 1.8 40.8-4.4-13.9-4.3-40.8-1.8-40.8zm-24.4 136.6c9.7-16.9 18-37 24.7-54.7 8.3 15.1 18.9 27.2 30.1 35.5-20.8 4.3-38.9 13.1-54.8 19.2zm131.6-5s-5 6-37.3-7.8c35.1-2.6 40.9 5.4 37.3 7.8z"],"file-powerpoint":[384,512,[],"f1c4","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm72-60V236c0-6.6 5.4-12 12-12h69.2c36.7 0 62.8 27 62.8 66.3 0 74.3-68.7 66.5-95.5 66.5V404c0 6.6-5.4 12-12 12H132c-6.6 0-12-5.4-12-12zm48.5-87.4h23c7.9 0 13.9-2.4 18.1-7.2 8.5-9.8 8.4-28.5.1-37.8-4.1-4.6-9.9-7-17.4-7h-23.9v52z"],"file-video":[384,512,[],"f1c8","M369.941 97.941l-83.882-83.882A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V131.882a48 48 0 0 0-14.059-33.941zM332.118 128H256V51.882L332.118 128zM48 464V48h160v104c0 13.255 10.745 24 24 24h104v288H48zm228.687-211.303L224 305.374V268c0-11.046-8.954-20-20-20H100c-11.046 0-20 8.954-20 20v104c0 11.046 8.954 20 20 20h104c11.046 0 20-8.954 20-20v-37.374l52.687 52.674C286.704 397.318 304 390.28 304 375.986V264.011c0-14.311-17.309-21.319-27.313-11.314z"],"file-word":[384,512,[],"f1c2","M369.9 97.9L286 14C277 5 264.8-.1 252.1-.1H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48V131.9c0-12.7-5.1-25-14.1-34zM332.1 128H256V51.9l76.1 76.1zM48 464V48h160v104c0 13.3 10.7 24 24 24h104v288H48zm220.1-208c-5.7 0-10.6 4-11.7 9.5-20.6 97.7-20.4 95.4-21 103.5-.2-1.2-.4-2.6-.7-4.3-.8-5.1.3.2-23.6-99.5-1.3-5.4-6.1-9.2-11.7-9.2h-13.3c-5.5 0-10.3 3.8-11.7 9.1-24.4 99-24 96.2-24.8 103.7-.1-1.1-.2-2.5-.5-4.2-.7-5.2-14.1-73.3-19.1-99-1.1-5.6-6-9.7-11.8-9.7h-16.8c-7.8 0-13.5 7.3-11.7 14.8 8 32.6 26.7 109.5 33.2 136 1.3 5.4 6.1 9.1 11.7 9.1h25.2c5.5 0 10.3-3.7 11.6-9.1l17.9-71.4c1.5-6.2 2.5-12 3-17.3l2.9 17.3c.1.4 12.6 50.5 17.9 71.4 1.3 5.3 6.1 9.1 11.6 9.1h24.7c5.5 0 10.3-3.7 11.6-9.1 20.8-81.9 30.2-119 34.5-136 1.9-7.6-3.8-14.9-11.6-14.9h-15.8z"],flag:[512,512,[],"f024","M336.174 80c-49.132 0-93.305-32-161.913-32-31.301 0-58.303 6.482-80.721 15.168a48.04 48.04 0 0 0 2.142-20.727C93.067 19.575 74.167 1.594 51.201.104 23.242-1.71 0 20.431 0 48c0 17.764 9.657 33.262 24 41.562V496c0 8.837 7.163 16 16 16h16c8.837 0 16-7.163 16-16v-83.443C109.869 395.28 143.259 384 199.826 384c49.132 0 93.305 32 161.913 32 58.479 0 101.972-22.617 128.548-39.981C503.846 367.161 512 352.051 512 335.855V95.937c0-34.459-35.264-57.768-66.904-44.117C409.193 67.309 371.641 80 336.174 80zM464 336c-21.783 15.412-60.824 32-102.261 32-59.945 0-102.002-32-161.913-32-43.361 0-96.379 9.403-127.826 24V128c21.784-15.412 60.824-32 102.261-32 59.945 0 102.002 32 161.913 32 43.271 0 96.32-17.366 127.826-32v240z"],folder:[512,512,[],"f07b","M464 128H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48zm-6 272H54c-3.314 0-6-2.678-6-5.992V117.992A5.993 5.993 0 0 1 54 112h134.118l64 64H458a6 6 0 0 1 6 6v212a6 6 0 0 1-6 6z"],"folder-open":[576,512,[],"f07c","M527.943 224H480v-48c0-26.51-21.49-48-48-48H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h400a48.001 48.001 0 0 0 40.704-22.56l79.942-128c19.948-31.917-3.038-73.44-40.703-73.44zM54 112h134.118l64 64H426a6 6 0 0 1 6 6v42H152a48 48 0 0 0-41.098 23.202L48 351.449V117.993A5.993 5.993 0 0 1 54 112zm394 288H72l77.234-128H528l-80 128z"],frown:[512,512,[],"f119","M256 56c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m0-48C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm64 136c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059s-23.059-10.324-23.059-23.059v-.017C266.386 181.488 264 190.465 264 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm-128 0c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059-12.735 0-23.059-10.324-23.059-23.059v-.017C138.386 181.488 136 190.465 136 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm171.547 201.782c-56.595-76.964-158.383-77.065-215.057-.001-18.82 25.593 19.858 54.018 38.67 28.438 37.511-51.01 100.365-50.796 137.717-.001 18.509 25.172 57.821-2.395 38.67-28.436z"],futbol:[512,512,[],"f1e3","M207.898 325.571l-29.894-91.312L256 177.732l77.996 56.527-29.622 91.312h-96.476zM504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-455.998-.19L48 256c0 44.7 14.015 87.242 39.95 122.626l7.982-35.118 88.595 10.871 37.775 80.985-30.978 18.427c41.832 13.631 87.598 13.606 129.354 0L289.7 435.364l37.775-80.985 88.594-10.871 7.982 35.118C449.985 343.242 464 300.7 464 256l-.002-.19-27.003 23.561-65.223-60.875 17.122-87.779 35.538 3.183c-25.216-34.63-61.309-62.053-104.577-75.951l14.143 33.091L256 134.25l-77.996-43.21 14.144-33.091C148.868 71.851 112.782 99.277 87.57 133.9l35.81-3.183 16.849 87.779-65.223 60.875-27.004-23.561z"],gem:[576,512,[],"f3a5","M464 0H112c-4 0-7.8 2-10 5.4L2 152.6c-2.9 4.4-2.6 10.2.7 14.2l276 340.8c4.8 5.9 13.8 5.9 18.6 0l276-340.8c3.3-4.1 3.6-9.8.7-14.2L474.1 5.4C471.8 2 468.1 0 464 0zm-19.3 48l63.3 96h-68.4l-51.7-96h56.8zm-202.1 0h90.7l51.7 96H191l51.6-96zm-111.3 0h56.8l-51.7 96H68l63.3-96zm-43 144h51.4L208 352 88.3 192zm102.9 0h193.6L288 435.3 191.2 192zM368 352l68.2-160h51.4L368 352z"],"hand-lizard":[576,512,[],"f258","M556.686 290.542L410.328 64.829C397.001 44.272 374.417 32 349.917 32H56C25.121 32 0 57.122 0 88v8c0 44.112 35.888 80 80 80h196.042l-18.333 48H144c-48.523 0-88 39.477-88 88 0 30.879 25.121 56 56 56h131.552c2.987 0 5.914.549 8.697 1.631L352 408.418V480h224V355.829c0-23.225-6.679-45.801-19.314-65.287zM528 432H400v-23.582c0-19.948-12.014-37.508-30.604-44.736l-99.751-38.788A71.733 71.733 0 0 0 243.552 320H112c-4.411 0-8-3.589-8-8 0-22.056 17.944-40 40-40h113.709c19.767 0 37.786-12.407 44.84-30.873l24.552-64.281c8.996-23.553-8.428-48.846-33.63-48.846H80c-17.645 0-32-14.355-32-32v-8c0-4.411 3.589-8 8-8h293.917c8.166 0 15.693 4.09 20.137 10.942l146.358 225.715A71.84 71.84 0 0 1 528 355.829V432z"],"hand-paper":[448,512,[],"f256","M372.57 112.641v-10.825c0-43.612-40.52-76.691-83.039-65.546-25.629-49.5-94.09-47.45-117.982.747C130.269 26.456 89.144 57.945 89.144 102v126.13c-19.953-7.427-43.308-5.068-62.083 8.871-29.355 21.796-35.794 63.333-14.55 93.153L132.48 498.569a32 32 0 0 0 26.062 13.432h222.897c14.904 0 27.835-10.289 31.182-24.813l30.184-130.958A203.637 203.637 0 0 0 448 310.564V179c0-40.62-35.523-71.992-75.43-66.359zm27.427 197.922c0 11.731-1.334 23.469-3.965 34.886L368.707 464h-201.92L51.591 302.303c-14.439-20.27 15.023-42.776 29.394-22.605l27.128 38.079c8.995 12.626 29.031 6.287 29.031-9.283V102c0-25.645 36.571-24.81 36.571.691V256c0 8.837 7.163 16 16 16h6.856c8.837 0 16-7.163 16-16V67c0-25.663 36.571-24.81 36.571.691V256c0 8.837 7.163 16 16 16h6.856c8.837 0 16-7.163 16-16V101.125c0-25.672 36.57-24.81 36.57.691V256c0 8.837 7.163 16 16 16h6.857c8.837 0 16-7.163 16-16v-76.309c0-26.242 36.57-25.64 36.57-.691v131.563z"],"hand-peace":[448,512,[],"f25b","M362.146 191.976c-13.71-21.649-38.761-34.016-65.006-30.341V74c0-40.804-32.811-74-73.141-74-40.33 0-73.14 33.196-73.14 74L160 168l-18.679-78.85C126.578 50.843 83.85 32.11 46.209 47.208 8.735 62.238-9.571 104.963 5.008 142.85l55.757 144.927c-30.557 24.956-43.994 57.809-24.733 92.218l54.853 97.999C102.625 498.97 124.73 512 148.575 512h205.702c30.744 0 57.558-21.44 64.555-51.797l27.427-118.999a67.801 67.801 0 0 0 1.729-15.203L448 256c0-44.956-43.263-77.343-85.854-64.024zM399.987 326c0 1.488-.169 2.977-.502 4.423l-27.427 119.001c-1.978 8.582-9.29 14.576-17.782 14.576H148.575c-6.486 0-12.542-3.621-15.805-9.449l-54.854-98c-4.557-8.141-2.619-18.668 4.508-24.488l26.647-21.764a16 16 0 0 0 4.812-18.139l-64.09-166.549C37.226 92.956 84.37 74.837 96.51 106.389l59.784 155.357A16 16 0 0 0 171.227 272h11.632c8.837 0 16-7.163 16-16V74c0-34.375 50.281-34.43 50.281 0v182c0 8.837 7.163 16 16 16h6.856c8.837 0 16-7.163 16-16v-28c0-25.122 36.567-25.159 36.567 0v28c0 8.837 7.163 16 16 16h6.856c8.837 0 16-7.163 16-16 0-25.12 36.567-25.16 36.567 0v70z"],"hand-point-down":[448,512,[],"f0a7","M188.8 512c45.616 0 83.2-37.765 83.2-83.2v-35.647a93.148 93.148 0 0 0 22.064-7.929c22.006 2.507 44.978-3.503 62.791-15.985C409.342 368.1 448 331.841 448 269.299V248c0-60.063-40-98.512-40-127.2v-2.679c4.952-5.747 8-13.536 8-22.12V32c0-17.673-12.894-32-28.8-32H156.8C140.894 0 128 14.327 128 32v64c0 8.584 3.048 16.373 8 22.12v2.679c0 6.964-6.193 14.862-23.668 30.183l-.148.129-.146.131c-9.937 8.856-20.841 18.116-33.253 25.851C48.537 195.798 0 207.486 0 252.8c0 56.928 35.286 92 83.2 92 8.026 0 15.489-.814 22.4-2.176V428.8c0 45.099 38.101 83.2 83.2 83.2zm0-48c-18.7 0-35.2-16.775-35.2-35.2V270.4c-17.325 0-35.2 26.4-70.4 26.4-26.4 0-35.2-20.625-35.2-44 0-8.794 32.712-20.445 56.1-34.926 14.575-9.074 27.225-19.524 39.875-30.799 18.374-16.109 36.633-33.836 39.596-59.075h176.752C364.087 170.79 400 202.509 400 248v21.299c0 40.524-22.197 57.124-61.325 50.601-8.001 14.612-33.979 24.151-53.625 12.925-18.225 19.365-46.381 17.787-61.05 4.95V428.8c0 18.975-16.225 35.2-35.2 35.2zM328 64c0-13.255 10.745-24 24-24s24 10.745 24 24-10.745 24-24 24-24-10.745-24-24z"],"hand-point-left":[512,512,[],"f0a5","M0 220.8C0 266.416 37.765 304 83.2 304h35.647a93.148 93.148 0 0 0 7.929 22.064c-2.507 22.006 3.503 44.978 15.985 62.791C143.9 441.342 180.159 480 242.701 480H264c60.063 0 98.512-40 127.2-40h2.679c5.747 4.952 13.536 8 22.12 8h64c17.673 0 32-12.894 32-28.8V188.8c0-15.906-14.327-28.8-32-28.8h-64c-8.584 0-16.373 3.048-22.12 8H391.2c-6.964 0-14.862-6.193-30.183-23.668l-.129-.148-.131-.146c-8.856-9.937-18.116-20.841-25.851-33.253C316.202 80.537 304.514 32 259.2 32c-56.928 0-92 35.286-92 83.2 0 8.026.814 15.489 2.176 22.4H83.2C38.101 137.6 0 175.701 0 220.8zm48 0c0-18.7 16.775-35.2 35.2-35.2h158.4c0-17.325-26.4-35.2-26.4-70.4 0-26.4 20.625-35.2 44-35.2 8.794 0 20.445 32.712 34.926 56.1 9.074 14.575 19.524 27.225 30.799 39.875 16.109 18.374 33.836 36.633 59.075 39.596v176.752C341.21 396.087 309.491 432 264 432h-21.299c-40.524 0-57.124-22.197-50.601-61.325-14.612-8.001-24.151-33.979-12.925-53.625-19.365-18.225-17.787-46.381-4.95-61.05H83.2C64.225 256 48 239.775 48 220.8zM448 360c13.255 0 24 10.745 24 24s-10.745 24-24 24-24-10.745-24-24 10.745-24 24-24z"],"hand-point-right":[512,512,[],"f0a4","M428.8 137.6h-86.177a115.52 115.52 0 0 0 2.176-22.4c0-47.914-35.072-83.2-92-83.2-45.314 0-57.002 48.537-75.707 78.784-7.735 12.413-16.994 23.317-25.851 33.253l-.131.146-.129.148C135.662 161.807 127.764 168 120.8 168h-2.679c-5.747-4.952-13.536-8-22.12-8H32c-17.673 0-32 12.894-32 28.8v230.4C0 435.106 14.327 448 32 448h64c8.584 0 16.373-3.048 22.12-8h2.679c28.688 0 67.137 40 127.2 40h21.299c62.542 0 98.8-38.658 99.94-91.145 12.482-17.813 18.491-40.785 15.985-62.791A93.148 93.148 0 0 0 393.152 304H428.8c45.435 0 83.2-37.584 83.2-83.2 0-45.099-38.101-83.2-83.2-83.2zm0 118.4h-91.026c12.837 14.669 14.415 42.825-4.95 61.05 11.227 19.646 1.687 45.624-12.925 53.625 6.524 39.128-10.076 61.325-50.6 61.325H248c-45.491 0-77.21-35.913-120-39.676V215.571c25.239-2.964 42.966-21.222 59.075-39.596 11.275-12.65 21.725-25.3 30.799-39.875C232.355 112.712 244.006 80 252.8 80c23.375 0 44 8.8 44 35.2 0 35.2-26.4 53.075-26.4 70.4h158.4c18.425 0 35.2 16.5 35.2 35.2 0 18.975-16.225 35.2-35.2 35.2zM88 384c0 13.255-10.745 24-24 24s-24-10.745-24-24 10.745-24 24-24 24 10.745 24 24z"],"hand-point-up":[448,512,[],"f0a6","M105.6 83.2v86.177a115.52 115.52 0 0 0-22.4-2.176c-47.914 0-83.2 35.072-83.2 92 0 45.314 48.537 57.002 78.784 75.707 12.413 7.735 23.317 16.994 33.253 25.851l.146.131.148.129C129.807 376.338 136 384.236 136 391.2v2.679c-4.952 5.747-8 13.536-8 22.12v64c0 17.673 12.894 32 28.8 32h230.4c15.906 0 28.8-14.327 28.8-32v-64c0-8.584-3.048-16.373-8-22.12V391.2c0-28.688 40-67.137 40-127.2v-21.299c0-62.542-38.658-98.8-91.145-99.94-17.813-12.482-40.785-18.491-62.791-15.985A93.148 93.148 0 0 0 272 118.847V83.2C272 37.765 234.416 0 188.8 0c-45.099 0-83.2 38.101-83.2 83.2zm118.4 0v91.026c14.669-12.837 42.825-14.415 61.05 4.95 19.646-11.227 45.624-1.687 53.625 12.925 39.128-6.524 61.325 10.076 61.325 50.6V264c0 45.491-35.913 77.21-39.676 120H183.571c-2.964-25.239-21.222-42.966-39.596-59.075-12.65-11.275-25.3-21.725-39.875-30.799C80.712 279.645 48 267.994 48 259.2c0-23.375 8.8-44 35.2-44 35.2 0 53.075 26.4 70.4 26.4V83.2c0-18.425 16.5-35.2 35.2-35.2 18.975 0 35.2 16.225 35.2 35.2zM352 424c13.255 0 24 10.745 24 24s-10.745 24-24 24-24-10.745-24-24 10.745-24 24-24z"],"hand-pointer":[448,512,[],"f25a","M358.182 179.361c-19.493-24.768-52.679-31.945-79.872-19.098-15.127-15.687-36.182-22.487-56.595-19.629V67c0-36.944-29.736-67-66.286-67S89.143 30.056 89.143 67v161.129c-19.909-7.41-43.272-5.094-62.083 8.872-29.355 21.795-35.793 63.333-14.55 93.152l109.699 154.001C134.632 501.59 154.741 512 176 512h178.286c30.802 0 57.574-21.5 64.557-51.797l27.429-118.999A67.873 67.873 0 0 0 448 326v-84c0-46.844-46.625-79.273-89.818-62.639zM80.985 279.697l27.126 38.079c8.995 12.626 29.031 6.287 29.031-9.283V67c0-25.12 36.571-25.16 36.571 0v175c0 8.836 7.163 16 16 16h6.857c8.837 0 16-7.164 16-16v-35c0-25.12 36.571-25.16 36.571 0v35c0 8.836 7.163 16 16 16H272c8.837 0 16-7.164 16-16v-21c0-25.12 36.571-25.16 36.571 0v21c0 8.836 7.163 16 16 16h6.857c8.837 0 16-7.164 16-16 0-25.121 36.571-25.16 36.571 0v84c0 1.488-.169 2.977-.502 4.423l-27.43 119.001c-1.978 8.582-9.29 14.576-17.782 14.576H176c-5.769 0-11.263-2.878-14.697-7.697l-109.712-154c-14.406-20.223 14.994-42.818 29.394-22.606zM176.143 400v-96c0-8.837 6.268-16 14-16h6c7.732 0 14 7.163 14 16v96c0 8.837-6.268 16-14 16h-6c-7.733 0-14-7.163-14-16zm75.428 0v-96c0-8.837 6.268-16 14-16h6c7.732 0 14 7.163 14 16v96c0 8.837-6.268 16-14 16h-6c-7.732 0-14-7.163-14-16zM327 400v-96c0-8.837 6.268-16 14-16h6c7.732 0 14 7.163 14 16v96c0 8.837-6.268 16-14 16h-6c-7.732 0-14-7.163-14-16z"],"hand-rock":[512,512,[],"f255","M408.864 79.052c-22.401-33.898-66.108-42.273-98.813-23.588-29.474-31.469-79.145-31.093-108.334-.022-47.16-27.02-108.71 5.055-110.671 60.806C44.846 105.407 0 140.001 0 187.429v56.953c0 32.741 14.28 63.954 39.18 85.634l97.71 85.081c4.252 3.702 3.11 5.573 3.11 32.903 0 17.673 14.327 32 32 32h252c17.673 0 32-14.327 32-32 0-23.513-1.015-30.745 3.982-42.37l42.835-99.656c6.094-14.177 9.183-29.172 9.183-44.568V146.963c0-52.839-54.314-88.662-103.136-67.911zM464 261.406a64.505 64.505 0 0 1-5.282 25.613l-42.835 99.655c-5.23 12.171-7.883 25.04-7.883 38.25V432H188v-10.286c0-16.37-7.14-31.977-19.59-42.817l-97.71-85.08C56.274 281.255 48 263.236 48 244.381v-56.953c0-33.208 52-33.537 52 .677v41.228a16 16 0 0 0 5.493 12.067l7 6.095A16 16 0 0 0 139 235.429V118.857c0-33.097 52-33.725 52 .677v26.751c0 8.836 7.164 16 16 16h7c8.836 0 16-7.164 16-16v-41.143c0-33.134 52-33.675 52 .677v40.466c0 8.836 7.163 16 16 16h7c8.837 0 16-7.164 16-16v-27.429c0-33.03 52-33.78 52 .677v26.751c0 8.836 7.163 16 16 16h7c8.837 0 16-7.164 16-16 0-33.146 52-33.613 52 .677v114.445z"],"hand-scissors":[512,512,[],"f257","M256 480l70-.013c5.114 0 10.231-.583 15.203-1.729l118.999-27.427C490.56 443.835 512 417.02 512 386.277V180.575c0-23.845-13.03-45.951-34.005-57.69l-97.999-54.853c-34.409-19.261-67.263-5.824-92.218 24.733L142.85 37.008c-37.887-14.579-80.612 3.727-95.642 41.201-15.098 37.642 3.635 80.37 41.942 95.112L168 192l-94-9.141c-40.804 0-74 32.811-74 73.14 0 40.33 33.196 73.141 74 73.141h87.635c-3.675 26.245 8.692 51.297 30.341 65.006C178.657 436.737 211.044 480 256 480zm0-48.013c-25.16 0-25.12-36.567 0-36.567 8.837 0 16-7.163 16-16v-6.856c0-8.837-7.163-16-16-16h-28c-25.159 0-25.122-36.567 0-36.567h28c8.837 0 16-7.163 16-16v-6.856c0-8.837-7.163-16-16-16H74c-34.43 0-34.375-50.281 0-50.281h182c8.837 0 16-7.163 16-16v-11.632a16 16 0 0 0-10.254-14.933L106.389 128.51c-31.552-12.14-13.432-59.283 19.222-46.717l166.549 64.091a16.001 16.001 0 0 0 18.139-4.812l21.764-26.647c5.82-7.127 16.348-9.064 24.488-4.508l98 54.854c5.828 3.263 9.449 9.318 9.449 15.805v205.701c0 8.491-5.994 15.804-14.576 17.782l-119.001 27.427a19.743 19.743 0 0 1-4.423.502h-70z"],"hand-spock":[512,512,[],"f259","M21.096 381.79l129.092 121.513a32 32 0 0 0 21.932 8.698h237.6c14.17 0 26.653-9.319 30.68-22.904l31.815-107.313A115.955 115.955 0 0 0 477 348.811v-36.839c0-4.051.476-8.104 1.414-12.045l31.73-133.41c10.099-42.412-22.316-82.738-65.544-82.525-4.144-24.856-22.543-47.165-49.85-53.992-35.803-8.952-72.227 12.655-81.25 48.75L296.599 184 274.924 52.01c-8.286-36.07-44.303-58.572-80.304-50.296-29.616 6.804-50.138 32.389-51.882 61.295-42.637.831-73.455 40.563-64.071 81.844l31.04 136.508c-27.194-22.515-67.284-19.992-91.482 5.722-25.376 26.961-24.098 69.325 2.871 94.707zm32.068-61.811l.002-.001c7.219-7.672 19.241-7.98 26.856-.813l53.012 49.894C143.225 378.649 160 371.4 160 357.406v-69.479c0-1.193-.134-2.383-.397-3.546l-34.13-150.172c-5.596-24.617 31.502-32.86 37.054-8.421l30.399 133.757a16 16 0 0 0 15.603 12.454h8.604c10.276 0 17.894-9.567 15.594-19.583l-41.62-181.153c-5.623-24.469 31.39-33.076 37.035-8.508l45.22 196.828A16 16 0 0 0 288.956 272h13.217a16 16 0 0 0 15.522-12.119l42.372-169.49c6.104-24.422 42.962-15.159 36.865 9.217L358.805 252.12c-2.521 10.088 5.115 19.88 15.522 19.88h9.694a16 16 0 0 0 15.565-12.295L426.509 146.6c5.821-24.448 42.797-15.687 36.966 8.802L431.72 288.81a100.094 100.094 0 0 0-2.72 23.162v36.839c0 6.548-.943 13.051-2.805 19.328L397.775 464h-219.31L53.978 346.836c-7.629-7.18-7.994-19.229-.814-26.857z"],handshake:[640,512,[],"f2b5","M616 96h-48c-7.107 0-13.49 3.091-17.884 8H526.59l-31.13-36.3-.16-.18A103.974 103.974 0 0 0 417.03 32h-46.55c-17.75 0-34.9 4.94-49.69 14.01C304.33 36.93 285.67 32 266.62 32h-32.11c-28.903 0-57.599 11.219-79.2 32.8L116.12 104H89.884C85.49 99.091 79.107 96 72 96H24c-13.255 0-24 10.745-24 24v240c0 13.255 10.745 24 24 24h48c10.449 0 19.334-6.68 22.629-16h18.801l75.35 67.57c25.542 26.45 59.925 44.43 96.58 44.43 16.39 0 32.28-3.85 46.1-10.93 24.936.496 51.101-10.368 69.07-31.41 19.684-5.579 37.503-17.426 50.72-34.6 20.989-4.401 40.728-16.492 53.42-35.06h40.701c3.295 9.32 12.18 16 22.629 16h48c13.255 0 24-10.745 24-24V120c0-13.255-10.745-24-24-24zM48 352c-8.837 0-16-7.163-16-16s7.163-16 16-16 16 7.163 16 16-7.163 16-16 16zm412.52-5.76c-15.35 14.295-36.884 11.328-39.95 8 1.414 13.382-18.257 41.043-49.08 38.88-5.541 18.523-28.218 33.826-51.49 25.75-8.89 8.89-22.46 13.13-34.64 13.13-24.95 0-47.77-14.54-63.14-30.91l-81.3-72.91a31.976 31.976 0 0 0-21.36-8.18H96V152h26.75c8.48 0 16.62-3.37 22.62-9.37l43.88-43.88A64.004 64.004 0 0 1 234.51 80h32.11c5.8 0 11.51.79 17 2.3l-43.27 50.49c-23.56 27.48-23.84 67.62-.66 95.44 32.388 38.866 91.378 39.228 124.48 1.98l25.98-30.08L462.59 296c13.44 14.6 10.95 38.13-2.07 50.24zM544 320h-24.458c.104-20.261-6.799-39.33-19.762-54.4L421.7 162.28c4.51-9.51 2.34-21.23-6.01-28.45-10.075-8.691-25.23-7.499-33.86 2.48l-53.63 62.12c-13.828 15.41-38.223 15.145-51.64-.93a25.857 25.857 0 0 1 .23-33.47l57.92-67.58A47.09 47.09 0 0 1 370.48 80h46.55c16.11 0 31.44 6.94 42.07 19.04L504.52 152H544v168zm48 32c-8.837 0-16-7.163-16-16s7.163-16 16-16 16 7.163 16 16-7.163 16-16 16z"],hdd:[576,512,[],"f0a0","M567.403 235.642L462.323 84.589A48 48 0 0 0 422.919 64H153.081a48 48 0 0 0-39.404 20.589L8.597 235.642A48.001 48.001 0 0 0 0 263.054V400c0 26.51 21.49 48 48 48h480c26.51 0 48-21.49 48-48V263.054c0-9.801-3-19.366-8.597-27.412zM153.081 112h269.838l77.913 112H75.168l77.913-112zM528 400H48V272h480v128zm-32-64c0 17.673-14.327 32-32 32s-32-14.327-32-32 14.327-32 32-32 32 14.327 32 32zm-96 0c0 17.673-14.327 32-32 32s-32-14.327-32-32 14.327-32 32-32 32 14.327 32 32z"],heart:[576,512,[],"f004","M257.3 475.4L92.5 313.6C85.4 307 24 248.1 24 174.8 24 84.1 80.8 24 176 24c41.4 0 80.6 22.8 112 49.8 31.3-27 70.6-49.8 112-49.8 91.7 0 152 56.5 152 150.8 0 52-31.8 103.5-68.1 138.7l-.4.4-164.8 161.5a43.7 43.7 0 0 1-61.4 0zM125.9 279.1L288 438.3l161.8-158.7c27.3-27 54.2-66.3 54.2-104.8C504 107.9 465.8 72 400 72c-47.2 0-92.8 49.3-112 68.4-17-17-64-68.4-112-68.4-65.9 0-104 35.9-104 102.8 0 37.3 26.7 78.9 53.9 104.3z"],hospital:[448,512,[],"f0f8","M128 244v-40c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12zm140 12h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12zm-76 84v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm76 12h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12zm180 124v36H0v-36c0-6.627 5.373-12 12-12h19.5V85.035C31.5 73.418 42.245 64 55.5 64H144V24c0-13.255 10.745-24 24-24h112c13.255 0 24 10.745 24 24v40h88.5c13.255 0 24 9.418 24 21.035V464H436c6.627 0 12 5.373 12 12zM79.5 463H192v-67c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v67h112.5V112H304v24c0 13.255-10.745 24-24 24H168c-13.255 0-24-10.745-24-24v-24H79.5v351zM266 64h-26V38a6 6 0 0 0-6-6h-20a6 6 0 0 0-6 6v26h-26a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6h26v26a6 6 0 0 0 6 6h20a6 6 0 0 0 6-6V96h26a6 6 0 0 0 6-6V70a6 6 0 0 0-6-6z"],hourglass:[384,512,[],"f254","M368 48h4c6.627 0 12-5.373 12-12V12c0-6.627-5.373-12-12-12H12C5.373 0 0 5.373 0 12v24c0 6.627 5.373 12 12 12h4c0 80.564 32.188 165.807 97.18 208C47.899 298.381 16 383.9 16 464h-4c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h360c6.627 0 12-5.373 12-12v-24c0-6.627-5.373-12-12-12h-4c0-80.564-32.188-165.807-97.18-208C336.102 213.619 368 128.1 368 48zM64 48h256c0 101.62-57.307 184-128 184S64 149.621 64 48zm256 416H64c0-101.62 57.308-184 128-184s128 82.38 128 184z"],"id-badge":[384,512,[],"f2c1","M192 128c35.346 0 64 28.654 64 64s-28.654 64-64 64-64-28.654-64-64 28.654-64 64-64m61.187 145.847l-18.064-5.161C222.371 275.884 207.658 280 192 280s-30.371-4.116-43.122-11.314l-18.064 5.161C110.207 279.734 96 298.569 96 320v72c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24v-72c0-21.431-14.207-40.266-34.813-46.153zM0 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V48c0-26.51-21.49-48-48-48H48C21.49 0 0 21.49 0 48zm336 32v378a6 6 0 0 1-6 6H54a6 6 0 0 1-6-6V80h288z"],"id-card":[512,512,[],"f2c2","M404 256H300c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12zm12 68v-24c0-6.627-5.373-12-12-12H300c-6.627 0-12 5.373-12 12v24c0 6.627 5.373 12 12 12h104c6.627 0 12-5.373 12-12zm96-212v288c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48zm-48 282V144H48v250a6 6 0 0 0 6 6h404a6 6 0 0 0 6-6zm-288-98c30.928 0 56-25.072 56-56s-25.072-56-56-56-56 25.072-56 56 25.072 56 56 56zm62.896 10.869l-13.464-4.039C211.814 313.568 194.649 320 176 320s-35.814-6.432-49.433-17.17l-13.464 4.039A24 24 0 0 0 96 329.857V372c0 6.627 5.373 12 12 12h136c6.627 0 12-5.373 12-12v-42.143a24 24 0 0 0-17.104-22.988z"],image:[512,512,[],"f03e","M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-6 336H54a6 6 0 0 1-6-6V118a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v276a6 6 0 0 1-6 6zM128 152c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zM96 352h320v-80l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L192 304l-39.515-39.515c-4.686-4.686-12.284-4.686-16.971 0L96 304v48z"],images:[576,512,[],"f302","M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v48H54a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6v-10h48zm42-336H150a6 6 0 0 0-6 6v244a6 6 0 0 0 6 6h372a6 6 0 0 0 6-6V86a6 6 0 0 0-6-6zm6-48c26.51 0 48 21.49 48 48v256c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h384zM264 144c0 22.091-17.909 40-40 40s-40-17.909-40-40 17.909-40 40-40 40 17.909 40 40zm-72 96l39.515-39.515c4.686-4.686 12.284-4.686 16.971 0L288 240l103.515-103.515c4.686-4.686 12.284-4.686 16.971 0L480 208v80H192v-48z"],keyboard:[576,512,[],"f11c","M528 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h480c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm8 336c0 4.411-3.589 8-8 8H48c-4.411 0-8-3.589-8-8V112c0-4.411 3.589-8 8-8h480c4.411 0 8 3.589 8 8v288zM170 270v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm-336 82v-28c0-6.627-5.373-12-12-12H82c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm384 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zM122 188v-28c0-6.627-5.373-12-12-12H82c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm96 0v-28c0-6.627-5.373-12-12-12h-28c-6.627 0-12 5.373-12 12v28c0 6.627 5.373 12 12 12h28c6.627 0 12-5.373 12-12zm-98 158v-16c0-6.627-5.373-12-12-12H180c-6.627 0-12 5.373-12 12v16c0 6.627 5.373 12 12 12h216c6.627 0 12-5.373 12-12z"],lemon:[512,512,[],"f094","M484.112 27.889C455.989-.233 416.108-8.057 387.059 8.865 347.604 31.848 223.504-41.111 91.196 91.197-41.277 223.672 31.923 347.472 8.866 387.058c-16.922 29.051-9.1 68.932 19.022 97.054 28.135 28.135 68.011 35.938 97.057 19.021 39.423-22.97 163.557 49.969 295.858-82.329 132.474-132.477 59.273-256.277 82.331-295.861 16.922-29.05 9.1-68.931-19.022-97.054zm-22.405 72.894c-38.8 66.609 45.6 165.635-74.845 286.08-120.44 120.443-219.475 36.048-286.076 74.843-22.679 13.207-64.035-27.241-50.493-50.488 38.8-66.609-45.6-165.635 74.845-286.08C245.573 4.702 344.616 89.086 411.219 50.292c22.73-13.24 64.005 27.288 50.488 50.491zm-169.861 8.736c1.37 10.96-6.404 20.957-17.365 22.327-54.846 6.855-135.779 87.787-142.635 142.635-1.373 10.989-11.399 18.734-22.326 17.365-10.961-1.37-18.735-11.366-17.365-22.326 9.162-73.286 104.167-168.215 177.365-177.365 10.953-1.368 20.956 6.403 22.326 17.364z"],"life-ring":[512,512,[],"f1cd","M256 504c136.967 0 248-111.033 248-248S392.967 8 256 8 8 119.033 8 256s111.033 248 248 248zm-103.398-76.72l53.411-53.411c31.806 13.506 68.128 13.522 99.974 0l53.411 53.411c-63.217 38.319-143.579 38.319-206.796 0zM336 256c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zm91.28 103.398l-53.411-53.411c13.505-31.806 13.522-68.128 0-99.974l53.411-53.411c38.319 63.217 38.319 143.579 0 206.796zM359.397 84.72l-53.411 53.411c-31.806-13.505-68.128-13.522-99.973 0L152.602 84.72c63.217-38.319 143.579-38.319 206.795 0zM84.72 152.602l53.411 53.411c-13.506 31.806-13.522 68.128 0 99.974L84.72 359.398c-38.319-63.217-38.319-143.579 0-206.796z"],lightbulb:[384,512,[],"f0eb","M272 428v28c0 10.449-6.68 19.334-16 22.629V488c0 13.255-10.745 24-24 24h-80c-13.255 0-24-10.745-24-24v-9.371c-9.32-3.295-16-12.18-16-22.629v-28c0-6.627 5.373-12 12-12h136c6.627 0 12 5.373 12 12zM128 176c0-35.29 28.71-64 64-64 8.837 0 16-7.164 16-16s-7.163-16-16-16c-52.935 0-96 43.065-96 96 0 8.836 7.164 16 16 16s16-7.164 16-16zm64-128c70.734 0 128 57.254 128 128 0 77.602-37.383 60.477-80.98 160h-94.04C101.318 236.33 64 253.869 64 176c0-70.735 57.254-128 128-128m0-48C94.805 0 16 78.803 16 176c0 101.731 51.697 91.541 90.516 192.674 3.55 9.249 12.47 15.326 22.376 15.326h126.215c9.906 0 18.826-6.078 22.376-15.326C316.303 267.541 368 277.731 368 176 368 78.803 289.195 0 192 0z"],"list-alt":[512,512,[],"f022","M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zm-6 400H54a6 6 0 0 1-6-6V86a6 6 0 0 1 6-6h404a6 6 0 0 1 6 6v340a6 6 0 0 1-6 6zm-42-92v24c0 6.627-5.373 12-12 12H204c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h200c6.627 0 12 5.373 12 12zm0-96v24c0 6.627-5.373 12-12 12H204c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h200c6.627 0 12 5.373 12 12zm0-96v24c0 6.627-5.373 12-12 12H204c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h200c6.627 0 12 5.373 12 12zm-252 12c0 19.882-16.118 36-36 36s-36-16.118-36-36 16.118-36 36-36 36 16.118 36 36zm0 96c0 19.882-16.118 36-36 36s-36-16.118-36-36 16.118-36 36-36 36 16.118 36 36zm0 96c0 19.882-16.118 36-36 36s-36-16.118-36-36 16.118-36 36-36 36 16.118 36 36z"],map:[576,512,[],"f279","M508.505 36.17L381.517 92.576 207.179 34.463a47.992 47.992 0 0 0-34.674 1.674l-144 64A48 48 0 0 0 0 144v287.967c0 34.938 35.991 57.864 67.495 43.863l126.988-56.406 174.339 58.113a47.992 47.992 0 0 0 34.674-1.674l144-64A48 48 0 0 0 576 368V80.033c0-34.938-35.991-57.864-67.495-43.863zM360 424l-144-48V88l144 48v288zm-312 8V144l120-53.333v288L48 432zm480-64l-120 53.333v-288L528 80v288z"],meh:[512,512,[],"f11a","M256 56c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m0-48C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm64 136c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059s-23.059-10.324-23.059-23.059v-.017C266.386 181.488 264 190.465 264 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm-128 0c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059-12.735 0-23.059-10.324-23.059-23.059v-.017C138.386 181.488 136 190.465 136 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm136 184H184c-31.776 0-31.749 48 0 48h144c31.776 0 31.749-48 0-48z"],"minus-square":[448,512,[],"f146","M108 284c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h232c6.6 0 12 5.4 12 12v32c0 6.6-5.4 12-12 12H108zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"money-bill-alt":[640,512,[],"f3d1","M320 144c-53.021 0-96 50.143-96 112 0 61.847 42.977 112 96 112 53 0 96-50.13 96-112 0-61.857-42.979-112-96-112zm48 164.428c0 7.477-3.917 11.572-11.572 11.572h-67.293c-7.656 0-11.573-4.095-11.573-11.572v-8.901c0-7.477 3.917-11.572 11.573-11.572h15.131v-39.878c0-5.163.534-10.503.534-10.503h-.356s-1.779 2.67-2.848 3.738c-4.451 4.273-10.504 4.451-15.666-1.068l-5.518-6.231c-5.342-5.341-4.984-11.216.534-16.379l21.72-19.939c4.449-4.095 8.366-5.697 14.42-5.697h12.105c7.656 0 11.75 3.916 11.75 11.572v84.384h15.488c7.655 0 11.572 4.094 11.572 11.572v8.902zM616 64H24C10.745 64 0 74.745 0 88v335c0 13.255 10.745 24 24 24h592c13.255 0 24-10.745 24-24V88c0-13.255-10.745-24-24-24zM512 400H128c0-44.183-35.817-80-80-80V192c44.183 0 80-35.817 80-80h384c0 44.183 35.817 80 80 80v128c-44.183 0-80 35.817-80 80z"],moon:[512,512,[],"f186","M279.135 512c78.756 0 150.982-35.804 198.844-94.775 28.27-34.831-2.558-85.722-46.249-77.401-82.348 15.683-158.272-47.268-158.272-130.792 0-48.424 26.06-92.292 67.434-115.836 38.745-22.05 28.999-80.788-15.022-88.919A257.936 257.936 0 0 0 279.135 0c-141.36 0-256 114.575-256 256 0 141.36 114.576 256 256 256zm0-464c12.985 0 25.689 1.201 38.016 3.478-54.76 31.163-91.693 90.042-91.693 157.554 0 113.848 103.641 199.2 215.252 177.944C402.574 433.964 344.366 464 279.135 464c-114.875 0-208-93.125-208-208s93.125-208 208-208z"],newspaper:[576,512,[],"f1ea","M552 64H112c-20.858 0-38.643 13.377-45.248 32H24c-13.255 0-24 10.745-24 24v272c0 30.928 25.072 56 56 56h496c13.255 0 24-10.745 24-24V88c0-13.255-10.745-24-24-24zM48 392V144h16v248c0 4.411-3.589 8-8 8s-8-3.589-8-8zm480 8H111.422c.374-2.614.578-5.283.578-8V112h416v288zM172 280h136c6.627 0 12-5.373 12-12v-96c0-6.627-5.373-12-12-12H172c-6.627 0-12 5.373-12 12v96c0 6.627 5.373 12 12 12zm28-80h80v40h-80v-40zm-40 140v-24c0-6.627 5.373-12 12-12h136c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12H172c-6.627 0-12-5.373-12-12zm192 0v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12H364c-6.627 0-12-5.373-12-12zm0-144v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12H364c-6.627 0-12-5.373-12-12zm0 72v-24c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12H364c-6.627 0-12-5.373-12-12z"],"object-group":[512,512,[],"f247","M500 128c6.627 0 12-5.373 12-12V44c0-6.627-5.373-12-12-12h-72c-6.627 0-12 5.373-12 12v12H96V44c0-6.627-5.373-12-12-12H12C5.373 32 0 37.373 0 44v72c0 6.627 5.373 12 12 12h12v256H12c-6.627 0-12 5.373-12 12v72c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-12h320v12c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-72c0-6.627-5.373-12-12-12h-12V128h12zm-52-64h32v32h-32V64zM32 64h32v32H32V64zm32 384H32v-32h32v32zm416 0h-32v-32h32v32zm-40-64h-12c-6.627 0-12 5.373-12 12v12H96v-12c0-6.627-5.373-12-12-12H72V128h12c6.627 0 12-5.373 12-12v-12h320v12c0 6.627 5.373 12 12 12h12v256zm-36-192h-84v-52c0-6.628-5.373-12-12-12H108c-6.627 0-12 5.372-12 12v168c0 6.628 5.373 12 12 12h84v52c0 6.628 5.373 12 12 12h200c6.627 0 12-5.372 12-12V204c0-6.628-5.373-12-12-12zm-268-24h144v112H136V168zm240 176H232v-24h76c6.627 0 12-5.372 12-12v-76h56v112z"],"object-ungroup":[576,512,[],"f248","M564 224c6.627 0 12-5.373 12-12v-72c0-6.627-5.373-12-12-12h-72c-6.627 0-12 5.373-12 12v12h-88v-24h12c6.627 0 12-5.373 12-12V44c0-6.627-5.373-12-12-12h-72c-6.627 0-12 5.373-12 12v12H96V44c0-6.627-5.373-12-12-12H12C5.373 32 0 37.373 0 44v72c0 6.627 5.373 12 12 12h12v160H12c-6.627 0-12 5.373-12 12v72c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-12h88v24h-12c-6.627 0-12 5.373-12 12v72c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-12h224v12c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-72c0-6.627-5.373-12-12-12h-12V224h12zM352 64h32v32h-32V64zm0 256h32v32h-32v-32zM64 352H32v-32h32v32zm0-256H32V64h32v32zm32 216v-12c0-6.627-5.373-12-12-12H72V128h12c6.627 0 12-5.373 12-12v-12h224v12c0 6.627 5.373 12 12 12h12v160h-12c-6.627 0-12 5.373-12 12v12H96zm128 136h-32v-32h32v32zm280-64h-12c-6.627 0-12 5.373-12 12v12H256v-12c0-6.627-5.373-12-12-12h-12v-24h88v12c0 6.627 5.373 12 12 12h72c6.627 0 12-5.373 12-12v-72c0-6.627-5.373-12-12-12h-12v-88h88v12c0 6.627 5.373 12 12 12h12v160zm40 64h-32v-32h32v32zm0-256h-32v-32h32v32z"],"paper-plane":[512,512,[],"f1d8","M440 6.5L24 246.4c-34.4 19.9-31.1 70.8 5.7 85.9L144 379.6V464c0 46.4 59.2 65.5 86.6 28.6l43.8-59.1 111.9 46.2c5.9 2.4 12.1 3.6 18.3 3.6 8.2 0 16.3-2.1 23.6-6.2 12.8-7.2 21.6-20 23.9-34.5l59.4-387.2c6.1-40.1-36.9-68.8-71.5-48.9zM192 464v-64.6l36.6 15.1L192 464zm212.6-28.7l-153.8-63.5L391 169.5c10.7-15.5-9.5-33.5-23.7-21.2L155.8 332.6 48 288 464 48l-59.4 387.3z"],"pause-circle":[512,512,[],"f28b","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm96-280v160c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16zm-112 0v160c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16z"],"play-circle":[512,512,[],"f144","M371.7 238l-176-107c-15.8-8.8-35.7 2.5-35.7 21v208c0 18.4 19.8 29.8 35.7 21l176-101c16.4-9.1 16.4-32.8 0-42zM504 256C504 119 393 8 256 8S8 119 8 256s111 248 248 248 248-111 248-248zm-448 0c0-110.5 89.5-200 200-200s200 89.5 200 200-89.5 200-200 200S56 366.5 56 256z"],"plus-square":[448,512,[],"f0fe","M352 240v32c0 6.6-5.4 12-12 12h-88v88c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-88h-88c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h88v-88c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v88h88c6.6 0 12 5.4 12 12zm96-160v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-48 346V86c0-3.3-2.7-6-6-6H54c-3.3 0-6 2.7-6 6v340c0 3.3 2.7 6 6 6h340c3.3 0 6-2.7 6-6z"],"question-circle":[512,512,[],"f059","M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 448c-110.532 0-200-89.431-200-200 0-110.495 89.472-200 200-200 110.491 0 200 89.471 200 200 0 110.53-89.431 200-200 200zm107.244-255.2c0 67.052-72.421 68.084-72.421 92.863V300c0 6.627-5.373 12-12 12h-45.647c-6.627 0-12-5.373-12-12v-8.659c0-35.745 27.1-50.034 47.579-61.516 17.561-9.845 28.324-16.541 28.324-29.579 0-17.246-21.999-28.693-39.784-28.693-23.189 0-33.894 10.977-48.942 29.969-4.057 5.12-11.46 6.071-16.666 2.124l-27.824-21.098c-5.107-3.872-6.251-11.066-2.644-16.363C184.846 131.491 214.94 112 261.794 112c49.071 0 101.45 38.304 101.45 88.8zM298 368c0 23.159-18.841 42-42 42s-42-18.841-42-42 18.841-42 42-42 42 18.841 42 42z"],registered:[512,512,[],"f25d","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 448c-110.532 0-200-89.451-200-200 0-110.531 89.451-200 200-200 110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200zm110.442-81.791c-53.046-96.284-50.25-91.468-53.271-96.085 24.267-13.879 39.482-41.563 39.482-73.176 0-52.503-30.247-85.252-101.498-85.252h-78.667c-6.617 0-12 5.383-12 12V380c0 6.617 5.383 12 12 12h38.568c6.617 0 12-5.383 12-12v-83.663h31.958l47.515 89.303a11.98 11.98 0 0 0 10.593 6.36h42.81c9.14 0 14.914-9.799 10.51-17.791zM256.933 239.906h-33.875v-64.14h27.377c32.417 0 38.929 12.133 38.929 31.709-.001 20.913-11.518 32.431-32.431 32.431z"],save:[448,512,[],"f0c7","M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM272 80v80H144V80h128zm122 352H54a6 6 0 0 1-6-6V86a6 6 0 0 1 6-6h42v104c0 13.255 10.745 24 24 24h176c13.255 0 24-10.745 24-24V83.882l78.243 78.243a6 6 0 0 1 1.757 4.243V426a6 6 0 0 1-6 6zM224 232c-48.523 0-88 39.477-88 88s39.477 88 88 88 88-39.477 88-88-39.477-88-88-88zm0 128c-22.056 0-40-17.944-40-40s17.944-40 40-40 40 17.944 40 40-17.944 40-40 40z"],"share-square":[576,512,[],"f14d","M561.938 158.06L417.94 14.092C387.926-15.922 336 5.097 336 48.032v57.198c-42.45 1.88-84.03 6.55-120.76 17.99-35.17 10.95-63.07 27.58-82.91 49.42C108.22 199.2 96 232.6 96 271.94c0 61.697 33.178 112.455 84.87 144.76 37.546 23.508 85.248-12.651 71.02-55.74-15.515-47.119-17.156-70.923 84.11-78.76V336c0 42.993 51.968 63.913 81.94 33.94l143.998-144c18.75-18.74 18.75-49.14 0-67.88zM384 336V232.16C255.309 234.082 166.492 255.35 206.31 376 176.79 357.55 144 324.08 144 271.94c0-109.334 129.14-118.947 240-119.85V48l144 144-144 144zm24.74 84.493a82.658 82.658 0 0 0 20.974-9.303c7.976-4.952 18.286.826 18.286 10.214V464c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h132c6.627 0 12 5.373 12 12v4.486c0 4.917-2.987 9.369-7.569 11.152-13.702 5.331-26.396 11.537-38.05 18.585a12.138 12.138 0 0 1-6.28 1.777H54a6 6 0 0 0-6 6v340a6 6 0 0 0 6 6h340a6 6 0 0 0 6-6v-25.966c0-5.37 3.579-10.059 8.74-11.541z"],smile:[512,512,[],"f118","M256 56c110.532 0 200 89.451 200 200 0 110.532-89.451 200-200 200-110.532 0-200-89.451-200-200 0-110.532 89.451-200 200-200m0-48C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm64 136c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059s-23.059-10.324-23.059-23.059v-.017C266.386 181.488 264 190.465 264 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm-128 0c-9.535 0-18.512 2.386-26.37 6.589h.017c12.735 0 23.059 10.324 23.059 23.059 0 12.735-10.324 23.059-23.059 23.059-12.735 0-23.059-10.324-23.059-23.059v-.017C138.386 181.488 136 190.465 136 200c0 30.928 25.072 56 56 56s56-25.072 56-56-25.072-56-56-56zm195.372 182.219c18.819-25.592-19.856-54.017-38.67-28.438-50.135 68.177-135.229 68.18-185.367 0-18.828-25.601-57.478 2.861-38.67 28.438 69.298 94.231 193.323 94.351 262.707 0z"],snowflake:[448,512,[],"f2dc","M438.237 355.927l-66.574-38.54 59.448-10.327c5.846-1.375 10.609-5.183 13.458-10.13 2.48-4.307 3.506-9.478 2.524-14.651-2.11-11.115-12.686-18.039-23.621-15.467l-85.423 31.115L255.914 256l82.136-41.926 85.423 31.115c10.936 2.572 21.512-4.352 23.621-15.467 2.111-11.115-5.046-22.209-15.981-24.781l-59.448-10.327 66.573-38.54c9.54-5.523 12.615-18.092 6.867-28.074-5.748-9.982-18.14-13.596-27.68-8.074l-66.574 38.54 20.805-56.787c3.246-10.782-2.758-22.542-13.413-26.268-10.654-3.725-21.922 1.997-25.168 12.779l-15.838 89.735-72.423 41.926V136l69.585-58.621c7.689-8.21 6.997-20.856-1.548-28.245-8.545-7.391-21.705-6.723-29.394 1.486l-38.644 46.46V20c0-11.046-9.318-20-20.813-20s-20.813 8.954-20.813 20v77.08l-38.644-46.46c-7.689-8.21-20.849-8.876-29.394-1.486-8.544 7.389-9.236 20.035-1.547 28.245L203.187 136v83.853l-72.423-41.926-15.838-89.736c-3.247-10.782-14.515-16.504-25.169-12.779-10.656 3.725-16.659 15.486-13.413 26.268l20.805 56.787-66.573-38.54c-9.54-5.523-21.933-1.908-27.68 8.074s-2.673 22.551 6.867 28.074l66.574 38.54-59.449 10.328C5.953 207.515-1.202 218.609.907 229.724c2.11 11.114 12.686 18.038 23.622 15.466l85.422-31.115L192.086 256l-82.136 41.926-85.423-31.115c-10.936-2.572-21.511 4.352-23.622 15.466-2.109 11.113 5.046 22.209 15.981 24.781l59.449 10.328-66.574 38.54C.223 361.449-2.852 374.018 2.896 384s18.14 13.597 27.68 8.074l66.574-38.54-20.805 56.786c-1.735 5.764-.828 11.805 2.02 16.751 2.48 4.307 6.433 7.784 11.392 9.517 10.655 3.725 21.923-1.997 25.169-12.779l15.838-89.736 72.423-41.926V376l-69.585 58.621c-7.69 8.21-6.997 20.855 1.547 28.245 8.544 7.388 21.705 6.723 29.394-1.487l38.644-46.46V492c0 11.046 9.318 20 20.813 20s20.813-8.954 20.813-20v-77.081l38.644 46.46c4.111 4.389 9.782 6.621 15.478 6.621 4.96 0 9.939-1.694 13.916-5.134 8.545-7.39 9.237-20.035 1.548-28.245L244.813 376v-83.853l72.423 41.926 15.838 89.736c3.246 10.782 14.514 16.504 25.168 12.779 10.653-3.726 16.659-15.487 13.412-26.268l-20.805-56.787 66.574 38.54c9.54 5.523 21.933 1.908 27.68-8.074 5.749-9.981 2.675-22.55-6.866-28.072z"],square:[448,512,[],"f0c8","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-6 400H54c-3.3 0-6-2.7-6-6V86c0-3.3 2.7-6 6-6h340c3.3 0 6 2.7 6 6v340c0 3.3-2.7 6-6 6z"],star:[576,512,[],"f005","M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z"],"star-half":[576,512,[],"f089","M288 385.3l-124.3 65.4 23.7-138.4-100.6-98 139-20.2 62.2-126V0c-11.4 0-22.8 5.9-28.7 17.8L194 150.2 47.9 171.4c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.1 23 46 46.4 33.7L288 439.6v-54.3z"],"sticky-note":[448,512,[],"f249","M448 348.106V80c0-26.51-21.49-48-48-48H48C21.49 32 0 53.49 0 80v351.988c0 26.51 21.49 48 48 48h268.118a48 48 0 0 0 33.941-14.059l83.882-83.882A48 48 0 0 0 448 348.106zm-128 80v-76.118h76.118L320 428.106zM400 80v223.988H296c-13.255 0-24 10.745-24 24v104H48V80h352z"],"stop-circle":[512,512,[],"f28d","M504 256C504 119 393 8 256 8S8 119 8 256s111 248 248 248 248-111 248-248zm-448 0c0-110.5 89.5-200 200-200s200 89.5 200 200-89.5 200-200 200S56 366.5 56 256zm296-80v160c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16z"],sun:[512,512,[],"f185","M220.116 487.936l-20.213-49.425a3.992 3.992 0 0 0-5.808-1.886l-45.404 28.104c-29.466 18.24-66.295-8.519-58.054-42.179l12.699-51.865a3.993 3.993 0 0 0-3.59-4.941l-53.251-3.951c-34.554-2.562-48.632-45.855-22.174-68.247L65.08 259.05a3.992 3.992 0 0 0 0-6.106l-40.76-34.497c-26.45-22.384-12.39-65.682 22.174-68.246l53.251-3.951a3.993 3.993 0 0 0 3.59-4.941L90.637 89.443c-8.239-33.656 28.581-60.42 58.054-42.179l45.403 28.104a3.993 3.993 0 0 0 5.808-1.887l20.213-49.425c13.116-32.071 58.638-32.081 71.758 0l20.212 49.424a3.994 3.994 0 0 0 5.809 1.887l45.403-28.104c29.464-18.236 66.297 8.513 58.054 42.179l-12.699 51.865a3.995 3.995 0 0 0 3.59 4.941l53.251 3.951c34.553 2.563 48.633 45.854 22.175 68.246l-40.76 34.497a3.993 3.993 0 0 0 0 6.107l40.76 34.496c26.511 22.441 12.322 65.689-22.175 68.247l-53.251 3.951a3.993 3.993 0 0 0-3.589 4.942l12.698 51.864c8.241 33.658-28.583 60.421-58.054 42.18l-45.403-28.104a3.994 3.994 0 0 0-5.809 1.887l-20.212 49.424c-13.159 32.178-58.675 31.993-71.757 0zm16.814-64.568l19.064 46.616 19.064-46.615c10.308-25.2 40.778-35.066 63.892-20.759l42.822 26.507-11.976-48.919c-6.475-26.444 12.38-52.339 39.487-54.349l50.226-3.726-38.444-32.536c-20.782-17.591-20.747-49.621.001-67.18l38.442-32.536-50.225-3.727c-27.151-2.015-45.95-27.948-39.488-54.349l11.978-48.919-42.823 26.507c-23.151 14.327-53.603 4.4-63.892-20.76l-19.064-46.615-19.064 46.617c-10.305 25.198-40.778 35.066-63.891 20.76l-42.823-26.508 11.977 48.918c6.474 26.446-12.381 52.338-39.488 54.35l-50.224 3.726 38.443 32.537c20.782 17.588 20.747 49.619 0 67.178L52.48 322.123l50.226 3.726c27.151 2.014 45.95 27.947 39.487 54.349l-11.977 48.919 42.823-26.507c23.188-14.355 53.622-4.352 63.891 20.758zM256 384c-70.58 0-128-57.421-128-128 0-70.58 57.42-128 128-128 70.579 0 128 57.42 128 128 0 70.579-57.421 128-128 128zm0-208c-44.112 0-80 35.888-80 80s35.888 80 80 80 80-35.888 80-80-35.888-80-80-80z"],"thumbs-down":[512,512,[],"f165","M466.27 225.31c4.674-22.647.864-44.538-8.99-62.99 2.958-23.868-4.021-48.565-17.34-66.99C438.986 39.423 404.117 0 327 0c-7 0-15 .01-22.22.01C201.195.01 168.997 40 128 40h-10.845c-5.64-4.975-13.042-8-21.155-8H32C14.327 32 0 46.327 0 64v240c0 17.673 14.327 32 32 32h64c11.842 0 22.175-6.438 27.708-16h7.052c19.146 16.953 46.013 60.653 68.76 83.4 13.667 13.667 10.153 108.6 71.76 108.6 57.58 0 95.27-31.936 95.27-104.73 0-18.41-3.93-33.73-8.85-46.54h36.48c48.602 0 85.82-41.565 85.82-85.58 0-19.15-4.96-34.99-13.73-49.84zM64 296c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24zm330.18 16.73H290.19c0 37.82 28.36 55.37 28.36 94.54 0 23.75 0 56.73-47.27 56.73-18.91-18.91-9.46-66.18-37.82-94.54C206.9 342.89 167.28 272 138.92 272H128V85.83c53.611 0 100.001-37.82 171.64-37.82h37.82c35.512 0 60.82 17.12 53.12 65.9 15.2 8.16 26.5 36.44 13.94 57.57 21.581 20.384 18.699 51.065 5.21 65.62 9.45 0 22.36 18.91 22.27 37.81-.09 18.91-16.71 37.82-37.82 37.82z"],"thumbs-up":[512,512,[],"f164","M466.27 286.69C475.04 271.84 480 256 480 236.85c0-44.015-37.218-85.58-85.82-85.58H357.7c4.92-12.81 8.85-28.13 8.85-46.54C366.55 31.936 328.86 0 271.28 0c-61.607 0-58.093 94.933-71.76 108.6-22.747 22.747-49.615 66.447-68.76 83.4H32c-17.673 0-32 14.327-32 32v240c0 17.673 14.327 32 32 32h64c14.893 0 27.408-10.174 30.978-23.95 44.509 1.001 75.06 39.94 177.802 39.94 7.22 0 15.22.01 22.22.01 77.117 0 111.986-39.423 112.94-95.33 13.319-18.425 20.299-43.122 17.34-66.99 9.854-18.452 13.664-40.343 8.99-62.99zm-61.75 53.83c12.56 21.13 1.26 49.41-13.94 57.57 7.7 48.78-17.608 65.9-53.12 65.9h-37.82c-71.639 0-118.029-37.82-171.64-37.82V240h10.92c28.36 0 67.98-70.89 94.54-97.46 28.36-28.36 18.91-75.63 37.82-94.54 47.27 0 47.27 32.98 47.27 56.73 0 39.17-28.36 56.72-28.36 94.54h103.99c21.11 0 37.73 18.91 37.82 37.82.09 18.9-12.82 37.81-22.27 37.81 13.489 14.555 16.371 45.236-5.21 65.62zM88 432c0 13.255-10.745 24-24 24s-24-10.745-24-24 10.745-24 24-24 24 10.745 24 24z"],"times-circle":[512,512,[],"f057","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm101.8-262.2L295.6 256l62.2 62.2c4.7 4.7 4.7 12.3 0 17l-22.6 22.6c-4.7 4.7-12.3 4.7-17 0L256 295.6l-62.2 62.2c-4.7 4.7-12.3 4.7-17 0l-22.6-22.6c-4.7-4.7-4.7-12.3 0-17l62.2-62.2-62.2-62.2c-4.7-4.7-4.7-12.3 0-17l22.6-22.6c4.7-4.7 12.3-4.7 17 0l62.2 62.2 62.2-62.2c4.7-4.7 12.3-4.7 17 0l22.6 22.6c4.7 4.7 4.7 12.3 0 17z"],"trash-alt":[448,512,[],"f2ed","M192 188v216c0 6.627-5.373 12-12 12h-24c-6.627 0-12-5.373-12-12V188c0-6.627 5.373-12 12-12h24c6.627 0 12 5.373 12 12zm100-12h-24c-6.627 0-12 5.373-12 12v216c0 6.627 5.373 12 12 12h24c6.627 0 12-5.373 12-12V188c0-6.627-5.373-12-12-12zm132-96c13.255 0 24 10.745 24 24v12c0 6.627-5.373 12-12 12h-20v336c0 26.51-21.49 48-48 48H80c-26.51 0-48-21.49-48-48V128H12c-6.627 0-12-5.373-12-12v-12c0-13.255 10.745-24 24-24h74.411l34.018-56.696A48 48 0 0 1 173.589 0h100.823a48 48 0 0 1 41.16 23.304L349.589 80H424zm-269.611 0h139.223L276.16 50.913A6 6 0 0 0 271.015 48h-94.028a6 6 0 0 0-5.145 2.913L154.389 80zM368 128H80v330a6 6 0 0 0 6 6h276a6 6 0 0 0 6-6V128z"],user:[512,512,[],"f007","M399.326 288.908C422.188 258.886 436 221.085 436 180 436 80.591 355.414 0 256 0 156.591 0 76 80.586 76 180c0 41.073 13.806 78.878 36.674 108.908C50.028 296.336 0 349.651 0 416v28.5C0 481.72 30.28 512 67.5 512h377c37.22 0 67.5-30.28 67.5-67.5V416c0-66.374-50.052-119.667-112.674-127.092zM256 48c72.902 0 132 59.098 132 132s-59.098 132-132 132-132-59.098-132-132S183.098 48 256 48zm208 396.5c0 10.77-8.73 19.5-19.5 19.5h-377c-10.77 0-19.5-8.73-19.5-19.5V416c0-44.183 35.817-80 80-80h38.14c55.486 31.968 124.026 32.087 179.72 0H384c44.183 0 80 35.817 80 80v28.5z"],"user-circle":[512,512,[],"f2bd","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 48c110.532 0 200 89.451 200 200 0 34.48-8.706 66.909-24.04 95.213-13.403-26.393-37.525-47.542-67.384-56.572C378.19 273.809 385.5 249.468 385.5 224c0-71.569-57.919-129.5-129.5-129.5-71.569 0-129.5 57.919-129.5 129.5 0 25.468 7.31 49.809 20.924 70.641-29.821 9.018-53.962 30.142-67.385 56.572C64.706 322.911 56 290.482 56 256c0-110.531 89.451-200 200-200zm-80 168c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm-59.927 174.943c1.519-33.998 29.554-61.097 63.927-61.097h14.171c38.337 20.889 85.337 20.881 123.659 0H332c34.373 0 62.408 27.099 63.927 61.097-77.746 76.114-202.156 76.065-279.854 0z"],"window-close":[512,512,[],"f410","M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm0 394c0 3.3-2.7 6-6 6H54c-3.3 0-6-2.7-6-6V86c0-3.3 2.7-6 6-6h404c3.3 0 6 2.7 6 6v340zM356.5 194.6L295.1 256l61.4 61.4c4.6 4.6 4.6 12.1 0 16.8l-22.3 22.3c-4.6 4.6-12.1 4.6-16.8 0L256 295.1l-61.4 61.4c-4.6 4.6-12.1 4.6-16.8 0l-22.3-22.3c-4.6-4.6-4.6-12.1 0-16.8l61.4-61.4-61.4-61.4c-4.6-4.6-4.6-12.1 0-16.8l22.3-22.3c4.6-4.6 12.1-4.6 16.8 0l61.4 61.4 61.4-61.4c4.6-4.6 12.1-4.6 16.8 0l22.3 22.3c4.7 4.6 4.7 12.1 0 16.8z"],"window-maximize":[512,512,[],"f2d0","M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm0 394c0 3.3-2.7 6-6 6H54c-3.3 0-6-2.7-6-6V192h416v234z"],"window-restore":[512,512,[],"f2d2","M464 0H144c-26.5 0-48 21.5-48 48v48H48c-26.5 0-48 21.5-48 48v320c0 26.5 21.5 48 48 48h320c26.5 0 48-21.5 48-48v-48h48c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm-96 464H48V256h320v208zm96-96h-48V144c0-26.5-21.5-48-48-48H144V48h320v320z"]}),t=z||{};t.___FONT_AWESOME___||(t.___FONT_AWESOME___={}),t.___FONT_AWESOME___.styles||(t.___FONT_AWESOME___.styles={}),t.___FONT_AWESOME___.hooks||(t.___FONT_AWESOME___.hooks={}),t.___FONT_AWESOME___.shims||(t.___FONT_AWESOME___.shims=[]);var s=t.___FONT_AWESOME___,r=Object.assign||function(c){for(var l=1;l<arguments.length;l++){var h=arguments[l];for(var v in h)Object.prototype.hasOwnProperty.call(h,v)&&(c[v]=h[v])}return c};!function(c){try{c()}catch(c){}}(function(){c("far")})}(),function(){"use strict";function c(c){"function"==typeof s.hooks.addPack?s.hooks.addPack(c,m):s.styles[c]=r({},s.styles[c]||{},m)}var l={};try{"undefined"!=typeof window&&(l=window)}catch(c){}var h=(l.navigator||{}).userAgent,v=void 0===h?"":h,z=l,e=(~v.indexOf("MSIE")||v.indexOf("Trident/"),[1,2,3,4,5,6,7,8,9,10]),a=e.concat([11,12,13,14,15,16,17,18,19,20]),m=(["xs","sm","lg","fw","ul","li","border","pull-left","pull-right","spin","pulse","rotate-90","rotate-180","rotate-270","flip-horizontal","flip-vertical","stack","stack-1x","stack-2x","inverse","layers","layers-text","layers-counter"].concat(e.map(function(c){return c+"x"})).concat(a.map(function(c){return"w-"+c})),{"address-book":[448,512,[],"f2b9","M436 160c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20V48c0-26.51-21.49-48-48-48H80C53.49 0 32 21.49 32 48v416c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48v-48h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20zM224 96c53.019 0 96 42.981 96 96s-42.981 96-96 96-96-42.981-96-96 42.981-96 96-96zm128 304c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48v-48.711c0-20.994 13.644-39.553 33.683-45.815l22.954-7.173C173.563 312.413 198.198 320 224 320s50.437-7.587 71.363-21.699l22.954 7.173C338.356 311.736 352 330.295 352 351.289V400z"],"address-card":[512,512,[],"f2bb","M464 64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm-288 64c44.183 0 80 35.817 80 80s-35.817 80-80 80-80-35.817-80-80 35.817-80 80-80zm112 232c0 13.255-10.745 24-24 24H88c-13.255 0-24-10.745-24-24v-29.897a24 24 0 0 1 17.407-23.077l28.938-8.268C129.323 312.549 152.087 320 176 320s46.677-7.451 65.656-21.241l28.938 8.268A23.999 23.999 0 0 1 288 330.103V360zm160-52c0 6.627-5.373 12-12 12H332c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v8zm0-64c0 6.627-5.373 12-12 12H332c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v8zm0-64c0 6.627-5.373 12-12 12H332c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v8z"],adjust:[512,512,[],"f042","M8 256c0 136.966 111.033 248 248 248s248-111.034 248-248S392.966 8 256 8 8 119.033 8 256zm248 184V72c101.705 0 184 82.311 184 184 0 101.705-82.311 184-184 184z"],"align-center":[448,512,[],"f037","M352 44v40c0 8.837-7.163 16-16 16H112c-8.837 0-16-7.163-16-16V44c0-8.837 7.163-16 16-16h224c8.837 0 16 7.163 16 16zM16 228h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm320-200H112c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16h224c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16z"],"align-justify":[448,512,[],"f039","M0 84V44c0-8.837 7.163-16 16-16h416c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16zm16 144h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0-128h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"],"align-left":[448,512,[],"f036","M288 44v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16V44c0-8.837 7.163-16 16-16h256c8.837 0 16 7.163 16 16zM0 172v40c0 8.837 7.163 16 16 16h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16zm16 312h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm256-200H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16z"],"align-right":[448,512,[],"f038","M160 84V44c0-8.837 7.163-16 16-16h256c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H176c-8.837 0-16-7.163-16-16zM16 228h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 256h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm160-128h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H176c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"],ambulance:[640,512,[],"f0f9","M592 0H272c-26.51 0-48 21.49-48 48v48h-44.118a48 48 0 0 0-33.941 14.059l-99.882 99.882A48 48 0 0 0 32 243.882V352h-8c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h40c0 53.019 42.981 96 96 96s96-42.981 96-96h128c0 53.019 42.981 96 96 96s96-42.981 96-96h40c13.255 0 24-10.745 24-24V48c0-26.51-21.49-48-48-48zM160 464c-26.467 0-48-21.533-48-48s21.533-48 48-48 48 21.533 48 48-21.533 48-48 48zm64-208H80v-12.118L179.882 144H224v112zm256 208c-26.467 0-48-21.533-48-48s21.533-48 48-48 48 21.533 48 48-21.533 48-48 48zm32-288v32c0 6.627-5.373 12-12 12h-56v56c0 6.627-5.373 12-12 12h-32c-6.627 0-12-5.373-12-12v-56h-56c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h56v-56c0-6.627 5.373-12 12-12h32c6.627 0 12 5.373 12 12v56h56c6.627 0 12 5.373 12 12z"],"american-sign-language-interpreting":[640,512,[],"f2a3","M290.547 189.039c-20.295-10.149-44.147-11.199-64.739-3.89 42.606 0 71.208 20.475 85.578 50.576 8.576 17.899-5.148 38.071-23.617 38.071 18.429 0 32.211 20.136 23.617 38.071-14.725 30.846-46.123 50.854-80.298 50.854-.557 0-94.471-8.615-94.471-8.615l-66.406 33.347c-9.384 4.693-19.815.379-23.895-7.781L1.86 290.747c-4.167-8.615-1.111-18.897 6.946-23.621l58.072-33.069L108 159.861c6.39-57.245 34.731-109.767 79.743-146.726 11.391-9.448 28.341-7.781 37.51 3.613 9.446 11.394 7.78 28.067-3.612 37.516-12.503 10.559-23.618 22.509-32.509 35.57 21.672-14.729 46.679-24.732 74.186-28.067 14.725-1.945 28.063 8.336 29.73 23.065 1.945 14.728-8.336 28.067-23.062 29.734-16.116 1.945-31.12 7.503-44.178 15.284 26.114-5.713 58.712-3.138 88.079 11.115 13.336 6.669 18.893 22.509 12.224 35.848-6.389 13.06-22.504 18.617-35.564 12.226zm-27.229 69.472c-6.112-12.505-18.338-20.286-32.231-20.286a35.46 35.46 0 0 0-35.565 35.57c0 21.428 17.808 35.57 35.565 35.57 13.893 0 26.119-7.781 32.231-20.286 4.446-9.449 13.614-15.006 23.339-15.284-9.725-.277-18.893-5.835-23.339-15.284zm374.821-37.237c4.168 8.615 1.111 18.897-6.946 23.621l-58.071 33.069L532 352.16c-6.39 57.245-34.731 109.767-79.743 146.726-10.932 9.112-27.799 8.144-37.51-3.613-9.446-11.394-7.78-28.067 3.613-37.516 12.503-10.559 23.617-22.509 32.508-35.57-21.672 14.729-46.679 24.732-74.186 28.067-10.021 2.506-27.552-5.643-29.73-23.065-1.945-14.728 8.336-28.067 23.062-29.734 16.116-1.946 31.12-7.503 44.178-15.284-26.114 5.713-58.712 3.138-88.079-11.115-13.336-6.669-18.893-22.509-12.224-35.848 6.389-13.061 22.505-18.619 35.565-12.227 20.295 10.149 44.147 11.199 64.739 3.89-42.606 0-71.208-20.475-85.578-50.576-8.576-17.899 5.148-38.071 23.617-38.071-18.429 0-32.211-20.136-23.617-38.071 14.033-29.396 44.039-50.887 81.966-50.854l92.803 8.615 66.406-33.347c9.408-4.704 19.828-.354 23.894 7.781l44.455 88.926zm-229.227-18.618c-13.893 0-26.119 7.781-32.231 20.286-4.446 9.449-13.614 15.006-23.339 15.284 9.725.278 18.893 5.836 23.339 15.284 6.112 12.505 18.338 20.286 32.231 20.286a35.46 35.46 0 0 0 35.565-35.57c0-21.429-17.808-35.57-35.565-35.57z"],anchor:[576,512,[],"f13d","M12.971 352h32.394C67.172 454.735 181.944 512 288 512c106.229 0 220.853-57.38 242.635-160h32.394c10.691 0 16.045-12.926 8.485-20.485l-67.029-67.029c-4.686-4.686-12.284-4.686-16.971 0l-67.029 67.029c-7.56 7.56-2.206 20.485 8.485 20.485h35.146c-20.29 54.317-84.963 86.588-144.117 94.015V256h52c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-52v-5.47c37.281-13.178 63.995-48.725 64-90.518C384.005 43.772 341.605.738 289.37.01 235.723-.739 192 42.525 192 96c0 41.798 26.716 77.35 64 90.53V192h-52c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h52v190.015c-58.936-7.399-123.82-39.679-144.117-94.015h35.146c10.691 0 16.045-12.926 8.485-20.485l-67.029-67.029c-4.686-4.686-12.284-4.686-16.971 0L4.485 331.515C-3.074 339.074 2.28 352 12.971 352zM288 64c17.645 0 32 14.355 32 32s-14.355 32-32 32-32-14.355-32-32 14.355-32 32-32z"],"angle-double-down":[320,512,[],"f103","M143 256.3L7 120.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0L313 86.3c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.4 9.5-24.6 9.5-34 .1zm34 192l136-136c9.4-9.4 9.4-24.6 0-33.9l-22.6-22.6c-9.4-9.4-24.6-9.4-33.9 0L160 352.1l-96.4-96.4c-9.4-9.4-24.6-9.4-33.9 0L7 278.3c-9.4 9.4-9.4 24.6 0 33.9l136 136c9.4 9.5 24.6 9.5 34 .1z"],"angle-double-left":[448,512,[],"f100","M223.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L319.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L393.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34zm-192 34l136 136c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9L127.9 256l96.4-96.4c9.4-9.4 9.4-24.6 0-33.9L201.7 103c-9.4-9.4-24.6-9.4-33.9 0l-136 136c-9.5 9.4-9.5 24.6-.1 34z"],"angle-double-right":[448,512,[],"f101","M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34zm192-34l-136-136c-9.4-9.4-24.6-9.4-33.9 0l-22.6 22.6c-9.4 9.4-9.4 24.6 0 33.9l96.4 96.4-96.4 96.4c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l136-136c9.4-9.2 9.4-24.4 0-33.8z"],"angle-double-up":[320,512,[],"f102","M177 255.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 351.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 425.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1zm-34-192L7 199.7c-9.4 9.4-9.4 24.6 0 33.9l22.6 22.6c9.4 9.4 24.6 9.4 33.9 0l96.4-96.4 96.4 96.4c9.4 9.4 24.6 9.4 33.9 0l22.6-22.6c9.4-9.4 9.4-24.6 0-33.9l-136-136c-9.2-9.4-24.4-9.4-33.8 0z"],"angle-down":[320,512,[],"f107","M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z"],"angle-left":[256,512,[],"f104","M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z"],"angle-right":[256,512,[],"f105","M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z"],"angle-up":[320,512,[],"f106","M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z"],archive:[512,512,[],"f187","M488 128H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h464c13.255 0 24 10.745 24 24v48c0 13.255-10.745 24-24 24zm-8 328V184c0-13.255-10.745-24-24-24H56c-13.255 0-24 10.745-24 24v272c0 13.255 10.745 24 24 24h400c13.255 0 24-10.745 24-24zM308 256H204c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h104c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12z"],"arrow-alt-circle-down":[512,512,[],"f358","M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zM212 140v116h-70.9c-10.7 0-16.1 13-8.5 20.5l114.9 114.3c4.7 4.7 12.2 4.7 16.9 0l114.9-114.3c7.6-7.6 2.2-20.5-8.5-20.5H300V140c0-6.6-5.4-12-12-12h-64c-6.6 0-12 5.4-12 12z"],"arrow-alt-circle-left":[512,512,[],"f359","M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zm116-292H256v-70.9c0-10.7-13-16.1-20.5-8.5L121.2 247.5c-4.7 4.7-4.7 12.2 0 16.9l114.3 114.9c7.6 7.6 20.5 2.2 20.5-8.5V300h116c6.6 0 12-5.4 12-12v-64c0-6.6-5.4-12-12-12z"],"arrow-alt-circle-right":[512,512,[],"f35a","M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zM140 300h116v70.9c0 10.7 13 16.1 20.5 8.5l114.3-114.9c4.7-4.7 4.7-12.2 0-16.9l-114.3-115c-7.6-7.6-20.5-2.2-20.5 8.5V212H140c-6.6 0-12 5.4-12 12v64c0 6.6 5.4 12 12 12z"],"arrow-alt-circle-up":[512,512,[],"f35b","M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm292 116V256h70.9c10.7 0 16.1-13 8.5-20.5L264.5 121.2c-4.7-4.7-12.2-4.7-16.9 0l-115 114.3c-7.6 7.6-2.2 20.5 8.5 20.5H212v116c0 6.6 5.4 12 12 12h64c6.6 0 12-5.4 12-12z"],"arrow-circle-down":[512,512,[],"f0ab","M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zm-143.6-28.9L288 302.6V120c0-13.3-10.7-24-24-24h-16c-13.3 0-24 10.7-24 24v182.6l-72.4-75.5c-9.3-9.7-24.8-9.9-34.3-.4l-10.9 11c-9.4 9.4-9.4 24.6 0 33.9L239 404.3c9.4 9.4 24.6 9.4 33.9 0l132.7-132.7c9.4-9.4 9.4-24.6 0-33.9l-10.9-11c-9.5-9.5-25-9.3-34.3.4z"],"arrow-circle-left":[512,512,[],"f0a8","M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zm28.9-143.6L209.4 288H392c13.3 0 24-10.7 24-24v-16c0-13.3-10.7-24-24-24H209.4l75.5-72.4c9.7-9.3 9.9-24.8.4-34.3l-11-10.9c-9.4-9.4-24.6-9.4-33.9 0L107.7 239c-9.4 9.4-9.4 24.6 0 33.9l132.7 132.7c9.4 9.4 24.6 9.4 33.9 0l11-10.9c9.5-9.5 9.3-25-.4-34.3z"],"arrow-circle-right":[512,512,[],"f0a9","M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm-28.9 143.6l75.5 72.4H120c-13.3 0-24 10.7-24 24v16c0 13.3 10.7 24 24 24h182.6l-75.5 72.4c-9.7 9.3-9.9 24.8-.4 34.3l11 10.9c9.4 9.4 24.6 9.4 33.9 0L404.3 273c9.4-9.4 9.4-24.6 0-33.9L271.6 106.3c-9.4-9.4-24.6-9.4-33.9 0l-11 10.9c-9.5 9.6-9.3 25.1.4 34.4z"],"arrow-circle-up":[512,512,[],"f0aa","M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm143.6 28.9l72.4-75.5V392c0 13.3 10.7 24 24 24h16c13.3 0 24-10.7 24-24V209.4l72.4 75.5c9.3 9.7 24.8 9.9 34.3.4l10.9-11c9.4-9.4 9.4-24.6 0-33.9L273 107.7c-9.4-9.4-24.6-9.4-33.9 0L106.3 240.4c-9.4 9.4-9.4 24.6 0 33.9l10.9 11c9.6 9.5 25.1 9.3 34.4-.4z"],"arrow-down":[448,512,[],"f063","M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"],"arrow-left":[448,512,[],"f060","M257.5 445.1l-22.2 22.2c-9.4 9.4-24.6 9.4-33.9 0L7 273c-9.4-9.4-9.4-24.6 0-33.9L201.4 44.7c9.4-9.4 24.6-9.4 33.9 0l22.2 22.2c9.5 9.5 9.3 25-.4 34.3L136.6 216H424c13.3 0 24 10.7 24 24v32c0 13.3-10.7 24-24 24H136.6l120.5 114.8c9.8 9.3 10 24.8.4 34.3z"],"arrow-right":[448,512,[],"f061","M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"],"arrow-up":[448,512,[],"f062","M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"],"arrows-alt":[512,512,[],"f0b2","M352.201 425.775l-79.196 79.196c-9.373 9.373-24.568 9.373-33.941 0l-79.196-79.196c-15.119-15.119-4.411-40.971 16.971-40.97h51.162L228 284H127.196v51.162c0 21.382-25.851 32.09-40.971 16.971L7.029 272.937c-9.373-9.373-9.373-24.569 0-33.941L86.225 159.8c15.119-15.119 40.971-4.411 40.971 16.971V228H228V127.196h-51.23c-21.382 0-32.09-25.851-16.971-40.971l79.196-79.196c9.373-9.373 24.568-9.373 33.941 0l79.196 79.196c15.119 15.119 4.411 40.971-16.971 40.971h-51.162V228h100.804v-51.162c0-21.382 25.851-32.09 40.97-16.971l79.196 79.196c9.373 9.373 9.373 24.569 0 33.941L425.773 352.2c-15.119 15.119-40.971 4.411-40.97-16.971V284H284v100.804h51.23c21.382 0 32.09 25.851 16.971 40.971z"],"arrows-alt-h":[512,512,[],"f337","M377.941 169.941V216H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.568 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296h243.882v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.568 0-33.941l-86.059-86.059c-15.119-15.12-40.971-4.412-40.971 16.97z"],"arrows-alt-v":[256,512,[],"f338","M214.059 377.941H168V134.059h46.059c21.382 0 32.09-25.851 16.971-40.971L144.971 7.029c-9.373-9.373-24.568-9.373-33.941 0L24.971 93.088c-15.119 15.119-4.411 40.971 16.971 40.971H88v243.882H41.941c-21.382 0-32.09 25.851-16.971 40.971l86.059 86.059c9.373 9.373 24.568 9.373 33.941 0l86.059-86.059c15.12-15.119 4.412-40.971-16.97-40.971z"],"assistive-listening-systems":[512,512,[],"f2a2","M216 260c0 15.464-12.536 28-28 28s-28-12.536-28-28c0-44.112 35.888-80 80-80s80 35.888 80 80c0 15.464-12.536 28-28 28s-28-12.536-28-28c0-13.234-10.767-24-24-24s-24 10.766-24 24zm24-176c-97.047 0-176 78.953-176 176 0 15.464 12.536 28 28 28s28-12.536 28-28c0-66.168 53.832-120 120-120s120 53.832 120 120c0 75.164-71.009 70.311-71.997 143.622L288 404c0 28.673-23.327 52-52 52-15.464 0-28 12.536-28 28s12.536 28 28 28c59.475 0 107.876-48.328 108-107.774.595-34.428 72-48.24 72-144.226 0-97.047-78.953-176-176-176zm-80 236c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zM32 448c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm480-187.993c0-1.518-.012-3.025-.045-4.531C510.076 140.525 436.157 38.47 327.994 1.511c-14.633-4.998-30.549 2.809-35.55 17.442-5 14.633 2.81 30.549 17.442 35.55 85.906 29.354 144.61 110.513 146.077 201.953l.003.188c.026 1.118.033 2.236.033 3.363 0 15.464 12.536 28 28 28s28.001-12.536 28.001-28zM152.971 439.029l-80-80L39.03 392.97l80 80 33.941-33.941z"],asterisk:[512,512,[],"f069","M478.21 334.093L336 256l142.21-78.093c11.795-6.477 15.961-21.384 9.232-33.037l-19.48-33.741c-6.728-11.653-21.72-15.499-33.227-8.523L296 186.718l3.475-162.204C299.763 11.061 288.937 0 275.48 0h-38.96c-13.456 0-24.283 11.061-23.994 24.514L216 186.718 77.265 102.607c-11.506-6.976-26.499-3.13-33.227 8.523l-19.48 33.741c-6.728 11.653-2.562 26.56 9.233 33.037L176 256 33.79 334.093c-11.795 6.477-15.961 21.384-9.232 33.037l19.48 33.741c6.728 11.653 21.721 15.499 33.227 8.523L216 325.282l-3.475 162.204C212.237 500.939 223.064 512 236.52 512h38.961c13.456 0 24.283-11.061 23.995-24.514L296 325.282l138.735 84.111c11.506 6.976 26.499 3.13 33.227-8.523l19.48-33.741c6.728-11.653 2.563-26.559-9.232-33.036z"],at:[512,512,[],"f1fa","M256 8C118.941 8 8 118.919 8 256c0 137.059 110.919 248 248 248 48.154 0 95.342-14.14 135.408-40.223 12.005-7.815 14.625-24.288 5.552-35.372l-10.177-12.433c-7.671-9.371-21.179-11.667-31.373-5.129C325.92 429.757 291.314 440 256 440c-101.458 0-184-82.542-184-184S154.542 72 256 72c100.139 0 184 57.619 184 160 0 38.786-21.093 79.742-58.17 83.693-17.349-.454-16.91-12.857-13.476-30.024l23.433-121.11C394.653 149.75 383.308 136 368.225 136h-44.981a13.518 13.518 0 0 0-13.432 11.993l-.01.092c-14.697-17.901-40.448-21.775-59.971-21.775-74.58 0-137.831 62.234-137.831 151.46 0 65.303 36.785 105.87 96 105.87 26.984 0 57.369-15.637 74.991-38.333 9.522 34.104 40.613 34.103 70.71 34.103C462.609 379.41 504 307.798 504 232 504 95.653 394.023 8 256 8zm-21.68 304.43c-22.249 0-36.07-15.623-36.07-40.771 0-44.993 30.779-72.729 58.63-72.729 22.292 0 35.601 15.241 35.601 40.77 0 45.061-33.875 72.73-58.161 72.73z"],"audio-description":[512,512,[],"f29e","M162.925 238.709l8.822 30.655h-25.606l9.041-30.652c1.277-4.421 2.651-9.994 3.872-15.245 1.22 5.251 2.594 10.823 3.871 15.242zm166.474-32.099h-14.523v98.781h14.523c29.776 0 46.175-17.678 46.175-49.776 0-32.239-17.49-49.005-46.175-49.005zM512 112v288c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48zM245.459 336.139l-57.097-168A12.001 12.001 0 0 0 177 160h-35.894a12.001 12.001 0 0 0-11.362 8.139l-57.097 168C70.003 343.922 75.789 352 84.009 352h29.133a12 12 0 0 0 11.535-8.693l8.574-29.906h51.367l8.793 29.977A12 12 0 0 0 204.926 352h29.172c8.22 0 14.006-8.078 11.361-15.861zm184.701-80.525c0-58.977-37.919-95.614-98.96-95.614h-57.366c-6.627 0-12 5.373-12 12v168c0 6.627 5.373 12 12 12H331.2c61.041 0 98.96-36.933 98.96-96.386z"],backward:[512,512,[],"f04a","M11.5 280.6l192 160c20.6 17.2 52.5 2.8 52.5-24.6V96c0-27.4-31.9-41.8-52.5-24.6l-192 160c-15.3 12.8-15.3 36.4 0 49.2zm256 0l192 160c20.6 17.2 52.5 2.8 52.5-24.6V96c0-27.4-31.9-41.8-52.5-24.6l-192 160c-15.3 12.8-15.3 36.4 0 49.2z"],"balance-scale":[640,512,[],"f24e","M352 448h168c13.255 0 24 10.745 24 24v16c0 13.255-10.745 24-24 24H120c-13.255 0-24-10.745-24-24v-16c0-13.255 10.745-24 24-24h168V153.324C264.469 143.04 246.836 121.778 241.603 96H120c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h135.999C270.594 12.57 293.828 0 320 0s49.406 12.57 64.001 32H520c13.255 0 24 10.745 24 24v16c0 13.255-10.745 24-24 24H398.397c-5.233 25.778-22.866 47.04-46.397 57.324V448zm287.981-112c.001-16.182 1.342-8.726-85.048-181.506-17.647-35.294-68.186-35.358-85.865 0C381.94 328.75 384.019 320.331 384.019 336H384c0 44.183 57.308 80 128 80s128-35.817 128-80h-.019zM512 176l72 144H440l72-144zM255.981 336c.001-16.182 1.342-8.726-85.048-181.506-17.647-35.294-68.186-35.358-85.865 0C-2.06 328.75.019 320.331.019 336H0c0 44.183 57.308 80 128 80s128-35.817 128-80h-.019zM128 176l72 144H56l72-144z"],ban:[512,512,[],"f05e","M256 8C119.034 8 8 119.033 8 256s111.034 248 248 248 248-111.034 248-248S392.967 8 256 8zm130.108 117.892c65.448 65.448 70 165.481 20.677 235.637L150.47 105.216c70.204-49.356 170.226-44.735 235.638 20.676zM125.892 386.108c-65.448-65.448-70-165.481-20.677-235.637L361.53 406.784c-70.203 49.356-170.226 44.736-235.638-20.676z"],barcode:[512,512,[],"f02a","M0 448V64h18v384H0zm26.857-.273V64H36v383.727h-9.143zm27.143 0V64h8.857v383.727H54zm44.857 0V64h8.857v383.727h-8.857zm36 0V64h17.714v383.727h-17.714zm44.857 0V64h8.857v383.727h-8.857zm18 0V64h8.857v383.727h-8.857zm18 0V64h8.857v383.727h-8.857zm35.715 0V64h18v383.727h-18zm44.857 0V64h18v383.727h-18zm35.999 0V64h18.001v383.727h-18.001zm36.001 0V64h18.001v383.727h-18.001zm26.857 0V64h18v383.727h-18zm45.143 0V64h26.857v383.727h-26.857zm35.714 0V64h9.143v383.727H476zm18 .273V64h18v384h-18z"],bars:[448,512,[],"f0c9","M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"],bath:[512,512,[],"f2cd","M488 256H80V112c0-17.645 14.355-32 32-32 11.351 0 21.332 5.945 27.015 14.88-16.492 25.207-14.687 59.576 6.838 83.035-4.176 4.713-4.021 11.916.491 16.428l11.314 11.314c4.686 4.686 12.284 4.686 16.971 0l95.03-95.029c4.686-4.686 4.686-12.284 0-16.971l-11.314-11.314c-4.512-4.512-11.715-4.666-16.428-.491-17.949-16.469-42.294-21.429-64.178-15.365C163.281 45.667 139.212 32 112 32c-44.112 0-80 35.888-80 80v144h-8c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h8v32c0 28.43 12.362 53.969 32 71.547V456c0 13.255 10.745 24 24 24h16c13.255 0 24-10.745 24-24v-8h256v8c0 13.255 10.745 24 24 24h16c13.255 0 24-10.745 24-24v-32.453c19.638-17.578 32-43.117 32-71.547v-32h8c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24z"],"battery-empty":[640,512,[],"f244","M544 160v64h32v64h-32v64H64V160h480m16-64H48c-26.51 0-48 21.49-48 48v224c0 26.51 21.49 48 48 48h512c26.51 0 48-21.49 48-48v-16h8c13.255 0 24-10.745 24-24V184c0-13.255-10.745-24-24-24h-8v-16c0-26.51-21.49-48-48-48z"],"battery-full":[640,512,[],"f240","M544 160v64h32v64h-32v64H64V160h480m16-64H48c-26.51 0-48 21.49-48 48v224c0 26.51 21.49 48 48 48h512c26.51 0 48-21.49 48-48v-16h8c13.255 0 24-10.745 24-24V184c0-13.255-10.745-24-24-24h-8v-16c0-26.51-21.49-48-48-48zm-48 96H96v128h416V192z"],"battery-half":[640,512,[],"f242","M544 160v64h32v64h-32v64H64V160h480m16-64H48c-26.51 0-48 21.49-48 48v224c0 26.51 21.49 48 48 48h512c26.51 0 48-21.49 48-48v-16h8c13.255 0 24-10.745 24-24V184c0-13.255-10.745-24-24-24h-8v-16c0-26.51-21.49-48-48-48zm-240 96H96v128h224V192z"],"battery-quarter":[640,512,[],"f243","M544 160v64h32v64h-32v64H64V160h480m16-64H48c-26.51 0-48 21.49-48 48v224c0 26.51 21.49 48 48 48h512c26.51 0 48-21.49 48-48v-16h8c13.255 0 24-10.745 24-24V184c0-13.255-10.745-24-24-24h-8v-16c0-26.51-21.49-48-48-48zm-336 96H96v128h128V192z"],"battery-three-quarters":[640,512,[],"f241","M544 160v64h32v64h-32v64H64V160h480m16-64H48c-26.51 0-48 21.49-48 48v224c0 26.51 21.49 48 48 48h512c26.51 0 48-21.49 48-48v-16h8c13.255 0 24-10.745 24-24V184c0-13.255-10.745-24-24-24h-8v-16c0-26.51-21.49-48-48-48zm-144 96H96v128h320V192z"],bed:[576,512,[],"f236","M552 288c13.255 0 24 10.745 24 24v136h-96v-64H96v64H0V88c0-13.255 10.745-24 24-24h48c13.255 0 24 10.745 24 24v200h456zM192 96c-44.183 0-80 35.817-80 80s35.817 80 80 80 80-35.817 80-80-35.817-80-80-80zm384 128c0-53.019-42.981-96-96-96H312c-13.255 0-24 10.745-24 24v104h288v-32z"],beer:[448,512,[],"f0fc","M368 96h-48V56c0-13.255-10.745-24-24-24H24C10.745 32 0 42.745 0 56v400c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24v-42.11l80.606-35.977C429.396 365.063 448 336.388 448 304.86V176c0-44.112-35.888-80-80-80zm16 208.86a16.018 16.018 0 0 1-9.479 14.611L320 343.805V160h48c8.822 0 16 7.178 16 16v128.86zM208 384c-8.836 0-16-7.164-16-16V144c0-8.836 7.164-16 16-16s16 7.164 16 16v224c0 8.836-7.164 16-16 16zm-96 0c-8.836 0-16-7.164-16-16V144c0-8.836 7.164-16 16-16s16 7.164 16 16v224c0 8.836-7.164 16-16 16z"],bell:[448,512,[],"f0f3","M433.884 366.059C411.634 343.809 384 316.118 384 208c0-79.394-57.831-145.269-133.663-157.83A31.845 31.845 0 0 0 256 32c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 6.75 2.095 13.008 5.663 18.17C121.831 62.731 64 128.606 64 208c0 108.118-27.643 135.809-49.893 158.059C-16.042 396.208 5.325 448 48.048 448H160c0 35.346 28.654 64 64 64s64-28.654 64-64h111.943c42.638 0 64.151-51.731 33.941-81.941zM224 472a8 8 0 0 1 0 16c-22.056 0-40-17.944-40-40h16c0 13.234 10.766 24 24 24z"],"bell-slash":[576,512,[],"f1f6","M78.107 366.059C47.958 396.208 69.325 448 112.048 448H224c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64h32.685L127.848 221.379c-2.198 97.078-28.439 123.378-49.741 144.68zM264 448c0 13.234 10.766 24 24 24a8 8 0 0 1 0 16c-22.056 0-40-17.944-40-40h16zm305.896 43.733l-10.762 12.086c-8.915 10.012-24.333 10.967-34.437 2.133L8.256 54.393C-1.848 45.558-2.811 30.28 6.104 20.267L16.865 8.181C25.781-1.831 41.199-2.786 51.303 6.049l113.81 99.512c24.017-28.778 57.946-48.996 96.55-55.39A31.85 31.85 0 0 1 256 32c0-17.673 14.327-32 32-32s32 14.327 32 32c0 6.75-2.095 13.008-5.663 18.17C390.169 62.731 448 128.606 448 208c0 108.118 27.634 135.809 49.884 158.059 12.149 12.149 15.923 27.776 13.33 42.121l56.53 49.427c10.104 8.835 11.067 24.113 2.152 34.126z"],bicycle:[640,512,[],"f206","M512.509 192.001c-16.373-.064-32.03 2.955-46.436 8.495l-77.68-125.153A24 24 0 0 0 368.001 64h-64c-8.837 0-16 7.163-16 16v16c0 8.837 7.163 16 16 16h50.649l14.896 24H256.002v-16c0-8.837-7.163-16-16-16h-87.459c-13.441 0-24.777 10.999-24.536 24.437.232 13.044 10.876 23.563 23.995 23.563h48.726l-29.417 47.52c-13.433-4.83-27.904-7.483-42.992-7.52C58.094 191.83.412 249.012.002 319.236-.413 390.279 57.055 448 128.002 448c59.642 0 109.758-40.793 123.967-96h52.033a24 24 0 0 0 20.406-11.367L410.37 201.77l14.938 24.067c-25.455 23.448-41.385 57.081-41.307 94.437.145 68.833 57.899 127.051 126.729 127.719 70.606.685 128.181-55.803 129.255-125.996 1.086-70.941-56.526-129.72-127.476-129.996zM186.75 265.772c9.727 10.529 16.673 23.661 19.642 38.228h-43.306l23.664-38.228zM128.002 400c-44.112 0-80-35.888-80-80s35.888-80 80-80c5.869 0 11.586.653 17.099 1.859l-45.505 73.509C89.715 331.327 101.213 352 120.002 352h81.3c-12.37 28.225-40.562 48-73.3 48zm162.63-96h-35.624c-3.96-31.756-19.556-59.894-42.383-80.026L237.371 184h127.547l-74.286 120zm217.057 95.886c-41.036-2.165-74.049-35.692-75.627-76.755-.812-21.121 6.633-40.518 19.335-55.263l44.433 71.586c4.66 7.508 14.524 9.816 22.032 5.156l13.594-8.437c7.508-4.66 9.817-14.524 5.156-22.032l-44.468-71.643a79.901 79.901 0 0 1 19.858-2.497c44.112 0 80 35.888 80 80-.001 45.54-38.252 82.316-84.313 79.885z"],binoculars:[512,512,[],"f1e5","M192 104H96V56c0-13.255 10.745-24 24-24h48c13.255 0 24 10.745 24 24v48zm224-48c0-13.255-10.745-24-24-24h-48c-13.255 0-24 10.745-24 24v48h96V56zM0 456c0 13.255 10.745 24 24 24h120c13.255 0 24-10.745 24-24v-16H0v16zm88-328c-13.255 0-24 10.745-24 24C64 256 0 272 0 416h168V312c0-13.255 10.745-24 24-24V128H88zm256 328c0 13.255 10.745 24 24 24h120c13.255 0 24-10.745 24-24v-16H344v16zM216 128v160h80V128h-80zm128 288h168c0-144-64-160-64-264 0-13.255-10.745-24-24-24H320v160c13.255 0 24 10.745 24 24v104z"],"birthday-cake":[448,512,[],"f1fd","M448 384c-28.02 0-31.26-32-74.5-32-43.43 0-46.825 32-74.75 32-27.695 0-31.454-32-74.75-32-42.842 0-47.218 32-74.5 32-28.148 0-31.202-32-74.75-32-43.547 0-46.653 32-74.75 32v-80c0-26.5 21.5-48 48-48h16V112h64v144h64V112h64v144h64V112h64v144h16c26.5 0 48 21.5 48 48v80zm0 128H0v-96c43.356 0 46.767-32 74.75-32 27.951 0 31.253 32 74.75 32 42.843 0 47.217-32 74.5-32 28.148 0 31.201 32 74.75 32 43.357 0 46.767-32 74.75-32 27.488 0 31.252 32 74.5 32v96zM96 96c-17.75 0-32-14.25-32-32 0-31 32-23 32-64 12 0 32 29.5 32 56s-14.25 40-32 40zm128 0c-17.75 0-32-14.25-32-32 0-31 32-23 32-64 12 0 32 29.5 32 56s-14.25 40-32 40zm128 0c-17.75 0-32-14.25-32-32 0-31 32-23 32-64 12 0 32 29.5 32 56s-14.25 40-32 40z"],blind:[384,512,[],"f29d","M380.15 510.837a8 8 0 0 1-10.989-2.687l-125.33-206.427a31.923 31.923 0 0 0 12.958-9.485l126.048 207.608a8 8 0 0 1-2.687 10.991zM142.803 314.338l-32.54 89.485 36.12 88.285c6.693 16.36 25.377 24.192 41.733 17.501 16.357-6.692 24.193-25.376 17.501-41.734l-62.814-153.537zM96 88c24.301 0 44-19.699 44-44S120.301 0 96 0 52 19.699 52 44s19.699 44 44 44zm154.837 169.128l-120-152c-4.733-5.995-11.75-9.108-18.837-9.112V96H80v.026c-7.146.003-14.217 3.161-18.944 9.24L0 183.766v95.694c0 13.455 11.011 24.791 24.464 24.536C37.505 303.748 48 293.1 48 280v-79.766l16-20.571v140.698L9.927 469.055c-6.04 16.609 2.528 34.969 19.138 41.009 16.602 6.039 34.968-2.524 41.009-19.138L136 309.638V202.441l-31.406-39.816a4 4 0 1 1 6.269-4.971l102.3 129.217c9.145 11.584 24.368 11.339 33.708 3.965 10.41-8.216 12.159-23.334 3.966-33.708z"],bold:[384,512,[],"f032","M304.793 243.891c33.639-18.537 53.657-54.16 53.657-95.693 0-48.236-26.25-87.626-68.626-104.179C265.138 34.01 240.849 32 209.661 32H24c-8.837 0-16 7.163-16 16v33.049c0 8.837 7.163 16 16 16h33.113v318.53H24c-8.837 0-16 7.163-16 16V464c0 8.837 7.163 16 16 16h195.69c24.203 0 44.834-1.289 66.866-7.584C337.52 457.193 376 410.647 376 350.014c0-52.168-26.573-91.684-71.207-106.123zM142.217 100.809h67.444c16.294 0 27.536 2.019 37.525 6.717 15.828 8.479 24.906 26.502 24.906 49.446 0 35.029-20.32 56.79-53.029 56.79h-76.846V100.809zm112.642 305.475c-10.14 4.056-22.677 4.907-31.409 4.907h-81.233V281.943h84.367c39.645 0 63.057 25.38 63.057 63.057.001 28.425-13.66 52.483-34.782 61.284z"],bolt:[320,512,[],"f0e7","M295.973 160H180.572L215.19 30.184C219.25 14.956 207.756 0 192 0H56C43.971 0 33.8 8.905 32.211 20.828l-31.996 240C-1.704 275.217 9.504 288 24.004 288h118.701L96.646 482.466C93.05 497.649 104.659 512 119.992 512c8.35 0 16.376-4.374 20.778-11.978l175.973-303.997c9.244-15.967-2.288-36.025-20.77-36.025z"],bomb:[512,512,[],"f1e2","M440.5 88.5l-52 52L415 167c9.4 9.4 9.4 24.6 0 33.9l-17.4 17.4c11.8 26.1 18.4 55.1 18.4 85.6 0 114.9-93.1 208-208 208S0 418.9 0 304 93.1 96 208 96c30.5 0 59.5 6.6 85.6 18.4L311 97c9.4-9.4 24.6-9.4 33.9 0l26.5 26.5 52-52 17.1 17zM500 60h-24c-6.6 0-12 5.4-12 12s5.4 12 12 12h24c6.6 0 12-5.4 12-12s-5.4-12-12-12zM440 0c-6.6 0-12 5.4-12 12v24c0 6.6 5.4 12 12 12s12-5.4 12-12V12c0-6.6-5.4-12-12-12zm33.9 55l17-17c4.7-4.7 4.7-12.3 0-17-4.7-4.7-12.3-4.7-17 0l-17 17c-4.7 4.7-4.7 12.3 0 17 4.8 4.7 12.4 4.7 17 0zm-67.8 0c4.7 4.7 12.3 4.7 17 0 4.7-4.7 4.7-12.3 0-17l-17-17c-4.7-4.7-12.3-4.7-17 0-4.7 4.7-4.7 12.3 0 17l17 17zm67.8 34c-4.7-4.7-12.3-4.7-17 0-4.7 4.7-4.7 12.3 0 17l17 17c4.7 4.7 12.3 4.7 17 0 4.7-4.7 4.7-12.3 0-17l-17-17zM112 272c0-35.3 28.7-64 64-64 8.8 0 16-7.2 16-16s-7.2-16-16-16c-52.9 0-96 43.1-96 96 0 8.8 7.2 16 16 16s16-7.2 16-16z"],book:[448,512,[],"f02d","M448 360V24c0-13.3-10.7-24-24-24H96C43 0 0 43 0 96v320c0 53 43 96 96 96h328c13.3 0 24-10.7 24-24v-16c0-7.5-3.5-14.3-8.9-18.7-4.2-15.4-4.2-59.3 0-74.7 5.4-4.3 8.9-11.1 8.9-18.6zM128 134c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm0 64c0-3.3 2.7-6 6-6h212c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H134c-3.3 0-6-2.7-6-6v-20zm253.4 250H96c-17.7 0-32-14.3-32-32 0-17.6 14.4-32 32-32h285.4c-1.9 17.1-1.9 46.9 0 64z"],bookmark:[384,512,[],"f02e","M0 512V48C0 21.49 21.49 0 48 0h288c26.51 0 48 21.49 48 48v464L192 400 0 512z"],braille:[640,512,[],"f2a1","M128 256c0 35.346-28.654 64-64 64S0 291.346 0 256s28.654-64 64-64 64 28.654 64 64zM64 384c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0-352C28.654 32 0 60.654 0 96s28.654 64 64 64 64-28.654 64-64-28.654-64-64-64zm160 192c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0 160c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0-352c-35.346 0-64 28.654-64 64s28.654 64 64 64 64-28.654 64-64-28.654-64-64-64zm224 192c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0 160c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0-352c-35.346 0-64 28.654-64 64s28.654 64 64 64 64-28.654 64-64-28.654-64-64-64zm160 192c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0 160c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm0-320c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32z"],briefcase:[512,512,[],"f0b1","M320 288h192v144c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V288h192v20c0 6.627 5.373 12 12 12h104c6.627 0 12-5.373 12-12v-20zm192-112v80H0v-80c0-26.51 21.49-48 48-48h80V80c0-26.51 21.49-48 48-48h160c26.51 0 48 21.49 48 48v48h80c26.51 0 48 21.49 48 48zM320 96H192v32h128V96z"],bug:[512,512,[],"f188","M511.988 288.9c-.478 17.43-15.217 31.1-32.653 31.1H424v16c0 21.864-4.882 42.584-13.6 61.145l60.228 60.228c12.496 12.497 12.496 32.758 0 45.255-12.498 12.497-32.759 12.496-45.256 0l-54.736-54.736C345.886 467.965 314.351 480 280 480V236c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v244c-34.351 0-65.886-12.035-90.636-32.108l-54.736 54.736c-12.498 12.497-32.759 12.496-45.256 0-12.496-12.497-12.496-32.758 0-45.255l60.228-60.228C92.882 378.584 88 357.864 88 336v-16H32.666C15.23 320 .491 306.33.013 288.9-.484 270.816 14.028 256 32 256h56v-58.745l-46.628-46.628c-12.496-12.497-12.496-32.758 0-45.255 12.498-12.497 32.758-12.497 45.256 0L141.255 160h229.489l54.627-54.627c12.498-12.497 32.758-12.497 45.256 0 12.496 12.497 12.496 32.758 0 45.255L424 197.255V256h56c17.972 0 32.484 14.816 31.988 32.9zM257 0c-61.856 0-112 50.144-112 112h224C369 50.144 318.856 0 257 0z"],building:[448,512,[],"f1ad","M436 480h-20V24c0-13.255-10.745-24-24-24H56C42.745 0 32 10.745 32 24v456H12c-6.627 0-12 5.373-12 12v20h448v-20c0-6.627-5.373-12-12-12zM128 76c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12V76zm0 96c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12v-40zm52 148h-40c-6.627 0-12-5.373-12-12v-40c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12zm76 160h-64v-84c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v84zm64-172c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12v-40c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40zm0-96c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12v-40c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40zm0-96c0 6.627-5.373 12-12 12h-40c-6.627 0-12-5.373-12-12V76c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v40z"],bullhorn:[576,512,[],"f0a1","M576 224c0-20.896-13.36-38.666-32-45.258V64c0-35.346-28.654-64-64-64-64.985 56-142.031 128-272 128H48c-26.51 0-48 21.49-48 48v96c0 26.51 21.49 48 48 48h43.263c-18.742 64.65 2.479 116.379 18.814 167.44 1.702 5.32 5.203 9.893 9.922 12.88 20.78 13.155 68.355 15.657 93.773 5.151 16.046-6.633 19.96-27.423 7.522-39.537-18.508-18.026-30.136-36.91-19.795-60.858a12.278 12.278 0 0 0-1.045-11.673c-16.309-24.679-3.581-62.107 28.517-72.752C346.403 327.887 418.591 395.081 480 448c35.346 0 64-28.654 64-64V269.258c18.64-6.592 32-24.362 32-45.258zm-96 139.855c-54.609-44.979-125.033-92.94-224-104.982v-69.747c98.967-12.042 169.391-60.002 224-104.982v279.711z"],bullseye:[512,512,[],"f140","M256 72c101.689 0 184 82.295 184 184 0 101.689-82.295 184-184 184-101.689 0-184-82.295-184-184 0-101.689 82.295-184 184-184m0-64C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 184c35.29 0 64 28.71 64 64s-28.71 64-64 64-64-28.71-64-64 28.71-64 64-64m0-64c-70.692 0-128 57.308-128 128s57.308 128 128 128 128-57.308 128-128-57.308-128-128-128z"],bus:[512,512,[],"f207","M512 152v80c0 13.255-10.745 24-24 24h-8v168c0 13.255-10.745 24-24 24h-8v40c0 13.255-10.745 24-24 24h-48c-13.255 0-24-10.745-24-24v-40H160v40c0 13.255-10.745 24-24 24H88c-13.255 0-24-10.745-24-24v-40h-8c-13.255 0-24-10.745-24-24V256h-8c-13.255 0-24-10.745-24-24v-80c0-13.255 10.745-24 24-24h8V80C32 35.817 132.288 0 256 0s224 35.817 224 80v48h8c13.255 0 24 10.745 24 24zM112 320c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zm288 0c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zm32-56V120c0-13.255-10.745-24-24-24H104c-13.255 0-24 10.745-24 24v144c0 13.255 10.745 24 24 24h304c13.255 0 24-10.745 24-24z"],calculator:[448,512,[],"f1ec","M0 464V48C0 21.49 21.49 0 48 0h352c26.51 0 48 21.49 48 48v416c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48zm384-284V76c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v104c0 6.627 5.373 12 12 12h296c6.627 0 12-5.373 12-12zM128 308v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm256 128V268c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v168c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-256 0v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm128-128v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm0 128v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z"],calendar:[448,512,[],"f133","M12 192h424c6.6 0 12 5.4 12 12v260c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V204c0-6.6 5.4-12 12-12zm436-44v-36c0-26.5-21.5-48-48-48h-48V12c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v52H160V12c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v52H48C21.5 64 0 85.5 0 112v36c0 6.6 5.4 12 12 12h424c6.6 0 12-5.4 12-12z"],"calendar-alt":[448,512,[],"f073","M436 160H12c-6.6 0-12-5.4-12-12v-36c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48v36c0 6.6-5.4 12-12 12zM12 192h424c6.6 0 12 5.4 12 12v260c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V204c0-6.6 5.4-12 12-12zm116 204c0-6.6-5.4-12-12-12H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40zm0-128c0-6.6-5.4-12-12-12H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40zm128 128c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40zm0-128c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40zm128 128c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40zm0-128c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-40z"],"calendar-check":[448,512,[],"f274","M436 160H12c-6.627 0-12-5.373-12-12v-36c0-26.51 21.49-48 48-48h48V12c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v52h128V12c0-6.627 5.373-12 12-12h40c6.627 0 12 5.373 12 12v52h48c26.51 0 48 21.49 48 48v36c0 6.627-5.373 12-12 12zM12 192h424c6.627 0 12 5.373 12 12v260c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V204c0-6.627 5.373-12 12-12zm333.296 95.947l-28.169-28.398c-4.667-4.705-12.265-4.736-16.97-.068L194.12 364.665l-45.98-46.352c-4.667-4.705-12.266-4.736-16.971-.068l-28.397 28.17c-4.705 4.667-4.736 12.265-.068 16.97l82.601 83.269c4.667 4.705 12.265 4.736 16.97.068l142.953-141.805c4.705-4.667 4.736-12.265.068-16.97z"],"calendar-minus":[448,512,[],"f272","M436 160H12c-6.6 0-12-5.4-12-12v-36c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48v36c0 6.6-5.4 12-12 12zM12 192h424c6.6 0 12 5.4 12 12v260c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V204c0-6.6 5.4-12 12-12zm304 192c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H132c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h184z"],"calendar-plus":[448,512,[],"f271","M436 160H12c-6.6 0-12-5.4-12-12v-36c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48v36c0 6.6-5.4 12-12 12zM12 192h424c6.6 0 12 5.4 12 12v260c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V204c0-6.6 5.4-12 12-12zm316 140c0-6.6-5.4-12-12-12h-60v-60c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v60h-60c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h60v60c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-60h60c6.6 0 12-5.4 12-12v-40z"],"calendar-times":[448,512,[],"f273","M436 160H12c-6.6 0-12-5.4-12-12v-36c0-26.5 21.5-48 48-48h48V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h128V12c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h48c26.5 0 48 21.5 48 48v36c0 6.6-5.4 12-12 12zM12 192h424c6.6 0 12 5.4 12 12v260c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V204c0-6.6 5.4-12 12-12zm257.3 160l48.1-48.1c4.7-4.7 4.7-12.3 0-17l-28.3-28.3c-4.7-4.7-12.3-4.7-17 0L224 306.7l-48.1-48.1c-4.7-4.7-12.3-4.7-17 0l-28.3 28.3c-4.7 4.7-4.7 12.3 0 17l48.1 48.1-48.1 48.1c-4.7 4.7-4.7 12.3 0 17l28.3 28.3c4.7 4.7 12.3 4.7 17 0l48.1-48.1 48.1 48.1c4.7 4.7 12.3 4.7 17 0l28.3-28.3c4.7-4.7 4.7-12.3 0-17L269.3 352z"],camera:[512,512,[],"f030","M512 144v288c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V144c0-26.5 21.5-48 48-48h88l12.3-32.9c7-18.7 24.9-31.1 44.9-31.1h125.5c20 0 37.9 12.4 44.9 31.1L376 96h88c26.5 0 48 21.5 48 48zM376 288c0-66.2-53.8-120-120-120s-120 53.8-120 120 53.8 120 120 120 120-53.8 120-120zm-32 0c0 48.5-39.5 88-88 88s-88-39.5-88-88 39.5-88 88-88 88 39.5 88 88z"],"camera-retro":[512,512,[],"f083","M48 32C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48H48zm0 32h106c3.3 0 6 2.7 6 6v20c0 3.3-2.7 6-6 6H38c-3.3 0-6-2.7-6-6V80c0-8.8 7.2-16 16-16zm426 96H38c-3.3 0-6-2.7-6-6v-36c0-3.3 2.7-6 6-6h138l30.2-45.3c1.1-1.7 3-2.7 5-2.7H464c8.8 0 16 7.2 16 16v74c0 3.3-2.7 6-6 6zM256 424c-66.2 0-120-53.8-120-120s53.8-120 120-120 120 53.8 120 120-53.8 120-120 120zm0-208c-48.5 0-88 39.5-88 88s39.5 88 88 88 88-39.5 88-88-39.5-88-88-88zm-48 104c-8.8 0-16-7.2-16-16 0-35.3 28.7-64 64-64 8.8 0 16 7.2 16 16s-7.2 16-16 16c-17.6 0-32 14.4-32 32 0 8.8-7.2 16-16 16z"],car:[512,512,[],"f1b9","M499.991 168h-54.815l-7.854-20.944c-9.192-24.513-25.425-45.351-46.942-60.263S343.651 64 317.472 64H194.528c-26.18 0-51.391 7.882-72.908 22.793-21.518 14.912-37.75 35.75-46.942 60.263L66.824 168H12.009c-8.191 0-13.974 8.024-11.384 15.795l8 24A12 12 0 0 0 20.009 216h28.815l-.052.14C29.222 227.093 16 247.997 16 272v48c0 16.225 6.049 31.029 16 42.309V424c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24v-40h256v40c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24v-61.691c9.951-11.281 16-26.085 16-42.309v-48c0-24.003-13.222-44.907-32.772-55.86l-.052-.14h28.815a12 12 0 0 0 11.384-8.205l8-24c2.59-7.771-3.193-15.795-11.384-15.795zm-365.388 1.528C143.918 144.689 168 128 194.528 128h122.944c26.528 0 50.61 16.689 59.925 41.528L391.824 208H120.176l14.427-38.472zM88 328c-17.673 0-32-14.327-32-32 0-17.673 14.327-32 32-32s48 30.327 48 48-30.327 16-48 16zm336 0c-17.673 0-48 1.673-48-16 0-17.673 30.327-48 48-48s32 14.327 32 32c0 17.673-14.327 32-32 32z"],"caret-down":[320,512,[],"f0d7","M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"],"caret-left":[192,512,[],"f0d9","M192 127.338v257.324c0 17.818-21.543 26.741-34.142 14.142L29.196 270.142c-7.81-7.81-7.81-20.474 0-28.284l128.662-128.662c12.599-12.6 34.142-3.676 34.142 14.142z"],"caret-right":[192,512,[],"f0da","M0 384.662V127.338c0-17.818 21.543-26.741 34.142-14.142l128.662 128.662c7.81 7.81 7.81 20.474 0 28.284L34.142 398.804C21.543 411.404 0 402.48 0 384.662z"],"caret-square-down":[448,512,[],"f150","M448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zM92.5 220.5l123 123c4.7 4.7 12.3 4.7 17 0l123-123c7.6-7.6 2.2-20.5-8.5-20.5H101c-10.7 0-16.1 12.9-8.5 20.5z"],"caret-square-left":[448,512,[],"f191","M400 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zM259.515 124.485l-123.03 123.03c-4.686 4.686-4.686 12.284 0 16.971l123.029 123.029c7.56 7.56 20.485 2.206 20.485-8.485V132.971c.001-10.691-12.925-16.045-20.484-8.486z"],"caret-square-right":[448,512,[],"f152","M48 32h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48zm140.485 355.515l123.029-123.029c4.686-4.686 4.686-12.284 0-16.971l-123.029-123.03c-7.56-7.56-20.485-2.206-20.485 8.485v246.059c0 10.691 12.926 16.045 20.485 8.486z"],"caret-square-up":[448,512,[],"f151","M0 432V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48zm355.515-140.485l-123.03-123.03c-4.686-4.686-12.284-4.686-16.971 0L92.485 291.515c-7.56 7.56-2.206 20.485 8.485 20.485h246.059c10.691 0 16.045-12.926 8.486-20.485z"],"caret-up":[320,512,[],"f0d8","M288.662 352H31.338c-17.818 0-26.741-21.543-14.142-34.142l128.662-128.662c7.81-7.81 20.474-7.81 28.284 0l128.662 128.662c12.6 12.599 3.676 34.142-14.142 34.142z"],"cart-arrow-down":[576,512,[],"f218","M504.717 320H211.572l6.545 32h268.418c15.401 0 26.816 14.301 23.403 29.319l-5.517 24.276C523.112 414.668 536 433.828 536 456c0 31.202-25.519 56.444-56.824 55.994-29.823-.429-54.35-24.631-55.155-54.447-.44-16.287 6.085-31.049 16.803-41.548H231.176C241.553 426.165 248 440.326 248 456c0 31.813-26.528 57.431-58.67 55.938-28.54-1.325-51.751-24.385-53.251-52.917-1.158-22.034 10.436-41.455 28.051-51.586L93.883 64H24C10.745 64 0 53.255 0 40V24C0 10.745 10.745 0 24 0h102.529c11.401 0 21.228 8.021 23.513 19.19L159.208 64H551.99c15.401 0 26.816 14.301 23.403 29.319l-47.273 208C525.637 312.246 515.923 320 504.717 320zM403.029 192H360v-60c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v60h-43.029c-10.691 0-16.045 12.926-8.485 20.485l67.029 67.029c4.686 4.686 12.284 4.686 16.971 0l67.029-67.029c7.559-7.559 2.205-20.485-8.486-20.485z"],"cart-plus":[576,512,[],"f217","M504.717 320H211.572l6.545 32h268.418c15.401 0 26.816 14.301 23.403 29.319l-5.517 24.276C523.112 414.668 536 433.828 536 456c0 31.202-25.519 56.444-56.824 55.994-29.823-.429-54.35-24.631-55.155-54.447-.44-16.287 6.085-31.049 16.803-41.548H231.176C241.553 426.165 248 440.326 248 456c0 31.813-26.528 57.431-58.67 55.938-28.54-1.325-51.751-24.385-53.251-52.917-1.158-22.034 10.436-41.455 28.051-51.586L93.883 64H24C10.745 64 0 53.255 0 40V24C0 10.745 10.745 0 24 0h102.529c11.401 0 21.228 8.021 23.513 19.19L159.208 64H551.99c15.401 0 26.816 14.301 23.403 29.319l-47.273 208C525.637 312.246 515.923 320 504.717 320zM408 168h-48v-40c0-8.837-7.163-16-16-16h-16c-8.837 0-16 7.163-16 16v40h-48c-8.837 0-16 7.163-16 16v16c0 8.837 7.163 16 16 16h48v40c0 8.837 7.163 16 16 16h16c8.837 0 16-7.163 16-16v-40h48c8.837 0 16-7.163 16-16v-16c0-8.837-7.163-16-16-16z"],certificate:[512,512,[],"f0a3","M458.622 255.92l45.985-45.005c13.708-12.977 7.316-36.039-10.664-40.339l-62.65-15.99 17.661-62.015c4.991-17.838-11.829-34.663-29.661-29.671l-61.994 17.667-15.984-62.671C337.085.197 313.765-6.276 300.99 7.228L256 53.57 211.011 7.229c-12.63-13.351-36.047-7.234-40.325 10.668l-15.984 62.671-61.995-17.667C74.87 57.907 58.056 74.738 63.046 92.572l17.661 62.015-62.65 15.99C.069 174.878-6.31 197.944 7.392 210.915l45.985 45.005-45.985 45.004c-13.708 12.977-7.316 36.039 10.664 40.339l62.65 15.99-17.661 62.015c-4.991 17.838 11.829 34.663 29.661 29.671l61.994-17.667 15.984 62.671c4.439 18.575 27.696 24.018 40.325 10.668L256 458.61l44.989 46.001c12.5 13.488 35.987 7.486 40.325-10.668l15.984-62.671 61.994 17.667c17.836 4.994 34.651-11.837 29.661-29.671l-17.661-62.015 62.65-15.99c17.987-4.302 24.366-27.367 10.664-40.339l-45.984-45.004z"],"chart-area":[512,512,[],"f1fe","M500 384c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v308h436zM372.7 159.5L288 216l-85.3-113.7c-5.1-6.8-15.5-6.3-19.9 1L96 248v104h384l-89.9-187.8c-3.2-6.5-11.4-8.7-17.4-4.7z"],"chart-bar":[512,512,[],"f080","M500 384c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v308h436zm-308-44v-72c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v72c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0V204c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v136c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm-96 0V140c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v200c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0V108c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v232c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"],"chart-line":[512,512,[],"f201","M500 384c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v308h436zM456 96H344c-21.4 0-32.1 25.9-17 41l32.9 32.9-72 72.9-55.6-55.6c-4.7-4.7-12.2-4.7-16.9 0L96.4 305c-4.7 4.6-4.8 12.2-.2 16.9l28.5 29.4c4.7 4.8 12.4 4.9 17.1.1l82.1-82.1 55.5 55.5c4.7 4.7 12.3 4.7 17 0l109.2-109.2L439 249c15.1 15.1 41 4.4 41-17V120c0-13.3-10.7-24-24-24z"],"chart-pie":[576,512,[],"f200","M288 12.3V240h227.7c6.9 0 12.3-5.8 12-12.7-6.4-122.4-104.5-220.6-227-227-6.9-.3-12.7 5.1-12.7 12zM552.7 288c6.9 0 12.3 5.8 12 12.7-2.8 53.2-23.2 105.6-61.2 147.8-4.6 5.1-12.6 5.4-17.5.5L325 288h227.7zM401 433c4.8 4.8 4.7 12.8-.4 17.3-42.6 38.4-99 61.7-160.8 61.7C107.6 511.9-.2 403.8 0 271.5.2 143.4 100.8 38.9 227.3 32.3c6.9-.4 12.7 5.1 12.7 12V272l161 161z"],check:[512,512,[],"f00c","M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"],"check-circle":[512,512,[],"f058","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"],"check-square":[448,512,[],"f14a","M400 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zm-204.686-98.059l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.248-16.379-6.249-22.628 0L184 302.745l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.25 16.379 6.25 22.628.001z"],"chevron-circle-down":[512,512,[],"f13a","M504 256c0 137-111 248-248 248S8 393 8 256 119 8 256 8s248 111 248 248zM273 369.9l135.5-135.5c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L256 285.1 154.4 183.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L239 369.9c9.4 9.4 24.6 9.4 34 0z"],"chevron-circle-left":[512,512,[],"f137","M256 504C119 504 8 393 8 256S119 8 256 8s248 111 248 248-111 248-248 248zM142.1 273l135.5 135.5c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L226.9 256l101.6-101.6c9.4-9.4 9.4-24.6 0-33.9l-17-17c-9.4-9.4-24.6-9.4-33.9 0L142.1 239c-9.4 9.4-9.4 24.6 0 34z"],"chevron-circle-right":[512,512,[],"f138","M256 8c137 0 248 111 248 248S393 504 256 504 8 393 8 256 119 8 256 8zm113.9 231L234.4 103.5c-9.4-9.4-24.6-9.4-33.9 0l-17 17c-9.4 9.4-9.4 24.6 0 33.9L285.1 256 183.5 357.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L369.9 273c9.4-9.4 9.4-24.6 0-34z"],"chevron-circle-up":[512,512,[],"f139","M8 256C8 119 119 8 256 8s248 111 248 248-111 248-248 248S8 393 8 256zm231-113.9L103.5 277.6c-9.4 9.4-9.4 24.6 0 33.9l17 17c9.4 9.4 24.6 9.4 33.9 0L256 226.9l101.6 101.6c9.4 9.4 24.6 9.4 33.9 0l17-17c9.4-9.4 9.4-24.6 0-33.9L273 142.1c-9.4-9.4-24.6-9.4-34 0z"],"chevron-down":[448,512,[],"f078","M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"],"chevron-left":[320,512,[],"f053","M34.52 239.03L228.87 44.69c9.37-9.37 24.57-9.37 33.94 0l22.67 22.67c9.36 9.36 9.37 24.52.04 33.9L131.49 256l154.02 154.75c9.34 9.38 9.32 24.54-.04 33.9l-22.67 22.67c-9.37 9.37-24.57 9.37-33.94 0L34.52 272.97c-9.37-9.37-9.37-24.57 0-33.94z"],"chevron-right":[320,512,[],"f054","M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"],"chevron-up":[448,512,[],"f077","M240.971 130.524l194.343 194.343c9.373 9.373 9.373 24.569 0 33.941l-22.667 22.667c-9.357 9.357-24.522 9.375-33.901.04L224 227.495 69.255 381.516c-9.379 9.335-24.544 9.317-33.901-.04l-22.667-22.667c-9.373-9.373-9.373-24.569 0-33.941L207.03 130.525c9.372-9.373 24.568-9.373 33.941-.001z"],child:[384,512,[],"f1ae","M120 72c0-39.765 32.235-72 72-72s72 32.235 72 72c0 39.764-32.235 72-72 72s-72-32.236-72-72zm254.627 1.373c-12.496-12.497-32.758-12.497-45.254 0L242.745 160H141.254L54.627 73.373c-12.496-12.497-32.758-12.497-45.254 0-12.497 12.497-12.497 32.758 0 45.255L104 213.254V480c0 17.673 14.327 32 32 32h16c17.673 0 32-14.327 32-32V368h16v112c0 17.673 14.327 32 32 32h16c17.673 0 32-14.327 32-32V213.254l94.627-94.627c12.497-12.497 12.497-32.757 0-45.254z"],circle:[512,512,[],"f111","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"],"circle-notch":[512,512,[],"f1ce","M288 39.056v16.659c0 10.804 7.281 20.159 17.686 23.066C383.204 100.434 440 171.518 440 256c0 101.689-82.295 184-184 184-101.689 0-184-82.295-184-184 0-84.47 56.786-155.564 134.312-177.219C216.719 75.874 224 66.517 224 55.712V39.064c0-15.709-14.834-27.153-30.046-23.234C86.603 43.482 7.394 141.206 8.003 257.332c.72 137.052 111.477 246.956 248.531 246.667C393.255 503.711 504 392.788 504 256c0-115.633-79.14-212.779-186.211-240.236C302.678 11.889 288 23.456 288 39.056z"],clipboard:[384,512,[],"f328","M384 112v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h80c0-35.29 28.71-64 64-64s64 28.71 64 64h80c26.51 0 48 21.49 48 48zM192 40c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24m96 114v-20a6 6 0 0 0-6-6H102a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6h180a6 6 0 0 0 6-6z"],clock:[512,512,[],"f017","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm57.1 350.1L224.9 294c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v137.7l63.5 46.2c5.4 3.9 6.5 11.4 2.6 16.8l-28.2 38.8c-3.9 5.3-11.4 6.5-16.8 2.6z"],clone:[512,512,[],"f24d","M464 0c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48H176c-26.51 0-48-21.49-48-48V48c0-26.51 21.49-48 48-48h288M176 416c-44.112 0-80-35.888-80-80V128H48c-26.51 0-48 21.49-48 48v288c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48v-48H176z"],"closed-captioning":[512,512,[],"f20a","M464 64H48C21.5 64 0 85.5 0 112v288c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zM218.1 287.7c2.8-2.5 7.1-2.1 9.2.9l19.5 27.7c1.7 2.4 1.5 5.6-.5 7.7-53.6 56.8-172.8 32.1-172.8-67.9 0-97.3 121.7-119.5 172.5-70.1 2.1 2 2.5 3.2 1 5.7l-17.5 30.5c-1.9 3.1-6.2 4-9.1 1.7-40.8-32-94.6-14.9-94.6 31.2.1 48 51.1 70.5 92.3 32.6zm190.4 0c2.8-2.5 7.1-2.1 9.2.9l19.5 27.7c1.7 2.4 1.5 5.6-.5 7.7-53.5 56.9-172.7 32.1-172.7-67.9 0-97.3 121.7-119.5 172.5-70.1 2.1 2 2.5 3.2 1 5.7L420 222.2c-1.9 3.1-6.2 4-9.1 1.7-40.8-32-94.6-14.9-94.6 31.2 0 48 51 70.5 92.2 32.6z"],cloud:[640,512,[],"f0c2","M537.585 226.56C541.725 215.836 544 204.184 544 192c0-53.019-42.981-96-96-96-19.729 0-38.065 5.954-53.316 16.159C367.042 64.248 315.288 32 256 32c-88.366 0-160 71.634-160 160 0 2.728.07 5.439.204 8.133C40.171 219.845 0 273.227 0 336c0 79.529 64.471 144 144 144h368c70.692 0 128-57.308 128-128 0-61.93-43.983-113.586-102.415-125.44z"],"cloud-download-alt":[640,512,[],"f381","M640 352c0 70.692-57.308 128-128 128H144C64.471 480 0 415.529 0 336c0-62.773 40.171-116.155 96.204-135.867A163.68 163.68 0 0 1 96 192c0-88.366 71.634-160 160-160 59.288 0 111.042 32.248 138.684 80.159C409.935 101.954 428.271 96 448 96c53.019 0 96 42.981 96 96 0 12.184-2.275 23.836-6.415 34.56C596.017 238.414 640 290.07 640 352zm-246.627-64H328V176c0-8.837-7.164-16-16-16h-48c-8.836 0-16 7.163-16 16v112h-65.373c-14.254 0-21.393 17.234-11.314 27.314l105.373 105.373c6.248 6.248 16.379 6.248 22.627 0l105.373-105.373c10.08-10.08 2.941-27.314-11.313-27.314z"],"cloud-upload-alt":[640,512,[],"f382","M640 352c0 70.692-57.308 128-128 128H144C64.471 480 0 415.529 0 336c0-62.773 40.171-116.155 96.204-135.867A163.68 163.68 0 0 1 96 192c0-88.366 71.634-160 160-160 59.288 0 111.042 32.248 138.684 80.159C409.935 101.954 428.271 96 448 96c53.019 0 96 42.981 96 96 0 12.184-2.275 23.836-6.415 34.56C596.017 238.414 640 290.07 640 352zm-235.314-91.314L299.314 155.314c-6.248-6.248-16.379-6.248-22.627 0L171.314 260.686c-10.08 10.08-2.941 27.314 11.313 27.314H248v112c0 8.837 7.164 16 16 16h48c8.836 0 16-7.163 16-16V288h65.373c14.254 0 21.393-17.234 11.313-27.314z"],code:[640,512,[],"f121","M278.9 511.5l-61-17.7c-6.4-1.8-10-8.5-8.2-14.9L346.2 8.7c1.8-6.4 8.5-10 14.9-8.2l61 17.7c6.4 1.8 10 8.5 8.2 14.9L293.8 503.3c-1.9 6.4-8.5 10.1-14.9 8.2zm-114-112.2l43.5-46.4c4.6-4.9 4.3-12.7-.8-17.2L117 256l90.6-79.7c5.1-4.5 5.5-12.3.8-17.2l-43.5-46.4c-4.5-4.8-12.1-5.1-17-.5L3.8 247.2c-5.1 4.7-5.1 12.8 0 17.5l144.1 135.1c4.9 4.6 12.5 4.4 17-.5zm327.2.6l144.1-135.1c5.1-4.7 5.1-12.8 0-17.5L492.1 112.1c-4.8-4.5-12.4-4.3-17 .5L431.6 159c-4.6 4.9-4.3 12.7.8 17.2L523 256l-90.6 79.7c-5.1 4.5-5.5 12.3-.8 17.2l43.5 46.4c4.5 4.9 12.1 5.1 17 .6z"],"code-branch":[384,512,[],"f126","M384 144c0-44.2-35.8-80-80-80s-80 35.8-80 80c0 36.4 24.3 67.1 57.5 76.8-.6 16.1-4.2 28.5-11 36.9-15.4 19.2-49.3 22.4-85.2 25.7-28.2 2.6-57.4 5.4-81.3 16.9v-144c32.5-10.2 56-40.5 56-76.3 0-44.2-35.8-80-80-80S0 35.8 0 80c0 35.8 23.5 66.1 56 76.3v199.3C23.5 365.9 0 396.2 0 432c0 44.2 35.8 80 80 80s80-35.8 80-80c0-34-21.2-63.1-51.2-74.6 3.1-5.2 7.8-9.8 14.9-13.4 16.2-8.2 40.4-10.4 66.1-12.8 42.2-3.9 90-8.4 118.2-43.4 14-17.4 21.1-39.8 21.6-67.9 31.6-10.8 54.4-40.7 54.4-75.9zM80 64c8.8 0 16 7.2 16 16s-7.2 16-16 16-16-7.2-16-16 7.2-16 16-16zm0 384c-8.8 0-16-7.2-16-16s7.2-16 16-16 16 7.2 16 16-7.2 16-16 16zm224-320c8.8 0 16 7.2 16 16s-7.2 16-16 16-16-7.2-16-16 7.2-16 16-16z"],coffee:[640,512,[],"f0f4","M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z"],cog:[512,512,[],"f013","M444.788 291.1l42.616 24.599c4.867 2.809 7.126 8.618 5.459 13.985-11.07 35.642-29.97 67.842-54.689 94.586a12.016 12.016 0 0 1-14.832 2.254l-42.584-24.595a191.577 191.577 0 0 1-60.759 35.13v49.182a12.01 12.01 0 0 1-9.377 11.718c-34.956 7.85-72.499 8.256-109.219.007-5.49-1.233-9.403-6.096-9.403-11.723v-49.184a191.555 191.555 0 0 1-60.759-35.13l-42.584 24.595a12.016 12.016 0 0 1-14.832-2.254c-24.718-26.744-43.619-58.944-54.689-94.586-1.667-5.366.592-11.175 5.459-13.985L67.212 291.1a193.48 193.48 0 0 1 0-70.199l-42.616-24.599c-4.867-2.809-7.126-8.618-5.459-13.985 11.07-35.642 29.97-67.842 54.689-94.586a12.016 12.016 0 0 1 14.832-2.254l42.584 24.595a191.577 191.577 0 0 1 60.759-35.13V25.759a12.01 12.01 0 0 1 9.377-11.718c34.956-7.85 72.499-8.256 109.219-.007 5.49 1.233 9.403 6.096 9.403 11.723v49.184a191.555 191.555 0 0 1 60.759 35.13l42.584-24.595a12.016 12.016 0 0 1 14.832 2.254c24.718 26.744 43.619 58.944 54.689 94.586 1.667 5.366-.592 11.175-5.459 13.985L444.788 220.9a193.485 193.485 0 0 1 0 70.2zM336 256c0-44.112-35.888-80-80-80s-80 35.888-80 80 35.888 80 80 80 80-35.888 80-80z"],cogs:[640,512,[],"f085","M512.1 191l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0L552 6.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zm-10.5-58.8c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.7-82.4 14.3-52.8 52.8zM386.3 286.1l33.7 16.8c10.1 5.8 14.5 18.1 10.5 29.1-8.9 24.2-26.4 46.4-42.6 65.8-7.4 8.9-20.2 11.1-30.3 5.3l-29.1-16.8c-16 13.7-34.6 24.6-54.9 31.7v33.6c0 11.6-8.3 21.6-19.7 23.6-24.6 4.2-50.4 4.4-75.9 0-11.5-2-20-11.9-20-23.6V418c-20.3-7.2-38.9-18-54.9-31.7L74 403c-10 5.8-22.9 3.6-30.3-5.3-16.2-19.4-33.3-41.6-42.2-65.7-4-10.9.4-23.2 10.5-29.1l33.3-16.8c-3.9-20.9-3.9-42.4 0-63.4L12 205.8c-10.1-5.8-14.6-18.1-10.5-29 8.9-24.2 26-46.4 42.2-65.8 7.4-8.9 20.2-11.1 30.3-5.3l29.1 16.8c16-13.7 34.6-24.6 54.9-31.7V57.1c0-11.5 8.2-21.5 19.6-23.5 24.6-4.2 50.5-4.4 76-.1 11.5 2 20 11.9 20 23.6v33.6c20.3 7.2 38.9 18 54.9 31.7l29.1-16.8c10-5.8 22.9-3.6 30.3 5.3 16.2 19.4 33.2 41.6 42.1 65.8 4 10.9.1 23.2-10 29.1l-33.7 16.8c3.9 21 3.9 42.5 0 63.5zm-117.6 21.1c59.2-77-28.7-164.9-105.7-105.7-59.2 77 28.7 164.9 105.7 105.7zm243.4 182.7l-8.2 14.3c-3 5.3-9.4 7.5-15.1 5.4-11.8-4.4-22.6-10.7-32.1-18.6-4.6-3.8-5.8-10.5-2.8-15.7l8.2-14.3c-6.9-8-12.3-17.3-15.9-27.4h-16.5c-6 0-11.2-4.3-12.2-10.3-2-12-2.1-24.6 0-37.1 1-6 6.2-10.4 12.2-10.4h16.5c3.6-10.1 9-19.4 15.9-27.4l-8.2-14.3c-3-5.2-1.9-11.9 2.8-15.7 9.5-7.9 20.4-14.2 32.1-18.6 5.7-2.1 12.1.1 15.1 5.4l8.2 14.3c10.5-1.9 21.2-1.9 31.7 0l8.2-14.3c3-5.3 9.4-7.5 15.1-5.4 11.8 4.4 22.6 10.7 32.1 18.6 4.6 3.8 5.8 10.5 2.8 15.7l-8.2 14.3c6.9 8 12.3 17.3 15.9 27.4h16.5c6 0 11.2 4.3 12.2 10.3 2 12 2.1 24.6 0 37.1-1 6-6.2 10.4-12.2 10.4h-16.5c-3.6 10.1-9 19.4-15.9 27.4l8.2 14.3c3 5.2 1.9 11.9-2.8 15.7-9.5 7.9-20.4 14.2-32.1 18.6-5.7 2.1-12.1-.1-15.1-5.4l-8.2-14.3c-10.4 1.9-21.2 1.9-31.7 0zM501.6 431c38.5 29.6 82.4-14.3 52.8-52.8-38.5-29.6-82.4 14.3-52.8 52.8z"],columns:[512,512,[],"f0db","M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64V160h160v256zm224 0H288V160h160v256z"],comment:[576,512,[],"f075","M576 240c0 115-129 208-288 208-48.3 0-93.9-8.6-133.9-23.8-40.3 31.2-89.8 50.3-142.4 55.7-5.2.6-10.2-2.8-11.5-7.7-1.3-5 2.7-8.1 6.6-11.8 19.3-18.4 42.7-32.8 51.9-94.6C21.9 330.9 0 287.3 0 240 0 125.1 129 32 288 32s288 93.1 288 208z"],"comment-alt":[576,512,[],"f27a","M576 240c0 115-129 208-288 208-48.3 0-93.9-8.6-133.9-23.8-40.3 31.2-89.8 50.3-142.4 55.7-5.2.6-10.2-2.8-11.5-7.7-1.3-5 2.7-8.1 6.6-11.8 19.3-18.4 42.7-32.8 51.9-94.6C21.9 330.9 0 287.3 0 240 0 125.1 129 32 288 32s288 93.1 288 208zm-416-48c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48zm128 0c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48zm128 0c-26.5 0-48 21.5-48 48s21.5 48 48 48 48-21.5 48-48-21.5-48-48-48z"],comments:[576,512,[],"f086","M224 358.857c-37.599 0-73.027-6.763-104.143-18.7-31.375 24.549-69.869 39.508-110.764 43.796a8.632 8.632 0 0 1-.89.047c-3.736 0-7.111-2.498-8.017-6.061-.98-3.961 2.088-6.399 5.126-9.305 15.017-14.439 33.222-25.79 40.342-74.297C17.015 266.886 0 232.622 0 195.429 0 105.16 100.297 32 224 32s224 73.159 224 163.429c-.001 90.332-100.297 163.428-224 163.428zm347.067 107.174c-13.944-13.127-30.849-23.446-37.46-67.543 68.808-64.568 52.171-156.935-37.674-207.065.031 1.334.066 2.667.066 4.006 0 122.493-129.583 216.394-284.252 211.222 38.121 30.961 93.989 50.492 156.252 50.492 34.914 0 67.811-6.148 96.704-17 29.134 22.317 64.878 35.916 102.853 39.814 3.786.395 7.363-1.973 8.27-5.467.911-3.601-1.938-5.817-4.759-8.459z"],compass:[512,512,[],"f14e","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM307.446 120.844l-102.642 97.779a23.997 23.997 0 0 0-6.772 11.729l-33.359 137.779c-5.68 23.459 22.777 39.318 39.88 23.024l102.64-97.779a23.99 23.99 0 0 0 6.772-11.729l33.359-137.779c5.618-23.198-22.591-39.493-39.878-23.024zM256 224c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32z"],compress:[448,512,[],"f066","M436 192H312c-13.3 0-24-10.7-24-24V44c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v84h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-276-24V44c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v84H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24zm0 300V344c0-13.3-10.7-24-24-24H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm192 0v-84h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12H312c-13.3 0-24 10.7-24 24v124c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12z"],copy:[448,512,[],"f0c5","M320 448v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h72v296c0 30.879 25.121 56 56 56h168zm0-344V0H152c-13.255 0-24 10.745-24 24v368c0 13.255 10.745 24 24 24h272c13.255 0 24-10.745 24-24V128H344c-13.2 0-24-10.8-24-24zm120.971-31.029L375.029 7.029A24 24 0 0 0 358.059 0H352v96h96v-6.059a24 24 0 0 0-7.029-16.97z"],copyright:[512,512,[],"f1f9","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm117.134 346.753c-1.592 1.867-39.776 45.731-109.851 45.731-84.692 0-144.484-63.26-144.484-145.567 0-81.303 62.004-143.401 143.762-143.401 66.957 0 101.965 37.315 103.422 38.904a12 12 0 0 1 1.238 14.623l-22.38 34.655c-4.049 6.267-12.774 7.351-18.234 2.295-.233-.214-26.529-23.88-61.88-23.88-46.116 0-73.916 33.575-73.916 76.082 0 39.602 25.514 79.692 74.277 79.692 38.697 0 65.28-28.338 65.544-28.625 5.132-5.565 14.059-5.033 18.508 1.053l24.547 33.572a12.001 12.001 0 0 1-.553 14.866z"],"credit-card":[576,512,[],"f09d","M0 432c0 26.5 21.5 48 48 48h480c26.5 0 48-21.5 48-48V256H0v176zm192-68c0-6.6 5.4-12 12-12h136c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H204c-6.6 0-12-5.4-12-12v-40zm-128 0c0-6.6 5.4-12 12-12h72c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H76c-6.6 0-12-5.4-12-12v-40zM576 80v48H0V80c0-26.5 21.5-48 48-48h480c26.5 0 48 21.5 48 48z"],crop:[512,512,[],"f125","M488 352h-40V109.3l57-57c9.4-9.4 9.4-24.6 0-33.9L493.7 7c-9.4-9.4-24.6-9.4-33.9 0l-57 57H160V24c0-13.3-10.7-24-24-24H88C74.7 0 64 10.7 64 24v40H24C10.7 64 0 74.7 0 88v48c0 13.3 10.7 24 24 24h40v264c0 13.3 10.7 24 24 24h264v40c0 13.3 10.7 24 24 24h48c13.3 0 24-10.7 24-24v-40h40c13.3 0 24-10.7 24-24v-48c0-13.3-10.7-24-24-24zM306.7 160L160 306.7V160h146.7zM205.3 352L352 205.3V352H205.3z"],crosshairs:[512,512,[],"f05b","M500 224h-30.364C455.724 130.325 381.675 56.276 288 42.364V12c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v30.364C130.325 56.276 56.276 130.325 42.364 224H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h30.364C56.276 381.675 130.325 455.724 224 469.636V500c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-30.364C381.675 455.724 455.724 381.675 469.636 288H500c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12zM288 404.634V364c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40.634C165.826 392.232 119.783 346.243 107.366 288H148c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-40.634C119.768 165.826 165.757 119.783 224 107.366V148c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40.634C346.174 119.768 392.217 165.757 404.634 224H364c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40.634C392.232 346.174 346.243 392.217 288 404.634zM288 256c0 17.673-14.327 32-32 32s-32-14.327-32-32c0-17.673 14.327-32 32-32s32 14.327 32 32z"],cube:[512,512,[],"f1b2","M239.1 6.3l-208 78c-18.7 7-31.1 25-31.1 45v225.1c0 18.2 10.3 34.8 26.5 42.9l208 104c13.5 6.8 29.4 6.8 42.9 0l208-104c16.3-8.1 26.5-24.8 26.5-42.9V129.3c0-20-12.4-37.9-31.1-44.9l-208-78C262 2.2 250 2.2 239.1 6.3zM256 68.4l192 72v1.1l-192 78-192-78v-1.1l192-72zm32 356V275.5l160-65v133.9l-160 80z"],cubes:[512,512,[],"f1b3","M488.6 250.2L392 214V105.5c0-15-9.3-28.4-23.4-33.7l-100-37.5c-8.1-3.1-17.1-3.1-25.3 0l-100 37.5c-14.1 5.3-23.4 18.7-23.4 33.7V214l-96.6 36.2C9.3 255.5 0 268.9 0 283.9V394c0 13.6 7.7 26.1 19.9 32.2l100 50c10.1 5.1 22.1 5.1 32.2 0l103.9-52 103.9 52c10.1 5.1 22.1 5.1 32.2 0l100-50c12.2-6.1 19.9-18.6 19.9-32.2V283.9c0-15-9.3-28.4-23.4-33.7zM358 214.8l-85 31.9v-68.2l85-37v73.3zM154 104.1l102-38.2 102 38.2v.6l-102 41.4-102-41.4v-.6zm84 291.1l-85 42.5v-79.1l85-38.8v75.4zm0-112l-102 41.4-102-41.4v-.6l102-38.2 102 38.2v.6zm240 112l-85 42.5v-79.1l85-38.8v75.4zm0-112l-102 41.4-102-41.4v-.6l102-38.2 102 38.2v.6z"],cut:[448,512,[],"f0c4","M444.485 422.426c4.689 4.689 4.684 12.287 0 16.971-32.804 32.804-85.991 32.804-118.795 0L210.176 323.883l-24.859 24.859C189.63 359.657 192 371.552 192 384c0 53.019-42.981 96-96 96S0 437.019 0 384s42.981-96 96-96c4.536 0 8.995.322 13.363.93l32.93-32.93-32.93-32.93c-4.368.608-8.827.93-13.363.93-53.019 0-96-42.981-96-96s42.981-96 96-96 96 42.981 96 96c0 12.448-2.37 24.343-6.682 35.258l24.859 24.859L325.69 72.603c32.804-32.804 85.991-32.804 118.795 0 4.684 4.684 4.689 12.282 0 16.971L278.059 256l166.426 166.426zM96 96c-17.645 0-32 14.355-32 32s14.355 32 32 32 32-14.355 32-32-14.355-32-32-32m0 256c-17.645 0-32 14.355-32 32s14.355 32 32 32 32-14.355 32-32-14.355-32-32-32m112-108c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12z"],database:[448,512,[],"f1c0","M448 73.143v45.714C448 159.143 347.667 192 224 192S0 159.143 0 118.857V73.143C0 32.857 100.333 0 224 0s224 32.857 224 73.143zM448 176v102.857C448 319.143 347.667 352 224 352S0 319.143 0 278.857V176c48.125 33.143 136.208 48.572 224 48.572S399.874 209.143 448 176zm0 160v102.857C448 479.143 347.667 512 224 512S0 479.143 0 438.857V336c48.125 33.143 136.208 48.572 224 48.572S399.874 369.143 448 336z"],deaf:[512,512,[],"f2a4","M216 260c0 15.464-12.536 28-28 28s-28-12.536-28-28c0-44.112 35.888-80 80-80s80 35.888 80 80c0 15.464-12.536 28-28 28s-28-12.536-28-28c0-13.234-10.767-24-24-24s-24 10.766-24 24zm24-176c-97.047 0-176 78.953-176 176 0 15.464 12.536 28 28 28s28-12.536 28-28c0-66.168 53.832-120 120-120s120 53.832 120 120c0 75.164-71.009 70.311-71.997 143.622L288 404c0 28.673-23.327 52-52 52-15.464 0-28 12.536-28 28s12.536 28 28 28c59.475 0 107.876-48.328 108-107.774.595-34.428 72-48.24 72-144.226 0-97.047-78.953-176-176-176zm268.485-52.201L480.2 3.515c-4.687-4.686-12.284-4.686-16.971 0L376.2 90.544c-4.686 4.686-4.686 12.284 0 16.971l28.285 28.285c4.686 4.686 12.284 4.686 16.97 0l87.03-87.029c4.687-4.688 4.687-12.286 0-16.972zM168.97 314.745c-4.686-4.686-12.284-4.686-16.97 0L3.515 463.23c-4.686 4.686-4.686 12.284 0 16.971L31.8 508.485c4.687 4.686 12.284 4.686 16.971 0L197.256 360c4.686-4.686 4.686-12.284 0-16.971l-28.286-28.284z"],desktop:[576,512,[],"f108","M528 0H48C21.5 0 0 21.5 0 48v320c0 26.5 21.5 48 48 48h192l-16 48h-72c-13.3 0-24 10.7-24 24s10.7 24 24 24h272c13.3 0 24-10.7 24-24s-10.7-24-24-24h-72l-16-48h192c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm-16 352H64V64h448v288z"],"dollar-sign":[320,512,[],"f155","M113.411 169.375c0-23.337 21.536-38.417 54.865-38.417 26.726 0 54.116 12.263 76.461 28.333 5.88 4.229 14.13 2.354 17.575-4.017l23.552-43.549c2.649-4.898 1.596-10.991-2.575-14.68-24.281-21.477-59.135-34.09-91.289-37.806V12c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v49.832c-58.627 13.29-97.299 55.917-97.299 108.639 0 123.533 184.765 110.81 184.765 169.414 0 19.823-16.311 41.158-52.124 41.158-30.751 0-62.932-15.88-87.848-35.887-5.31-4.264-13.082-3.315-17.159 2.14l-30.389 40.667c-3.627 4.854-3.075 11.657 1.302 15.847 24.049 23.02 59.249 41.255 98.751 47.973V500c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-47.438c65.72-10.215 106.176-59.186 106.176-116.516.001-119.688-184.764-103.707-184.764-166.671z"],"dot-circle":[512,512,[],"f192","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm80 248c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80z"],download:[512,512,[],"f019","M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"],edit:[576,512,[],"f044","M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"],eject:[448,512,[],"f052","M448 384v64c0 17.673-14.327 32-32 32H32c-17.673 0-32-14.327-32-32v-64c0-17.673 14.327-32 32-32h384c17.673 0 32 14.327 32 32zM48.053 320h351.886c41.651 0 63.581-49.674 35.383-80.435L259.383 47.558c-19.014-20.743-51.751-20.744-70.767 0L12.67 239.565C-15.475 270.268 6.324 320 48.053 320z"],"ellipsis-h":[512,512,[],"f141","M328 256c0 39.8-32.2 72-72 72s-72-32.2-72-72 32.2-72 72-72 72 32.2 72 72zm104-72c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm-352 0c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72z"],"ellipsis-v":[192,512,[],"f142","M96 184c39.8 0 72 32.2 72 72s-32.2 72-72 72-72-32.2-72-72 32.2-72 72-72zM24 80c0 39.8 32.2 72 72 72s72-32.2 72-72S135.8 8 96 8 24 40.2 24 80zm0 352c0 39.8 32.2 72 72 72s72-32.2 72-72-32.2-72-72-72-72 32.2-72 72z"],envelope:[512,512,[],"f0e0","M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"],"envelope-open":[512,512,[],"f2b6","M512 464c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V200.724a48 48 0 0 1 18.387-37.776c24.913-19.529 45.501-35.365 164.2-121.511C199.412 29.17 232.797-.347 256 .003c23.198-.354 56.596 29.172 73.413 41.433 118.687 86.137 139.303 101.995 164.2 121.512A48 48 0 0 1 512 200.724V464zm-65.666-196.605c-2.563-3.728-7.7-4.595-11.339-1.907-22.845 16.873-55.462 40.705-105.582 77.079-16.825 12.266-50.21 41.781-73.413 41.43-23.211.344-56.559-29.143-73.413-41.43-50.114-36.37-82.734-60.204-105.582-77.079-3.639-2.688-8.776-1.821-11.339 1.907l-9.072 13.196a7.998 7.998 0 0 0 1.839 10.967c22.887 16.899 55.454 40.69 105.303 76.868 20.274 14.781 56.524 47.813 92.264 47.573 35.724.242 71.961-32.771 92.263-47.573 49.85-36.179 82.418-59.97 105.303-76.868a7.998 7.998 0 0 0 1.839-10.967l-9.071-13.196z"],"envelope-square":[448,512,[],"f199","M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM178.117 262.104C87.429 196.287 88.353 196.121 64 177.167V152c0-13.255 10.745-24 24-24h272c13.255 0 24 10.745 24 24v25.167c-24.371 18.969-23.434 19.124-114.117 84.938-10.5 7.655-31.392 26.12-45.883 25.894-14.503.218-35.367-18.227-45.883-25.895zM384 217.775V360c0 13.255-10.745 24-24 24H88c-13.255 0-24-10.745-24-24V217.775c13.958 10.794 33.329 25.236 95.303 70.214 14.162 10.341 37.975 32.145 64.694 32.01 26.887.134 51.037-22.041 64.72-32.025 61.958-44.965 81.325-59.406 95.283-70.199z"],eraser:[512,512,[],"f12d","M497.941 273.941c18.745-18.745 18.745-49.137 0-67.882l-160-160c-18.745-18.745-49.136-18.746-67.883 0l-256 256c-18.745 18.745-18.745 49.137 0 67.882l96 96A48.004 48.004 0 0 0 144 480h356c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12H355.883l142.058-142.059zm-302.627-62.627l137.373 137.373L265.373 416H150.628l-80-80 124.686-124.686z"],"euro-sign":[320,512,[],"f153","M310.706 413.765c-1.314-6.63-7.835-10.872-14.424-9.369-10.692 2.439-27.422 5.413-45.426 5.413-56.763 0-101.929-34.79-121.461-85.449h113.689a12 12 0 0 0 11.708-9.369l6.373-28.36c1.686-7.502-4.019-14.631-11.708-14.631H115.22c-1.21-14.328-1.414-28.287.137-42.245H261.95a12 12 0 0 0 11.723-9.434l6.512-29.755c1.638-7.484-4.061-14.566-11.723-14.566H130.184c20.633-44.991 62.69-75.03 117.619-75.03 14.486 0 28.564 2.25 37.851 4.145 6.216 1.268 12.347-2.498 14.002-8.623l11.991-44.368c1.822-6.741-2.465-13.616-9.326-14.917C290.217 34.912 270.71 32 249.635 32 152.451 32 74.03 92.252 45.075 176H12c-6.627 0-12 5.373-12 12v29.755c0 6.627 5.373 12 12 12h21.569c-1.009 13.607-1.181 29.287-.181 42.245H12c-6.627 0-12 5.373-12 12v28.36c0 6.627 5.373 12 12 12h30.114C67.139 414.692 145.264 480 249.635 480c26.301 0 48.562-4.544 61.101-7.788 6.167-1.595 10.027-7.708 8.788-13.957l-8.818-44.49z"],"exchange-alt":[512,512,[],"f362","M0 168v-16c0-13.255 10.745-24 24-24h360V80c0-21.367 25.899-32.042 40.971-16.971l80 80c9.372 9.373 9.372 24.569 0 33.941l-80 80C409.956 271.982 384 261.456 384 240v-48H24c-13.255 0-24-10.745-24-24zm488 152H128v-48c0-21.314-25.862-32.08-40.971-16.971l-80 80c-9.372 9.373-9.372 24.569 0 33.941l80 80C102.057 463.997 128 453.437 128 432v-48h360c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24z"],exclamation:[192,512,[],"f12a","M176 432c0 44.112-35.888 80-80 80s-80-35.888-80-80 35.888-80 80-80 80 35.888 80 80zM25.26 25.199l13.6 272C39.499 309.972 50.041 320 62.83 320h66.34c12.789 0 23.331-10.028 23.97-22.801l13.6-272C167.425 11.49 156.496 0 142.77 0H49.23C35.504 0 24.575 11.49 25.26 25.199z"],"exclamation-circle":[512,512,[],"f06a","M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"],"exclamation-triangle":[576,512,[],"f071","M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"],expand:[448,512,[],"f065","M0 180V56c0-13.3 10.7-24 24-24h124c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H64v84c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12zM288 44v40c0 6.6 5.4 12 12 12h84v84c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12V56c0-13.3-10.7-24-24-24H300c-6.6 0-12 5.4-12 12zm148 276h-40c-6.6 0-12 5.4-12 12v84h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h124c13.3 0 24-10.7 24-24V332c0-6.6-5.4-12-12-12zM160 468v-40c0-6.6-5.4-12-12-12H64v-84c0-6.6-5.4-12-12-12H12c-6.6 0-12 5.4-12 12v124c0 13.3 10.7 24 24 24h124c6.6 0 12-5.4 12-12z"],"expand-arrows-alt":[448,512,[],"f31e","M448.1 344v112c0 13.3-10.7 24-24 24h-112c-21.4 0-32.1-25.9-17-41l36.2-36.2L224 295.6 116.8 402.9 153 439c15.1 15.1 4.4 41-17 41H24c-13.3 0-24-10.7-24-24V344c0-21.4 25.9-32.1 41-17l36.2 36.2L184.5 256 77.2 148.7 41 185c-15.1 15.1-41 4.4-41-17V56c0-13.3 10.7-24 24-24h112c21.4 0 32.1 25.9 17 41l-36.2 36.2L224 216.4l107.3-107.3L295.1 73c-15.1-15.1-4.4-41 17-41h112c13.3 0 24 10.7 24 24v112c0 21.4-25.9 32.1-41 17l-36.2-36.2L263.6 256l107.3 107.3 36.2-36.2c15.1-15.2 41-4.5 41 16.9z"],"external-link-alt":[576,512,[],"f35d","M576 24v127.984c0 21.461-25.96 31.98-40.971 16.971l-35.707-35.709-243.523 243.523c-9.373 9.373-24.568 9.373-33.941 0l-22.627-22.627c-9.373-9.373-9.373-24.569 0-33.941L442.756 76.676l-35.703-35.705C391.982 25.9 402.656 0 424.024 0H552c13.255 0 24 10.745 24 24zM407.029 270.794l-16 16A23.999 23.999 0 0 0 384 303.765V448H64V128h264a24.003 24.003 0 0 0 16.97-7.029l16-16C376.089 89.851 365.381 64 344 64H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V287.764c0-21.382-25.852-32.09-40.971-16.97z"],"external-link-square-alt":[448,512,[],"f360","M448 80v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48zm-88 16H248.029c-21.313 0-32.08 25.861-16.971 40.971l31.984 31.987L67.515 364.485c-4.686 4.686-4.686 12.284 0 16.971l31.029 31.029c4.687 4.686 12.285 4.686 16.971 0l195.526-195.526 31.988 31.991C358.058 263.977 384 253.425 384 231.979V120c0-13.255-10.745-24-24-24z"],eye:[576,512,[],"f06e","M569.354 231.631C512.969 135.949 407.81 72 288 72 168.14 72 63.004 135.994 6.646 231.631a47.999 47.999 0 0 0 0 48.739C63.031 376.051 168.19 440 288 440c119.86 0 224.996-63.994 281.354-159.631a47.997 47.997 0 0 0 0-48.738zM288 392c-75.162 0-136-60.827-136-136 0-75.162 60.826-136 136-136 75.162 0 136 60.826 136 136 0 75.162-60.826 136-136 136zm104-136c0 57.438-46.562 104-104 104s-104-46.562-104-104c0-17.708 4.431-34.379 12.236-48.973l-.001.032c0 23.651 19.173 42.823 42.824 42.823s42.824-19.173 42.824-42.823c0-23.651-19.173-42.824-42.824-42.824l-.032.001C253.621 156.431 270.292 152 288 152c57.438 0 104 46.562 104 104z"],"eye-dropper":[512,512,[],"f1fb","M177.38 206.64L39.03 344.97A24.01 24.01 0 0 0 32 361.94V424L0 480l32 32 56-32h62.06c6.36 0 12.47-2.53 16.97-7.03l138.35-138.33-128-128zm225.552 30.47l16.952 16.95c9.37 9.37 9.37 24.57 0 33.94l-40.973 40.97c-9.292 9.312-24.506 9.434-33.94 0L183.028 167.03c-9.37-9.37-9.37-24.57 0-33.94L224 92.12c9.289-9.309 24.502-9.438 33.94 0l16.992 16.99 82.606-82.601c35.19-35.19 92.5-35.5 128 0 40.49 48.08 29.66 98.34 0 128l-82.606 82.601z"],"eye-slash":[576,512,[],"f070","M286.693 391.984l32.579 46.542A333.958 333.958 0 0 1 288 440C168.19 440 63.031 376.051 6.646 280.369a47.999 47.999 0 0 1 0-48.739c24.023-40.766 56.913-75.775 96.024-102.537l57.077 81.539C154.736 224.82 152 240.087 152 256c0 74.736 60.135 135.282 134.693 135.984zm282.661-111.615c-31.667 53.737-78.747 97.46-135.175 125.475l.011.015 41.47 59.2c7.6 10.86 4.96 25.82-5.9 33.42l-13.11 9.18c-10.86 7.6-25.82 4.96-33.42-5.9L100.34 46.94c-7.6-10.86-4.96-25.82 5.9-33.42l13.11-9.18c10.86-7.6 25.82-4.96 33.42 5.9l51.038 72.617C230.68 75.776 258.905 72 288 72c119.81 0 224.969 63.949 281.354 159.631a48.002 48.002 0 0 1 0 48.738zM424 256c0-75.174-60.838-136-136-136-17.939 0-35.056 3.473-50.729 9.772l19.299 27.058c25.869-8.171 55.044-6.163 80.4 7.41h-.03c-23.65 0-42.82 19.17-42.82 42.82 0 23.626 19.147 42.82 42.82 42.82 23.65 0 42.82-19.17 42.82-42.82v-.03c18.462 34.49 16.312 77.914-8.25 110.95v.01l19.314 27.061C411.496 321.2 424 290.074 424 256zM262.014 356.727l-77.53-110.757c-5.014 52.387 29.314 98.354 77.53 110.757z"],"fast-backward":[512,512,[],"f049","M0 436V76c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v151.9L235.5 71.4C256.1 54.3 288 68.6 288 96v131.9L459.5 71.4C480.1 54.3 512 68.6 512 96v320c0 27.4-31.9 41.7-52.5 24.6L288 285.3V416c0 27.4-31.9 41.7-52.5 24.6L64 285.3V436c0 6.6-5.4 12-12 12H12c-6.6 0-12-5.4-12-12z"],"fast-forward":[512,512,[],"f050","M512 76v360c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12V284.1L276.5 440.6c-20.6 17.2-52.5 2.8-52.5-24.6V284.1L52.5 440.6C31.9 457.8 0 443.4 0 416V96c0-27.4 31.9-41.7 52.5-24.6L224 226.8V96c0-27.4 31.9-41.7 52.5-24.6L448 226.8V76c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12z"],fax:[512,512,[],"f1ac","M128 144v320c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V144c0-26.51 21.49-48 48-48h32c26.51 0 48 21.49 48 48zm384 64v256c0 26.51-21.49 48-48 48H192c-26.51 0-48-21.49-48-48V40c0-22.091 17.909-40 40-40h207.432a39.996 39.996 0 0 1 28.284 11.716l48.569 48.569A39.999 39.999 0 0 1 480 88.568v74.174c18.641 6.591 32 24.36 32 45.258zm-320-16h240V96h-24c-13.203 0-24-10.797-24-24V48H192v144zm96 204c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40zm0-128c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40zm128 128c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40zm0-128c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40z"],female:[256,512,[],"f182","M128 0c35.346 0 64 28.654 64 64s-28.654 64-64 64c-35.346 0-64-28.654-64-64S92.654 0 128 0m119.283 354.179l-48-192A24 24 0 0 0 176 144h-11.36c-22.711 10.443-49.59 10.894-73.28 0H80a24 24 0 0 0-23.283 18.179l-48 192C4.935 369.305 16.383 384 32 384h56v104c0 13.255 10.745 24 24 24h32c13.255 0 24-10.745 24-24V384h56c15.591 0 27.071-14.671 23.283-29.821z"],"fighter-jet":[640,512,[],"f0fb","M544 224l-128-16-48-16h-24L227.158 44h39.509C278.333 44 288 41.375 288 38s-9.667-6-21.333-6H152v12h16v164h-48l-66.667-80H18.667L8 138.667V208h8v16h48v2.666l-64 8v42.667l64 8V288H16v16H8v69.333L18.667 384h34.667L120 304h48v164h-16v12h114.667c11.667 0 21.333-2.625 21.333-6s-9.667-6-21.333-6h-39.509L344 320h24l48-16 128-16c96-21.333 96-26.583 96-32 0-5.417 0-10.667-96-32z"],file:[384,512,[],"f15b","M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm160-14.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],"file-alt":[384,512,[],"f15c","M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm64 236c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-64c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12v8zm0-72v8c0 6.6-5.4 12-12 12H108c-6.6 0-12-5.4-12-12v-8c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm96-114.1v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],"file-archive":[384,512,[],"f1c6","M224 136V0h-63.6v32h-32V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zM95.9 32h32v32h-32V32zm32.3 384c-33.2 0-58-30.4-51.4-62.9L96.4 256v-32h32v-32h-32v-32h32v-32h-32V96h32V64h32v32h-32v32h32v32h-32v32h32v32h-32v32h22.1c5.7 0 10.7 4.1 11.8 9.7l17.3 87.7c6.4 32.4-18.4 62.6-51.4 62.6zm32.7-53c0 14.9-14.5 27-32.4 27S96 378 96 363c0-14.9 14.5-27 32.4-27s32.5 12.1 32.5 27zM384 121.9v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],"file-audio":[384,512,[],"f1c7","M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm-64 268c0 10.7-12.9 16-20.5 8.5L104 376H76c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h28l35.5-36.5c7.6-7.6 20.5-2.2 20.5 8.5v136zm33.2-47.6c9.1-9.3 9.1-24.1 0-33.4-22.1-22.8 12.2-56.2 34.4-33.5 27.2 27.9 27.2 72.4 0 100.4-21.8 22.3-56.9-10.4-34.4-33.5zm86-117.1c54.4 55.9 54.4 144.8 0 200.8-21.8 22.4-57-10.3-34.4-33.5 36.2-37.2 36.3-96.5 0-133.8-22.1-22.8 12.3-56.3 34.4-33.5zM384 121.9v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],"file-code":[384,512,[],"f1c9","M384 121.941V128H256V0h6.059c6.365 0 12.47 2.529 16.971 7.029l97.941 97.941A24.005 24.005 0 0 1 384 121.941zM248 160c-13.2 0-24-10.8-24-24V0H24C10.745 0 0 10.745 0 24v464c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V160H248zM123.206 400.505a5.4 5.4 0 0 1-7.633.246l-64.866-60.812a5.4 5.4 0 0 1 0-7.879l64.866-60.812a5.4 5.4 0 0 1 7.633.246l19.579 20.885a5.4 5.4 0 0 1-.372 7.747L101.65 336l40.763 35.874a5.4 5.4 0 0 1 .372 7.747l-19.579 20.884zm51.295 50.479l-27.453-7.97a5.402 5.402 0 0 1-3.681-6.692l61.44-211.626a5.402 5.402 0 0 1 6.692-3.681l27.452 7.97a5.4 5.4 0 0 1 3.68 6.692l-61.44 211.626a5.397 5.397 0 0 1-6.69 3.681zm160.792-111.045l-64.866 60.812a5.4 5.4 0 0 1-7.633-.246l-19.58-20.885a5.4 5.4 0 0 1 .372-7.747L284.35 336l-40.763-35.874a5.4 5.4 0 0 1-.372-7.747l19.58-20.885a5.4 5.4 0 0 1 7.633-.246l64.866 60.812a5.4 5.4 0 0 1-.001 7.879z"],"file-excel":[384,512,[],"f1c3","M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm60.1 106.5L224 336l60.1 93.5c5.1 8-.6 18.5-10.1 18.5h-34.9c-4.4 0-8.5-2.4-10.6-6.3C208.9 405.5 192 373 192 373c-6.4 14.8-10 20-36.6 68.8-2.1 3.9-6.1 6.3-10.5 6.3H110c-9.5 0-15.2-10.5-10.1-18.5l60.3-93.5-60.3-93.5c-5.2-8 .6-18.5 10.1-18.5h34.8c4.4 0 8.5 2.4 10.6 6.3 26.1 48.8 20 33.6 36.6 68.5 0 0 6.1-11.7 36.6-68.5 2.1-3.9 6.2-6.3 10.6-6.3H274c9.5-.1 15.2 10.4 10.1 18.4zM384 121.9v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],"file-image":[384,512,[],"f1c5","M384 121.941V128H256V0h6.059a24 24 0 0 1 16.97 7.029l97.941 97.941a24.002 24.002 0 0 1 7.03 16.971zM248 160c-13.2 0-24-10.8-24-24V0H24C10.745 0 0 10.745 0 24v464c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V160H248zm-135.455 16c26.51 0 48 21.49 48 48s-21.49 48-48 48-48-21.49-48-48 21.491-48 48-48zm208 240h-256l.485-48.485L104.545 328c4.686-4.686 11.799-4.201 16.485.485L160.545 368 264.06 264.485c4.686-4.686 12.284-4.686 16.971 0L320.545 304v112z"],"file-pdf":[384,512,[],"f1c1","M181.9 256.1c-5-16-4.9-46.9-2-46.9 8.4 0 7.6 36.9 2 46.9zm-1.7 47.2c-7.7 20.2-17.3 43.3-28.4 62.7 18.3-7 39-17.2 62.9-21.9-12.7-9.6-24.9-23.4-34.5-40.8zM86.1 428.1c0 .8 13.2-5.4 34.9-40.2-6.7 6.3-29.1 24.5-34.9 40.2zM248 160h136v328c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V24C0 10.7 10.7 0 24 0h200v136c0 13.2 10.8 24 24 24zm-8 171.8c-20-12.2-33.3-29-42.7-53.8 4.5-18.5 11.6-46.6 6.2-64.2-4.7-29.4-42.4-26.5-47.8-6.8-5 18.3-.4 44.1 8.1 77-11.6 27.6-28.7 64.6-40.8 85.8-.1 0-.1.1-.2.1-27.1 13.9-73.6 44.5-54.5 68 5.6 6.9 16 10 21.5 10 17.9 0 35.7-18 61.1-61.8 25.8-8.5 54.1-19.1 79-23.2 21.7 11.8 47.1 19.5 64 19.5 29.2 0 31.2-32 19.7-43.4-13.9-13.6-54.3-9.7-73.6-7.2zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-74.1 255.3c4.1-2.7-2.5-11.9-42.8-9 37.1 15.8 42.8 9 42.8 9z"],"file-powerpoint":[384,512,[],"f1c4","M193.7 271.2c8.8 0 15.5 2.7 20.3 8.1 9.6 10.9 9.8 32.7-.2 44.1-4.9 5.6-11.9 8.5-21.1 8.5h-26.9v-60.7h27.9zM377 105L279 7c-4.5-4.5-10.6-7-17-7h-6v128h128v-6.1c0-6.3-2.5-12.4-7-16.9zm-153 31V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm53 165.2c0 90.3-88.8 77.6-111.1 77.6V436c0 6.6-5.4 12-12 12h-30.8c-6.6 0-12-5.4-12-12V236.2c0-6.6 5.4-12 12-12h81c44.5 0 72.9 32.8 72.9 77z"],"file-video":[384,512,[],"f1c8","M384 121.941V128H256V0h6.059c6.365 0 12.47 2.529 16.971 7.029l97.941 97.941A24.005 24.005 0 0 1 384 121.941zM224 136V0H24C10.745 0 0 10.745 0 24v464c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V160H248c-13.2 0-24-10.8-24-24zm96 144.016v111.963c0 21.445-25.943 31.998-40.971 16.971L224 353.941V392c0 13.255-10.745 24-24 24H88c-13.255 0-24-10.745-24-24V280c0-13.255 10.745-24 24-24h112c13.255 0 24 10.745 24 24v38.059l55.029-55.013c15.011-15.01 40.971-4.491 40.971 16.97z"],"file-word":[384,512,[],"f1c2","M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm57.1 120H305c7.7 0 13.4 7.1 11.7 14.7l-38 168c-1.2 5.5-6.1 9.3-11.7 9.3h-38c-5.5 0-10.3-3.8-11.6-9.1-25.8-103.5-20.8-81.2-25.6-110.5h-.5c-1.1 14.3-2.4 17.4-25.6 110.5-1.3 5.3-6.1 9.1-11.6 9.1H117c-5.6 0-10.5-3.9-11.7-9.4l-37.8-168c-1.7-7.5 4-14.6 11.7-14.6h24.5c5.7 0 10.7 4 11.8 9.7 15.6 78 20.1 109.5 21 122.2 1.6-10.2 7.3-32.7 29.4-122.7 1.3-5.4 6.1-9.1 11.7-9.1h29.1c5.6 0 10.4 3.8 11.7 9.2 24 100.4 28.8 124 29.6 129.4-.2-11.2-2.6-17.8 21.6-129.2 1-5.6 5.9-9.5 11.5-9.5zM384 121.9v6.1H256V0h6.1c6.4 0 12.5 2.5 17 7l97.9 98c4.5 4.5 7 10.6 7 16.9z"],film:[512,512,[],"f008","M488 64h-8v20c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12V64H96v20c0 6.6-5.4 12-12 12H44c-6.6 0-12-5.4-12-12V64h-8C10.7 64 0 74.7 0 88v336c0 13.3 10.7 24 24 24h8v-20c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v20h320v-20c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v20h8c13.3 0 24-10.7 24-24V88c0-13.3-10.7-24-24-24zM96 372c0 6.6-5.4 12-12 12H44c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40zm0-96c0 6.6-5.4 12-12 12H44c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40zm0-96c0 6.6-5.4 12-12 12H44c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40zm272 208c0 6.6-5.4 12-12 12H156c-6.6 0-12-5.4-12-12v-96c0-6.6 5.4-12 12-12h200c6.6 0 12 5.4 12 12v96zm0-168c0 6.6-5.4 12-12 12H156c-6.6 0-12-5.4-12-12v-96c0-6.6 5.4-12 12-12h200c6.6 0 12 5.4 12 12v96zm112 152c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40zm0-96c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40zm0-96c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40z"],filter:[512,512,[],"f0b0","M487.976 0H24.028C2.71 0-8.047 25.866 7.058 40.971L192 225.941V432c0 7.831 3.821 15.17 10.237 19.662l80 55.98C298.02 518.69 320 507.493 320 487.98V225.941l184.947-184.97C520.021 25.896 509.338 0 487.976 0z"],fire:[384,512,[],"f06d","M216 23.858c0-23.802-30.653-32.765-44.149-13.038C48 191.851 224 200 224 288c0 35.629-29.114 64.458-64.85 63.994C123.98 351.538 96 322.22 96 287.046v-85.51c0-21.703-26.471-32.225-41.432-16.504C27.801 213.158 0 261.332 0 320c0 105.869 86.131 192 192 192s192-86.131 192-192c0-170.29-168-193.003-168-296.142z"],"fire-extinguisher":[448,512,[],"f134","M434.027 26.329l-168 28C254.693 56.218 256 67.8 256 72h-58.332C208.353 36.108 181.446 0 144 0c-39.435 0-66.368 39.676-52.228 76.203-52.039 13.051-75.381 54.213-90.049 90.884-4.923 12.307 1.063 26.274 13.37 31.197 12.317 4.926 26.279-1.075 31.196-13.37C75.058 112.99 106.964 120 168 120v27.076c-41.543 10.862-72 49.235-72 94.129V488c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24V240c0-44.731-30.596-82.312-72-92.97V120h40c0 2.974-1.703 15.716 10.027 17.671l168 28C441.342 166.89 448 161.25 448 153.834V38.166c0-7.416-6.658-13.056-13.973-11.837zM144 72c-8.822 0-16-7.178-16-16s7.178-16 16-16 16 7.178 16 16-7.178 16-16 16z"],flag:[512,512,[],"f024","M349.565 98.783C295.978 98.783 251.721 64 184.348 64c-24.955 0-47.309 4.384-68.045 12.013a55.947 55.947 0 0 0 3.586-23.562C118.117 24.015 94.806 1.206 66.338.048 34.345-1.254 8 24.296 8 56c0 19.026 9.497 35.825 24 45.945V488c0 13.255 10.745 24 24 24h16c13.255 0 24-10.745 24-24v-94.4c28.311-12.064 63.582-22.122 114.435-22.122 53.588 0 97.844 34.783 165.217 34.783 48.169 0 86.667-16.294 122.505-40.858C506.84 359.452 512 349.571 512 339.045v-243.1c0-23.393-24.269-38.87-45.485-29.016-34.338 15.948-76.454 31.854-116.95 31.854z"],"flag-checkered":[512,512,[],"f11e","M466.515 66.928C487.731 57.074 512 72.551 512 95.944v243.1c0 10.526-5.161 20.407-13.843 26.358-35.837 24.564-74.335 40.858-122.505 40.858-67.373 0-111.63-34.783-165.217-34.783-50.853 0-86.124 10.058-114.435 22.122V488c0 13.255-10.745 24-24 24H56c-13.255 0-24-10.745-24-24V101.945C17.497 91.825 8 75.026 8 56 8 24.296 34.345-1.254 66.338.048c28.468 1.158 51.779 23.968 53.551 52.404.52 8.342-.81 16.31-3.586 23.562C137.039 68.384 159.393 64 184.348 64c67.373 0 111.63 34.783 165.217 34.783 40.496 0 82.612-15.906 116.95-31.855zM96 134.63v70.49c29-10.67 51.18-17.83 73.6-20.91v-71.57c-23.5 2.17-40.44 9.79-73.6 21.99zm220.8 9.19c-26.417-4.672-49.886-13.979-73.6-21.34v67.42c24.175 6.706 47.566 16.444 73.6 22.31v-68.39zm-147.2 40.39v70.04c32.796-2.978 53.91-.635 73.6 3.8V189.9c-25.247-7.035-46.581-9.423-73.6-5.69zm73.6 142.23c26.338 4.652 49.732 13.927 73.6 21.34v-67.41c-24.277-6.746-47.54-16.45-73.6-22.32v68.39zM96 342.1c23.62-8.39 47.79-13.84 73.6-16.56v-71.29c-26.11 2.35-47.36 8.04-73.6 17.36v70.49zm368-221.6c-21.3 8.85-46.59 17.64-73.6 22.47v71.91c27.31-4.36 50.03-14.1 73.6-23.89V120.5zm0 209.96v-70.49c-22.19 14.2-48.78 22.61-73.6 26.02v71.58c25.07-2.38 48.49-11.04 73.6-27.11zM316.8 212.21v68.16c25.664 7.134 46.616 9.342 73.6 5.62v-71.11c-25.999 4.187-49.943 2.676-73.6-2.67z"],flask:[448,512,[],"f0c3","M437.2 403.5L320 215V64h8c13.3 0 24-10.7 24-24V24c0-13.3-10.7-24-24-24H120c-13.3 0-24 10.7-24 24v16c0 13.3 10.7 24 24 24h8v151L10.8 403.5C-18.5 450.6 15.3 512 70.9 512h306.2c55.7 0 89.4-61.5 60.1-108.5zM137.9 320l48.2-77.6c3.7-5.2 5.8-11.6 5.8-18.4V64h64v160c0 6.9 2.2 13.2 5.8 18.4l48.2 77.6h-172z"],folder:[512,512,[],"f07b","M464 128H272l-64-64H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V176c0-26.51-21.49-48-48-48z"],"folder-open":[576,512,[],"f07c","M572.694 292.093L500.27 416.248A63.997 63.997 0 0 1 444.989 448H45.025c-18.523 0-30.064-20.093-20.731-36.093l72.424-124.155A64 64 0 0 1 152 256h399.964c18.523 0 30.064 20.093 20.73 36.093zM152 224h328v-48c0-26.51-21.49-48-48-48H272l-64-64H48C21.49 64 0 85.49 0 112v278.046l69.077-118.418C86.214 242.25 117.989 224 152 224z"],font:[448,512,[],"f031","M152 416h-24.013l26.586-80.782H292.8L319.386 416H296c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h136c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-26.739L275.495 42.746A16 16 0 0 0 260.382 32h-72.766a16 16 0 0 0-15.113 10.746L42.739 416H16c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h136c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16zm64.353-271.778c4.348-15.216 6.61-28.156 7.586-34.644.839 6.521 2.939 19.476 7.727 34.706l41.335 124.006h-98.619l41.971-124.068z"],forward:[512,512,[],"f04e","M500.5 231.4l-192-160C287.9 54.3 256 68.6 256 96v320c0 27.4 31.9 41.8 52.5 24.6l192-160c15.3-12.8 15.3-36.4 0-49.2zm-256 0l-192-160C31.9 54.3 0 68.6 0 96v320c0 27.4 31.9 41.8 52.5 24.6l192-160c15.3-12.8 15.3-36.4 0-49.2z"],frown:[512,512,[],"f119","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-396-64c0 37.497 30.503 68 68 68s68-30.503 68-68-30.503-68-68-68-68 30.503-68 68zm160.5 0c0 37.221 30.279 67.5 67.5 67.5s67.5-30.279 67.5-67.5-30.279-67.5-67.5-67.5-67.5 30.279-67.5 67.5zm67.5-48a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 288 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48zm-160 0a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 128 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48zm192.551 212.66c-59.128-91.455-165.846-91.594-225.064 0-11.502 17.79 15.383 35.148 26.873 17.374 46.626-72.118 124.862-71.855 171.318 0 11.328 17.524 38.548.684 26.873-17.374z"],futbol:[512,512,[],"f1e3","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-48 0l-.003-.282-26.064 22.741-62.679-58.5 16.454-84.355 34.303 3.072c-24.889-34.216-60.004-60.089-100.709-73.141l13.651 31.939L256 139l-74.953-41.525 13.651-31.939c-40.631 13.028-75.78 38.87-100.709 73.141l34.565-3.073 16.192 84.355-62.678 58.5-26.064-22.741-.003.282c0 43.015 13.497 83.952 38.472 117.991l7.704-33.897 85.138 10.447 36.301 77.826-29.902 17.786c40.202 13.122 84.29 13.148 124.572 0l-29.902-17.786 36.301-77.826 85.138-10.447 7.704 33.897C442.503 339.952 456 299.015 456 256zm-248.102 69.571l-29.894-91.312L256 177.732l77.996 56.527-29.622 91.312h-96.476z"],gamepad:[640,512,[],"f11b","M480 96H160C71.6 96 0 167.6 0 256s71.6 160 160 160c44.8 0 85.2-18.4 114.2-48h91.5c29 29.6 69.5 48 114.2 48 88.4 0 160-71.6 160-160S568.4 96 480 96zM256 276c0 6.6-5.4 12-12 12h-52v52c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12v-52H76c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h52v-52c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v52h52c6.6 0 12 5.4 12 12v40zm184 68c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48zm80-80c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z"],gavel:[512,512,[],"f0e3","M504.971 199.362l-22.627-22.627c-9.373-9.373-24.569-9.373-33.941 0l-5.657 5.657L329.608 69.255l5.657-5.657c9.373-9.373 9.373-24.569 0-33.941L312.638 7.029c-9.373-9.373-24.569-9.373-33.941 0L154.246 131.48c-9.373 9.373-9.373 24.569 0 33.941l22.627 22.627c9.373 9.373 24.569 9.373 33.941 0l5.657-5.657 39.598 39.598-81.04 81.04-5.657-5.657c-12.497-12.497-32.758-12.497-45.255 0L9.373 412.118c-12.497 12.497-12.497 32.758 0 45.255l45.255 45.255c12.497 12.497 32.758 12.497 45.255 0l114.745-114.745c12.497-12.497 12.497-32.758 0-45.255l-5.657-5.657 81.04-81.04 39.598 39.598-5.657 5.657c-9.373 9.373-9.373 24.569 0 33.941l22.627 22.627c9.373 9.373 24.569 9.373 33.941 0l124.451-124.451c9.372-9.372 9.372-24.568 0-33.941z"],gem:[576,512,[],"f3a5","M485.5 0L576 160H474.9L405.7 0h79.8zm-128 0l69.2 160H149.3L218.5 0h139zm-267 0h79.8l-69.2 160H0L90.5 0zM0 192h100.7l123 251.7c1.5 3.1-2.7 5.9-5 3.3L0 192zm148.2 0h279.6l-137 318.2c-1 2.4-4.5 2.4-5.5 0L148.2 192zm204.1 251.7l123-251.7H576L357.3 446.9c-2.3 2.7-6.5-.1-5-3.2z"],genderless:[288,512,[],"f22d","M144 176c44.1 0 80 35.9 80 80s-35.9 80-80 80-80-35.9-80-80 35.9-80 80-80m0-64C64.5 112 0 176.5 0 256s64.5 144 144 144 144-64.5 144-144-64.5-144-144-144z"],gift:[512,512,[],"f06b","M488 192h-64.512C438.72 175.003 448 152.566 448 128c0-52.935-43.065-96-96-96-41.997 0-68.742 20.693-95.992 54.15C226.671 50.192 199.613 32 160 32c-52.935 0-96 43.065-96 96 0 24.566 9.28 47.003 24.512 64H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h8v112c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V320h8c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zm-208-32c24-56 55.324-64 72-64 17.645 0 32 14.355 32 32s-14.355 32-32 32h-72zM160 96c16.676 0 48 8 72 64h-72c-17.645 0-32-14.355-32-32s14.355-32 32-32zm48 128h96v184c0 13.255-10.745 24-24 24h-48c-13.255 0-24-10.745-24-24V224z"],"glass-martini":[512,512,[],"f000","M507.3 27.3c10-10 2.9-27.3-11.3-27.3H16C1.8 0-5.4 17.2 4.7 27.3L216 238.6V472h-92c-15.5 0-28 12.5-28 28 0 6.6 5.4 12 12 12h296c6.6 0 12-5.4 12-12 0-15.5-12.5-28-28-28h-92V238.6L507.3 27.3z"],globe:[512,512,[],"f0ac","M364.215 192h131.43c5.439 20.419 8.354 41.868 8.354 64s-2.915 43.581-8.354 64h-131.43c5.154-43.049 4.939-86.746 0-128zM185.214 352c10.678 53.68 33.173 112.514 70.125 151.992.221.001.44.008.661.008s.44-.008.661-.008c37.012-39.543 59.467-98.414 70.125-151.992H185.214zm174.13-192h125.385C452.802 84.024 384.128 27.305 300.95 12.075c30.238 43.12 48.821 96.332 58.394 147.925zm-27.35 32H180.006c-5.339 41.914-5.345 86.037 0 128h151.989c5.339-41.915 5.345-86.037-.001-128zM152.656 352H27.271c31.926 75.976 100.6 132.695 183.778 147.925-30.246-43.136-48.823-96.35-58.393-147.925zm206.688 0c-9.575 51.605-28.163 104.814-58.394 147.925 83.178-15.23 151.852-71.949 183.778-147.925H359.344zm-32.558-192c-10.678-53.68-33.174-112.514-70.125-151.992-.221 0-.44-.008-.661-.008s-.44.008-.661.008C218.327 47.551 195.872 106.422 185.214 160h141.572zM16.355 192C10.915 212.419 8 233.868 8 256s2.915 43.581 8.355 64h131.43c-4.939-41.254-5.154-84.951 0-128H16.355zm136.301-32c9.575-51.602 28.161-104.81 58.394-147.925C127.872 27.305 59.198 84.024 27.271 160h125.385z"],"graduation-cap":[640,512,[],"f19d","M622.884 199.005l-275.817 85.1a96 96 0 0 1-54.134 0L92.398 222.232c-8.564 11.438-11.018 23.05-11.918 38.335C89.778 266.165 96 276.355 96 288c0 11.952-6.557 22.366-16.265 27.861l16.197 123.096c.63 4.786-3.1 9.043-7.932 9.043H40c-4.828 0-8.562-4.253-7.932-9.044L48.265 315.86C38.557 310.366 32 299.952 32 288c0-12.034 6.646-22.511 16.465-27.976.947-17.951 3.974-33.231 12.152-47.597l-43.502-13.422c-22.876-6.801-22.766-39.241 0-46.01l275.817-85.1a96 96 0 0 1 54.134 0l275.817 85.1c22.877 6.801 22.767 39.241.001 46.01zM356.503 314.682l-.207.064-.207.061a127.998 127.998 0 0 1-72.177 0l-.207-.061-.207-.064-150.914-46.57L120 352c0 35.346 89.543 64 200 64s200-28.654 200-64l-12.583-83.888-150.914 46.57z"],"h-square":[448,512,[],"f0fd","M448 80v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48zm-112 48h-32c-8.837 0-16 7.163-16 16v80H160v-80c0-8.837-7.163-16-16-16h-32c-8.837 0-16 7.163-16 16v224c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16v-80h128v80c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16V144c0-8.837-7.163-16-16-16z"],"hand-lizard":[576,512,[],"f258","M384 480h192V363.778a95.998 95.998 0 0 0-14.833-51.263L398.127 54.368A48 48 0 0 0 357.544 32H24C10.745 32 0 42.745 0 56v16c0 30.928 25.072 56 56 56h229.981c12.844 0 21.556 13.067 16.615 24.923l-21.41 51.385A32 32 0 0 1 251.648 224H128c-35.346 0-64 28.654-64 64v8c0 13.255 10.745 24 24 24h147.406a47.995 47.995 0 0 1 25.692 7.455l111.748 70.811A24.001 24.001 0 0 1 384 418.539V480z"],"hand-paper":[448,512,[],"f256","M408.781 128.007C386.356 127.578 368 146.36 368 168.79V256h-8V79.79c0-22.43-18.356-41.212-40.781-40.783C297.488 39.423 280 57.169 280 79v177h-8V40.79C272 18.36 253.644-.422 231.219.007 209.488.423 192 18.169 192 40v216h-8V80.79c0-22.43-18.356-41.212-40.781-40.783C121.488 40.423 104 58.169 104 80v235.992l-31.648-43.519c-12.993-17.866-38.009-21.817-55.877-8.823-17.865 12.994-21.815 38.01-8.822 55.877l125.601 172.705A48 48 0 0 0 172.073 512h197.59c22.274 0 41.622-15.324 46.724-37.006l26.508-112.66a192.011 192.011 0 0 0 5.104-43.975V168c.001-21.831-17.487-39.577-39.218-39.993z"],"hand-peace":[448,512,[],"f25b","M408 216c-22.092 0-40 17.909-40 40h-8v-32c0-22.091-17.908-40-40-40s-40 17.909-40 40v32h-8V48c0-26.51-21.49-48-48-48s-48 21.49-48 48v208h-13.572L92.688 78.449C82.994 53.774 55.134 41.63 30.461 51.324 5.787 61.017-6.356 88.877 3.337 113.551l74.765 190.342-31.09 24.872c-15.381 12.306-19.515 33.978-9.741 51.081l64 112A39.998 39.998 0 0 0 136 512h240c18.562 0 34.686-12.77 38.937-30.838l32-136A39.97 39.97 0 0 0 448 336v-80c0-22.091-17.908-40-40-40z"],"hand-point-down":[384,512,[],"f0a7","M91.826 467.2V317.966c-8.248 5.841-16.558 10.57-24.918 14.153C35.098 345.752-.014 322.222 0 288c.008-18.616 10.897-32.203 29.092-40 28.286-12.122 64.329-78.648 77.323-107.534 7.956-17.857 25.479-28.453 43.845-28.464l.001-.002h171.526c11.812 0 21.897 8.596 23.703 20.269 7.25 46.837 38.483 61.76 38.315 123.731-.007 2.724.195 13.254.195 16 0 50.654-22.122 81.574-71.263 72.6-9.297 18.597-39.486 30.738-62.315 16.45-21.177 24.645-53.896 22.639-70.944 6.299V467.2c0 24.15-20.201 44.8-43.826 44.8-23.283 0-43.826-21.35-43.826-44.8zM112 72V24c0-13.255 10.745-24 24-24h192c13.255 0 24 10.745 24 24v48c0 13.255-10.745 24-24 24H136c-13.255 0-24-10.745-24-24zm212-24c0-11.046-8.954-20-20-20s-20 8.954-20 20 8.954 20 20 20 20-8.954 20-20z"],"hand-point-left":[512,512,[],"f0a5","M44.8 155.826h149.234c-5.841-8.248-10.57-16.558-14.153-24.918C166.248 99.098 189.778 63.986 224 64c18.616.008 32.203 10.897 40 29.092 12.122 28.286 78.648 64.329 107.534 77.323 17.857 7.956 28.453 25.479 28.464 43.845l.002.001v171.526c0 11.812-8.596 21.897-20.269 23.703-46.837 7.25-61.76 38.483-123.731 38.315-2.724-.007-13.254.195-16 .195-50.654 0-81.574-22.122-72.6-71.263-18.597-9.297-30.738-39.486-16.45-62.315-24.645-21.177-22.639-53.896-6.299-70.944H44.8c-24.15 0-44.8-20.201-44.8-43.826 0-23.283 21.35-43.826 44.8-43.826zM440 176h48c13.255 0 24 10.745 24 24v192c0 13.255-10.745 24-24 24h-48c-13.255 0-24-10.745-24-24V200c0-13.255 10.745-24 24-24zm24 212c11.046 0 20-8.954 20-20s-8.954-20-20-20-20 8.954-20 20 8.954 20 20 20z"],"hand-point-right":[512,512,[],"f0a4","M512 199.652c0 23.625-20.65 43.826-44.8 43.826h-99.851c16.34 17.048 18.346 49.766-6.299 70.944 14.288 22.829 2.147 53.017-16.45 62.315C353.574 425.878 322.654 448 272 448c-2.746 0-13.276-.203-16-.195-61.971.168-76.894-31.065-123.731-38.315C120.596 407.683 112 397.599 112 385.786V214.261l.002-.001c.011-18.366 10.607-35.889 28.464-43.845 28.886-12.994 95.413-49.038 107.534-77.323 7.797-18.194 21.384-29.084 40-29.092 34.222-.014 57.752 35.098 44.119 66.908-3.583 8.359-8.312 16.67-14.153 24.918H467.2c23.45 0 44.8 20.543 44.8 43.826zM96 200v192c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V200c0-13.255 10.745-24 24-24h48c13.255 0 24 10.745 24 24zM68 368c0-11.046-8.954-20-20-20s-20 8.954-20 20 8.954 20 20 20 20-8.954 20-20z"],"hand-point-up":[384,512,[],"f0a6","M135.652 0c23.625 0 43.826 20.65 43.826 44.8v99.851c17.048-16.34 49.766-18.346 70.944 6.299 22.829-14.288 53.017-2.147 62.315 16.45C361.878 158.426 384 189.346 384 240c0 2.746-.203 13.276-.195 16 .168 61.971-31.065 76.894-38.315 123.731C343.683 391.404 333.599 400 321.786 400H150.261l-.001-.002c-18.366-.011-35.889-10.607-43.845-28.464C93.421 342.648 57.377 276.122 29.092 264 10.897 256.203.008 242.616 0 224c-.014-34.222 35.098-57.752 66.908-44.119 8.359 3.583 16.67 8.312 24.918 14.153V44.8c0-23.45 20.543-44.8 43.826-44.8zM136 416h192c13.255 0 24 10.745 24 24v48c0 13.255-10.745 24-24 24H136c-13.255 0-24-10.745-24-24v-48c0-13.255 10.745-24 24-24zm168 28c-11.046 0-20 8.954-20 20s8.954 20 20 20 20-8.954 20-20-8.954-20-20-20z"],"hand-pointer":[448,512,[],"f25a","M448 240v96c0 3.084-.356 6.159-1.063 9.162l-32 136C410.686 499.23 394.562 512 376 512H168a40.004 40.004 0 0 1-32.35-16.473l-127.997-176c-12.993-17.866-9.043-42.883 8.822-55.876 17.867-12.994 42.884-9.043 55.877 8.823L104 315.992V40c0-22.091 17.908-40 40-40s40 17.909 40 40v200h8v-40c0-22.091 17.908-40 40-40s40 17.909 40 40v40h8v-24c0-22.091 17.908-40 40-40s40 17.909 40 40v24h8c0-22.091 17.908-40 40-40s40 17.909 40 40zm-256 80h-8v96h8v-96zm88 0h-8v96h8v-96zm88 0h-8v96h8v-96z"],"hand-rock":[512,512,[],"f255","M512 128.79c0-26.322-20.861-48.344-47.18-48.783C437.935 79.558 416 101.217 416 128h-8V96.79c0-26.322-20.861-48.344-47.18-48.783C333.935 47.558 312 69.217 312 96v32h-8V80.79c0-26.322-20.861-48.344-47.18-48.783C229.935 31.558 208 53.217 208 80v48h-8V96.79c0-26.322-20.861-48.344-47.18-48.783C125.935 47.558 104 69.217 104 96v136l-8-7.111V176.79c0-26.322-20.861-48.344-47.18-48.783C21.935 127.558 0 149.217 0 176v66.445a95.998 95.998 0 0 0 32.221 71.751l111.668 99.261A47.999 47.999 0 0 1 160 449.333V456c0 13.255 10.745 24 24 24h240c13.255 0 24-10.745 24-24v-2.921a96.01 96.01 0 0 1 7.523-37.254l48.954-116.265A96.002 96.002 0 0 0 512 262.306V128.79z"],"hand-scissors":[512,512,[],"f257","M216 440c0-22.092 17.909-40 40-40v-8h-32c-22.091 0-40-17.908-40-40s17.909-40 40-40h32v-8H48c-26.51 0-48-21.49-48-48s21.49-48 48-48h208v-13.572l-177.551-69.74c-24.674-9.694-36.818-37.555-27.125-62.228 9.693-24.674 37.554-36.817 62.228-27.124l190.342 74.765 24.872-31.09c12.306-15.381 33.978-19.515 51.081-9.741l112 64A40.002 40.002 0 0 1 512 168v240c0 18.562-12.77 34.686-30.838 38.937l-136 32A39.982 39.982 0 0 1 336 480h-80c-22.091 0-40-17.908-40-40z"],"hand-spock":[512,512,[],"f259","M10.872 316.585c15.139-16.086 40.454-16.854 56.543-1.713L128 371.893v-79.405L88.995 120.865c-4.896-21.542 8.598-42.974 30.14-47.87 21.549-4.894 42.975 8.599 47.87 30.141L201.747 256h9.833L164.016 48.966c-4.946-21.531 8.498-42.994 30.028-47.94 21.532-4.95 42.994 8.498 47.94 30.028L293.664 256h15.105l48.425-193.702c5.357-21.432 27.075-34.462 48.507-29.104 21.432 5.358 34.463 27.075 29.104 48.507L391.231 256h11.08l30.768-129.265c5.117-21.491 26.685-34.768 48.177-29.647 21.491 5.117 34.765 26.686 29.647 48.177l-36.292 152.467A96.024 96.024 0 0 0 472 319.967v42.102a96.002 96.002 0 0 1-3.96 27.287l-26.174 88.287C435.825 498.022 417.101 512 395.846 512H179.172a48.002 48.002 0 0 1-32.898-13.046L12.585 373.128c-16.087-15.141-16.853-40.456-1.713-56.543z"],handshake:[640,512,[],"f2b5","M72 112H24c-13.255 0-24 10.745-24 24v208c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24V136c0-13.255-10.745-24-24-24zM48 340c-11.046 0-20-8.954-20-20s8.954-20 20-20 20 8.954 20 20-8.954 20-20 20zm568-228h-48c-13.255 0-24 10.745-24 24v208c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24V136c0-13.255-10.745-24-24-24zm-24 228c-11.046 0-20-8.954-20-20s8.954-20 20-20 20 8.954 20 20-8.954 20-20 20zM485.94 92.67L528 140.74V320h-19.17c.56-14.96-4.38-28.98-14-39.71l-80.92-98.91c2.93-3.2 2.76-8.16-.38-11.16-2.82-2.7-7.08-2.92-10.14-.76-.42.3-60.35 62.93-60.35 62.93l-.2.21c-23.904 26.905-66.127 26.204-89.15-1.42-15.48-18.58-15.29-45.39.45-63.76l66.57-77.67C334.304 73.88 354.534 64 376.7 64h46.05a83.98 83.98 0 0 1 63.19 28.67zm-3.37 197.92c15.46 16.78 12.59 43.83-2.37 57.75-17.711 16.462-42.433 13.004-45.93 9.2 1.653 15.658-21.389 47.249-56.42 44.68-6.325 21.185-32.298 38.909-59.18 29.61-10.22 10.21-25.82 14.97-39.81 14.97-28.69 0-54.92-11.99-72.58-30.8L112 320V135.52l61.36-50.57A71.52 71.52 0 0 1 223.93 64h37.42c16.73 0 32.68 6.84 44.21 18.85l-63.57 74.16c-20.84 24.31-21.09 59.81-.59 84.42 29.375 35.247 83.007 35.853 113.31 1.92L402.82 193l79.75 97.59z"],hashtag:[448,512,[],"f292","M440.667 182.109l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l14.623-81.891C377.123 38.754 371.468 32 363.997 32h-40.632a12 12 0 0 0-11.813 9.891L296.175 128H197.54l14.623-81.891C213.477 38.754 207.822 32 200.35 32h-40.632a12 12 0 0 0-11.813 9.891L132.528 128H53.432a12 12 0 0 0-11.813 9.891l-7.143 40C33.163 185.246 38.818 192 46.289 192h74.81L98.242 320H19.146a12 12 0 0 0-11.813 9.891l-7.143 40C-1.123 377.246 4.532 384 12.003 384h74.81L72.19 465.891C70.877 473.246 76.532 480 84.003 480h40.632a12 12 0 0 0 11.813-9.891L151.826 384h98.634l-14.623 81.891C234.523 473.246 240.178 480 247.65 480h40.632a12 12 0 0 0 11.813-9.891L315.472 384h79.096a12 12 0 0 0 11.813-9.891l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l22.857-128h79.096a12 12 0 0 0 11.813-9.891zM261.889 320h-98.634l22.857-128h98.634l-22.857 128z"],hdd:[576,512,[],"f0a0","M576 304v96c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48v-96c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48zm-48-80a79.557 79.557 0 0 1 30.777 6.165L462.25 85.374A48.003 48.003 0 0 0 422.311 64H153.689a48 48 0 0 0-39.938 21.374L17.223 230.165A79.557 79.557 0 0 1 48 224h480zm-48 96c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32zm-96 0c-17.673 0-32 14.327-32 32s14.327 32 32 32 32-14.327 32-32-14.327-32-32-32z"],heading:[512,512,[],"f1dc","M496 80V48c0-8.837-7.163-16-16-16H320c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h37.621v128H154.379V96H192c8.837 0 16-7.163 16-16V48c0-8.837-7.163-16-16-16H32c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h37.275v320H32c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h160c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-37.621V288H357.62v128H320c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h160c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16h-37.275V96H480c8.837 0 16-7.163 16-16z"],headphones:[512,512,[],"f025","M256 32C114.52 32 0 146.496 0 288v48a32 32 0 0 0 17.689 28.622l14.383 7.191C34.083 431.903 83.421 480 144 480h24c13.255 0 24-10.745 24-24V280c0-13.255-10.745-24-24-24h-24c-31.342 0-59.671 12.879-80 33.627V288c0-105.869 86.131-192 192-192s192 86.131 192 192v1.627C427.671 268.879 399.342 256 368 256h-24c-13.255 0-24 10.745-24 24v176c0 13.255 10.745 24 24 24h24c60.579 0 109.917-48.098 111.928-108.187l14.382-7.191A32 32 0 0 0 512 336v-48c0-141.479-114.496-256-256-256z"],heart:[576,512,[],"f004","M414.9 24C361.8 24 312 65.7 288 89.3 264 65.7 214.2 24 161.1 24 70.3 24 16 76.9 16 165.5c0 72.6 66.8 133.3 69.2 135.4l187 180.8c8.8 8.5 22.8 8.5 31.6 0l186.7-180.2c2.7-2.7 69.5-63.5 69.5-136C560 76.9 505.7 24 414.9 24z"],heartbeat:[576,512,[],"f21e","M47.9 257C31.6 232.7 16 200.5 16 165.5 16 76.9 70.3 24 161.1 24 214.2 24 264 65.7 288 89.3 312 65.7 361.8 24 414.9 24 505.7 24 560 76.9 560 165.5c0 35-15.5 67.2-31.9 91.5H408l-26.4-58.6c-4.7-8.9-17.6-8.5-21.6.7l-53.3 134.6L235.4 120c-3.7-10.6-18.7-10.7-22.6-.2l-48 137.2H47.9zm348 32c-4.5 0-8.6-2.5-10.6-6.4l-12.8-32.5-56.9 142.8c-4.4 9.9-18.7 9.4-22.3-.9l-69.7-209.2-33.6 98.4c-1.7 4.7-6.2 7.8-11.2 7.8H73.4c5.3 5.7-12.8-12 198.9 192.6 8.8 8.5 22.8 8.5 31.6 0 204.3-197.2 191-184 199-192.6h-107z"],history:[512,512,[],"f1da","M504 255.531c.253 136.64-111.18 248.372-247.82 248.468-59.015.042-113.223-20.53-155.822-54.911-11.077-8.94-11.905-25.541-1.839-35.607l11.267-11.267c8.609-8.609 22.353-9.551 31.891-1.984C173.062 425.135 212.781 440 256 440c101.705 0 184-82.311 184-184 0-101.705-82.311-184-184-184-48.814 0-93.149 18.969-126.068 49.932l50.754 50.754c10.08 10.08 2.941 27.314-11.313 27.314H24c-8.837 0-16-7.163-16-16V38.627c0-14.254 17.234-21.393 27.314-11.314l49.372 49.372C129.209 34.136 189.552 8 256 8c136.81 0 247.747 110.78 248 247.531zm-180.912 78.784l9.823-12.63c8.138-10.463 6.253-25.542-4.21-33.679L288 256.349V152c0-13.255-10.745-24-24-24h-16c-13.255 0-24 10.745-24 24v135.651l65.409 50.874c10.463 8.137 25.541 6.253 33.679-4.21z"],home:[576,512,[],"f015","M488 312.7V456c0 13.3-10.7 24-24 24H348c-6.6 0-12-5.4-12-12V356c0-6.6-5.4-12-12-12h-72c-6.6 0-12 5.4-12 12v112c0 6.6-5.4 12-12 12H112c-13.3 0-24-10.7-24-24V312.7c0-3.6 1.6-7 4.4-9.3l188-154.8c4.4-3.6 10.8-3.6 15.3 0l188 154.8c2.7 2.3 4.3 5.7 4.3 9.3zm83.6-60.9L488 182.9V44.4c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12V117l-89.5-73.7c-17.7-14.6-43.3-14.6-61 0L4.4 251.8c-5.1 4.2-5.8 11.8-1.6 16.9l25.5 31c4.2 5.1 11.8 5.8 16.9 1.6l235.2-193.7c4.4-3.6 10.8-3.6 15.3 0l235.2 193.7c5.1 4.2 12.7 3.5 16.9-1.6l25.5-31c4.2-5.2 3.4-12.7-1.7-16.9z"],hospital:[448,512,[],"f0f8","M448 492v20H0v-20c0-6.627 5.373-12 12-12h20V120c0-13.255 10.745-24 24-24h88V24c0-13.255 10.745-24 24-24h112c13.255 0 24 10.745 24 24v72h88c13.255 0 24 10.745 24 24v360h20c6.627 0 12 5.373 12 12zM308 192h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12zm-168 64h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12zm104 128h-40c-6.627 0-12 5.373-12 12v84h64v-84c0-6.627-5.373-12-12-12zm64-96h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12zm-116 12c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40zM182 96h26v26a6 6 0 0 0 6 6h20a6 6 0 0 0 6-6V96h26a6 6 0 0 0 6-6V70a6 6 0 0 0-6-6h-26V38a6 6 0 0 0-6-6h-20a6 6 0 0 0-6 6v26h-26a6 6 0 0 0-6 6v20a6 6 0 0 0 6 6z"],hourglass:[384,512,[],"f254","M360 64c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24 0 90.965 51.016 167.734 120.842 192C75.016 280.266 24 357.035 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24 0-90.965-51.016-167.734-120.842-192C308.984 231.734 360 154.965 360 64z"],"hourglass-end":[384,512,[],"f253","M360 64c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24 0 90.965 51.016 167.734 120.842 192C75.016 280.266 24 357.035 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24 0-90.965-51.016-167.734-120.842-192C308.984 231.734 360 154.965 360 64zM192 208c-57.787 0-104-66.518-104-144h208c0 77.945-46.51 144-104 144z"],"hourglass-half":[384,512,[],"f252","M360 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24 0 90.965 51.016 167.734 120.842 192C75.016 280.266 24 357.035 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24 0-90.965-51.016-167.734-120.842-192C308.984 231.734 360 154.965 360 64c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24zm-75.078 384H99.08c17.059-46.797 52.096-80 92.92-80 40.821 0 75.862 33.196 92.922 80zm.019-256H99.078C91.988 108.548 88 86.748 88 64h208c0 22.805-3.987 44.587-11.059 64z"],"hourglass-start":[384,512,[],"f251","M360 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24 0 90.965 51.016 167.734 120.842 192C75.016 280.266 24 357.035 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24 0-90.965-51.016-167.734-120.842-192C308.984 231.734 360 154.965 360 64c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24zm-64 448H88c0-77.458 46.204-144 104-144 57.786 0 104 66.517 104 144z"],"i-cursor":[256,512,[],"f246","M256 52.048V12.065C256 5.496 250.726.148 244.158.066 211.621-.344 166.469.011 128 37.959 90.266.736 46.979-.114 11.913.114 5.318.157 0 5.519 0 12.114v39.645c0 6.687 5.458 12.078 12.145 11.998C38.111 63.447 96 67.243 96 112.182V224H60c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h36v112c0 44.932-56.075 48.031-83.95 47.959C5.404 447.942 0 453.306 0 459.952v39.983c0 6.569 5.274 11.917 11.842 11.999 32.537.409 77.689.054 116.158-37.894 37.734 37.223 81.021 38.073 116.087 37.845 6.595-.043 11.913-5.405 11.913-12V460.24c0-6.687-5.458-12.078-12.145-11.998C217.889 448.553 160 444.939 160 400V288h36c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-36V112.182c0-44.932 56.075-48.213 83.95-48.142 6.646.018 12.05-5.346 12.05-11.992z"],"id-badge":[384,512,[],"f2c1","M0 464V48C0 21.49 21.49 0 48 0h288c26.51 0 48 21.49 48 48v416c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48zm192-144c53.019 0 96-42.981 96-96s-42.981-96-96-96-96 42.981-96 96 42.981 96 96 96zm94.317 17.474l-22.954-7.173C242.437 344.413 217.802 352 192 352s-50.437-7.587-71.363-21.699l-22.954 7.173C77.644 343.736 64 362.295 64 383.289V424c0 13.255 10.745 24 24 24h208c13.255 0 24-10.745 24-24v-40.711c0-20.994-13.644-39.553-33.683-45.815zM352 52v-8c0-6.627-5.373-12-12-12H44c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h296c6.627 0 12-5.373 12-12z"],"id-card":[512,512,[],"f2c2","M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM160 160c-35.346 0-64 28.654-64 64s28.654 64 64 64 64-28.654 64-64-28.654-64-64-64m79.589 154.53l-28.281-9.427C196.458 314.532 178.856 320 160 320s-36.458-5.468-51.309-14.897L80.41 314.53A24 24 0 0 0 64 337.298V360c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24v-22.702a24 24 0 0 0-16.411-22.768zM448 340v-8c0-6.627-5.373-12-12-12H300c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h136c6.627 0 12-5.373 12-12zm0-64v-8c0-6.627-5.373-12-12-12H300c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h136c6.627 0 12-5.373 12-12zm0-64v-8c0-6.627-5.373-12-12-12H300c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h136c6.627 0 12-5.373 12-12zm32-96v-8c0-6.627-5.373-12-12-12H44c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h424c6.627 0 12-5.373 12-12z"],image:[512,512,[],"f03e","M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"],images:[576,512,[],"f302","M480 416v16c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v208c0 44.112 35.888 80 80 80h336zm96-80V80c0-26.51-21.49-48-48-48H144c-26.51 0-48 21.49-48 48v256c0 26.51 21.49 48 48 48h384c26.51 0 48-21.49 48-48zM256 128c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-96 144l55.515-55.515c4.686-4.686 12.284-4.686 16.971 0L272 256l135.515-135.515c4.686-4.686 12.284-4.686 16.971 0L512 208v112H160v-48z"],inbox:[576,512,[],"f01c","M567.938 243.908L462.25 85.374A48.003 48.003 0 0 0 422.311 64H153.689a48 48 0 0 0-39.938 21.374L8.062 243.908A47.994 47.994 0 0 0 0 270.533V400c0 26.51 21.49 48 48 48h480c26.51 0 48-21.49 48-48V270.533a47.994 47.994 0 0 0-8.062-26.625zM162.252 128h251.497l85.333 128H376l-32 64H232l-32-64H76.918l85.334-128z"],indent:[448,512,[],"f03c","M0 84V44c0-8.837 7.163-16 16-16h416c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16zm176 144h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H176c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zM16 484h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm160-128h256c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H176c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm-52.687-111.313l-96-95.984C17.266 138.652 0 145.776 0 160.016v191.975c0 14.329 17.325 21.304 27.313 11.313l96-95.992c6.249-6.247 6.249-16.377 0-22.625z"],industry:[512,512,[],"f275","M475.115 163.781L336 252.309v-68.28c0-18.916-20.931-30.399-36.885-20.248L160 252.309V56c0-13.255-10.745-24-24-24H24C10.745 32 0 42.745 0 56v400c0 13.255 10.745 24 24 24h464c13.255 0 24-10.745 24-24V184.029c0-18.917-20.931-30.399-36.885-20.248z"],info:[192,512,[],"f129","M20 424.229h20V279.771H20c-11.046 0-20-8.954-20-20V212c0-11.046 8.954-20 20-20h112c11.046 0 20 8.954 20 20v212.229h20c11.046 0 20 8.954 20 20V492c0 11.046-8.954 20-20 20H20c-11.046 0-20-8.954-20-20v-47.771c0-11.046 8.954-20 20-20zM96 0C56.235 0 24 32.235 24 72s32.235 72 72 72 72-32.235 72-72S135.764 0 96 0z"],"info-circle":[512,512,[],"f05a","M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 110c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"],italic:[320,512,[],"f033","M204.758 416h-33.849l62.092-320h40.725a16 16 0 0 0 15.704-12.937l6.242-32C297.599 41.184 290.034 32 279.968 32H120.235a16 16 0 0 0-15.704 12.937l-6.242 32C96.362 86.816 103.927 96 113.993 96h33.846l-62.09 320H46.278a16 16 0 0 0-15.704 12.935l-6.245 32C22.402 470.815 29.967 480 40.034 480h158.479a16 16 0 0 0 15.704-12.935l6.245-32c1.927-9.88-5.638-19.065-15.704-19.065z"],key:[512,512,[],"f084","M512 176.001C512 273.203 433.202 352 336 352c-11.22 0-22.19-1.062-32.827-3.069l-24.012 27.014A23.999 23.999 0 0 1 261.223 384H224v40c0 13.255-10.745 24-24 24h-40v40c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-78.059c0-6.365 2.529-12.47 7.029-16.971l161.802-161.802C163.108 213.814 160 195.271 160 176 160 78.798 238.797.001 335.999 0 433.488-.001 512 78.511 512 176.001zM336 128c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48-48 21.49-48 48z"],keyboard:[576,512,[],"f11c","M528 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM128 180v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm288 0v-40c0-6.627-5.373-12-12-12H172c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z"],language:[640,512,[],"f1ab","M304 416H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h280v320zm-120.676-72.622A12 12 0 0 0 194.839 352h22.863c8.22 0 14.007-8.078 11.362-15.861L171.61 167.085a12 12 0 0 0-11.362-8.139h-32.489a12.001 12.001 0 0 0-11.362 8.139L58.942 336.139C56.297 343.922 62.084 352 70.304 352h22.805a12 12 0 0 0 11.535-8.693l9.118-31.807h60.211l9.351 31.878zm-39.051-140.42s4.32 21.061 7.83 33.21l10.8 37.531h-38.07l11.07-37.531c3.51-12.15 7.83-33.21 7.83-33.21h.54zM616 416H336V96h280c13.255 0 24 10.745 24 24v272c0 13.255-10.745 24-24 24zm-36-228h-64v-16c0-6.627-5.373-12-12-12h-16c-6.627 0-12 5.373-12 12v16h-64c-6.627 0-12 5.373-12 12v16c0 6.627 5.373 12 12 12h114.106c-6.263 14.299-16.518 28.972-30.023 43.206-6.56-6.898-12.397-13.91-17.365-20.933-3.639-5.144-10.585-6.675-15.995-3.446l-7.28 4.346-6.498 3.879c-5.956 3.556-7.693 11.421-3.735 17.117 6.065 8.729 13.098 17.336 20.984 25.726-8.122 6.226-16.841 12.244-26.103 17.964-5.521 3.41-7.381 10.556-4.162 16.19l7.941 13.896c3.362 5.883 10.935 7.826 16.706 4.276 12.732-7.831 24.571-16.175 35.443-24.891 10.917 8.761 22.766 17.102 35.396 24.881 5.774 3.556 13.353 1.618 16.717-4.27l7.944-13.903c3.213-5.623 1.37-12.76-4.135-16.171a312.737 312.737 0 0 1-26.06-18.019c21.024-22.425 35.768-46.289 42.713-69.85H580c6.627 0 12-5.373 12-12v-16c0-6.625-5.373-11.998-12-11.998z"],laptop:[640,512,[],"f109","M512 64v256H128V64h384m16-64H112C85.5 0 64 21.5 64 48v288c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm100 416H389.5c-3 0-5.5 2.1-5.9 5.1C381.2 436.3 368 448 352 448h-64c-16 0-29.2-11.7-31.6-26.9-.5-2.9-3-5.1-5.9-5.1H12c-6.6 0-12 5.4-12 12v36c0 26.5 21.5 48 48 48h544c26.5 0 48-21.5 48-48v-36c0-6.6-5.4-12-12-12z"],leaf:[576,512,[],"f06c","M395.4 420.8c-43.4 21.6-91.9 34.4-140.8 34.4-82.2 0-151.1-40.1-151.1-40.1-16.1 0-35.4 64.9-63.3 64.9-27 0-40.2-24-40.2-38.5 0-33.1 63.6-58.9 63.6-77.3 0 0-12.5-21.2-12.5-59.2 0-101.2 81.3-173.4 172.6-203.3 65.9-21.6 206 3.5 250.7-38.5C492.1 47 500.8 32 527.8 32c36.3 0 48.2 93.2 48.2 120.3 0 110.9-54.5 206.5-180.6 268.5zm-254.3-75.6c63.5-89.9 144.5-128.8 257.7-120 8.8.7 16.5-5.9 17.2-14.7.7-8.8-5.9-16.5-14.7-17.2-124-9.6-215.9 33.9-286.3 133.5-5.1 7.2-3.4 17.2 3.8 22.3 7.2 5.1 17.2 3.4 22.3-3.9z"],lemon:[512,512,[],"f094","M489.038 22.963C465.944-.13 434.648-5.93 413.947 6.129c-58.906 34.312-181.25-53.077-321.073 86.746S40.441 355.041 6.129 413.945c-12.059 20.702-6.26 51.999 16.833 75.093 23.095 23.095 54.392 28.891 75.095 16.832 58.901-34.31 181.246 53.079 321.068-86.743S471.56 156.96 505.871 98.056c12.059-20.702 6.261-51.999-16.833-75.093zM243.881 95.522c-58.189 14.547-133.808 90.155-148.358 148.358-1.817 7.27-8.342 12.124-15.511 12.124-1.284 0-2.59-.156-3.893-.481-8.572-2.144-13.784-10.83-11.642-19.403C81.901 166.427 166.316 81.93 236.119 64.478c8.575-2.143 17.261 3.069 19.403 11.642s-3.069 17.259-11.641 19.402z"],"level-down-alt":[320,512,[],"f3be","M313.553 392.331L209.587 504.334c-9.485 10.214-25.676 10.229-35.174 0L70.438 392.331C56.232 377.031 67.062 352 88.025 352H152V80H68.024a11.996 11.996 0 0 1-8.485-3.515l-56-56C-4.021 12.926 1.333 0 12.024 0H208c13.255 0 24 10.745 24 24v328h63.966c20.878 0 31.851 24.969 17.587 40.331z"],"level-up-alt":[320,512,[],"f3bf","M313.553 119.669L209.587 7.666c-9.485-10.214-25.676-10.229-35.174 0L70.438 119.669C56.232 134.969 67.062 160 88.025 160H152v272H68.024a11.996 11.996 0 0 0-8.485 3.515l-56 56C-4.021 499.074 1.333 512 12.024 512H208c13.255 0 24-10.745 24-24V160h63.966c20.878 0 31.851-24.969 17.587-40.331z"],"life-ring":[512,512,[],"f1cd","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm173.696 119.559l-63.399 63.399c-10.987-18.559-26.67-34.252-45.255-45.255l63.399-63.399a218.396 218.396 0 0 1 45.255 45.255zM256 352c-53.019 0-96-42.981-96-96s42.981-96 96-96 96 42.981 96 96-42.981 96-96 96zM127.559 82.304l63.399 63.399c-18.559 10.987-34.252 26.67-45.255 45.255l-63.399-63.399a218.372 218.372 0 0 1 45.255-45.255zM82.304 384.441l63.399-63.399c10.987 18.559 26.67 34.252 45.255 45.255l-63.399 63.399a218.396 218.396 0 0 1-45.255-45.255zm302.137 45.255l-63.399-63.399c18.559-10.987 34.252-26.67 45.255-45.255l63.399 63.399a218.403 218.403 0 0 1-45.255 45.255z"],lightbulb:[384,512,[],"f0eb","M272 428v28c0 10.449-6.68 19.334-16 22.629V488c0 13.255-10.745 24-24 24h-80c-13.255 0-24-10.745-24-24v-9.371c-9.32-3.295-16-12.18-16-22.629v-28c0-6.627 5.373-12 12-12h136c6.627 0 12 5.373 12 12zm-143.107-44c-9.907 0-18.826-6.078-22.376-15.327C67.697 267.541 16 277.731 16 176 16 78.803 94.805 0 192 0s176 78.803 176 176c0 101.731-51.697 91.541-90.516 192.673-3.55 9.249-12.47 15.327-22.376 15.327H128.893zM112 176c0-44.112 35.888-80 80-80 8.837 0 16-7.164 16-16s-7.163-16-16-16c-61.757 0-112 50.243-112 112 0 8.836 7.164 16 16 16s16-7.164 16-16z"],link:[512,512,[],"f0c1","M326.612 185.391c59.747 59.809 58.927 155.698.36 214.59-.11.12-.24.25-.36.37l-67.2 67.2c-59.27 59.27-155.699 59.262-214.96 0-59.27-59.26-59.27-155.7 0-214.96l37.106-37.106c9.84-9.84 26.786-3.3 27.294 10.606.648 17.722 3.826 35.527 9.69 52.721 1.986 5.822.567 12.262-3.783 16.612l-13.087 13.087c-28.026 28.026-28.905 73.66-1.155 101.96 28.024 28.579 74.086 28.749 102.325.51l67.2-67.19c28.191-28.191 28.073-73.757 0-101.83-3.701-3.694-7.429-6.564-10.341-8.569a16.037 16.037 0 0 1-6.947-12.606c-.396-10.567 3.348-21.456 11.698-29.806l21.054-21.055c5.521-5.521 14.182-6.199 20.584-1.731a152.482 152.482 0 0 1 20.522 17.197zM467.547 44.449c-59.261-59.262-155.69-59.27-214.96 0l-67.2 67.2c-.12.12-.25.25-.36.37-58.566 58.892-59.387 154.781.36 214.59a152.454 152.454 0 0 0 20.521 17.196c6.402 4.468 15.064 3.789 20.584-1.731l21.054-21.055c8.35-8.35 12.094-19.239 11.698-29.806a16.037 16.037 0 0 0-6.947-12.606c-2.912-2.005-6.64-4.875-10.341-8.569-28.073-28.073-28.191-73.639 0-101.83l67.2-67.19c28.239-28.239 74.3-28.069 102.325.51 27.75 28.3 26.872 73.934-1.155 101.96l-13.087 13.087c-4.35 4.35-5.769 10.79-3.783 16.612 5.864 17.194 9.042 34.999 9.69 52.721.509 13.906 17.454 20.446 27.294 10.606l37.106-37.106c59.271-59.259 59.271-155.699.001-214.959z"],"lira-sign":[384,512,[],"f195","M371.994 256h-48.019C317.64 256 312 260.912 312 267.246 312 368 230.179 416 144 416V256.781l134.603-29.912A12 12 0 0 0 288 215.155v-40.976c0-7.677-7.109-13.38-14.603-11.714L144 191.219V160.78l134.603-29.912A12 12 0 0 0 288 119.154V78.179c0-7.677-7.109-13.38-14.603-11.714L144 95.219V44c0-6.627-5.373-12-12-12H76c-6.627 0-12 5.373-12 12v68.997L9.397 125.131A12 12 0 0 0 0 136.845v40.976c0 7.677 7.109 13.38 14.603 11.714L64 178.558v30.439L9.397 221.131A12 12 0 0 0 0 232.845v40.976c0 7.677 7.109 13.38 14.603 11.714L64 274.558V468c0 6.627 5.373 12 12 12h79.583c134.091 0 223.255-77.834 228.408-211.592.261-6.782-5.211-12.408-11.997-12.408z"],list:[512,512,[],"f03a","M128 116V76c0-8.837 7.163-16 16-16h352c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H144c-8.837 0-16-7.163-16-16zm16 176h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zM16 144h64c8.837 0 16-7.163 16-16V64c0-8.837-7.163-16-16-16H16C7.163 48 0 55.163 0 64v64c0 8.837 7.163 16 16 16zm0 160h64c8.837 0 16-7.163 16-16v-64c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v64c0 8.837 7.163 16 16 16zm0 160h64c8.837 0 16-7.163 16-16v-64c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v64c0 8.837 7.163 16 16 16z"],"list-alt":[512,512,[],"f022","M464 480H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v352c0 26.51-21.49 48-48 48zM128 120c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zm0 96c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zm0 96c-22.091 0-40 17.909-40 40s17.909 40 40 40 40-17.909 40-40-17.909-40-40-40zm288-136v-32c0-6.627-5.373-12-12-12H204c-6.627 0-12 5.373-12 12v32c0 6.627 5.373 12 12 12h200c6.627 0 12-5.373 12-12zm0 96v-32c0-6.627-5.373-12-12-12H204c-6.627 0-12 5.373-12 12v32c0 6.627 5.373 12 12 12h200c6.627 0 12-5.373 12-12zm0 96v-32c0-6.627-5.373-12-12-12H204c-6.627 0-12 5.373-12 12v32c0 6.627 5.373 12 12 12h200c6.627 0 12-5.373 12-12z"],"list-ol":[512,512,[],"f0cb","M3.263 139.527c0-7.477 3.917-11.572 11.573-11.572h15.131V88.078c0-5.163.534-10.503.534-10.503h-.356s-1.779 2.67-2.848 3.738c-4.451 4.273-10.504 4.451-15.666-1.068l-5.518-6.231c-5.342-5.341-4.984-11.216.534-16.379l21.72-19.938C32.815 33.602 36.732 32 42.785 32H54.89c7.656 0 11.749 3.916 11.749 11.572v84.384h15.488c7.655 0 11.572 4.094 11.572 11.572v8.901c0 7.477-3.917 11.572-11.572 11.572H14.836c-7.656 0-11.573-4.095-11.573-11.572v-8.902zM2.211 304.591c0-47.278 50.955-56.383 50.955-69.165 0-7.18-5.954-8.755-9.28-8.755-3.153 0-6.479 1.051-9.455 3.852-5.079 4.903-10.507 7.004-16.111 2.451l-8.579-6.829c-5.779-4.553-7.18-9.805-2.803-15.409C13.592 201.981 26.025 192 47.387 192c19.437 0 44.476 10.506 44.476 39.573 0 38.347-46.753 46.402-48.679 56.909h39.049c7.529 0 11.557 4.027 11.557 11.382v8.755c0 7.354-4.028 11.382-11.557 11.382h-67.94c-7.005 0-12.083-4.028-12.083-11.382v-4.028zM5.654 454.61l5.603-9.28c3.853-6.654 9.105-7.004 15.584-3.152 4.903 2.101 9.63 3.152 14.359 3.152 10.155 0 14.358-3.502 14.358-8.23 0-6.654-5.604-9.106-15.934-9.106h-4.728c-5.954 0-9.28-2.101-12.258-7.88l-1.05-1.926c-2.451-4.728-1.226-9.806 2.801-14.884l5.604-7.004c6.829-8.405 12.257-13.483 12.257-13.483v-.35s-4.203 1.051-12.608 1.051H16.685c-7.53 0-11.383-4.028-11.383-11.382v-8.755c0-7.53 3.853-11.382 11.383-11.382h58.484c7.529 0 11.382 4.027 11.382 11.382v3.327c0 5.778-1.401 9.806-5.079 14.183l-17.509 20.137c19.611 5.078 28.716 20.487 28.716 34.845 0 21.363-14.358 44.126-48.503 44.126-16.636 0-28.192-4.728-35.896-9.455-5.779-4.202-6.304-9.805-2.626-15.934zM144 132h352c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"],"list-ul":[512,512,[],"f0ca","M96 96c0 26.51-21.49 48-48 48S0 122.51 0 96s21.49-48 48-48 48 21.49 48 48zM48 208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm0 160c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm96-236h352c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h352c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H144c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"],"location-arrow":[512,512,[],"f124","M443.683 4.529L27.818 196.418C-18.702 217.889-3.39 288 47.933 288H224v175.993c0 51.727 70.161 66.526 91.582 20.115L507.38 68.225c18.905-40.961-23.752-82.133-63.697-63.696z"],lock:[448,512,[],"f023","M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"],"lock-open":[576,512,[],"f3c1","M423.5 0C339.5.3 272 69.5 272 153.5V224H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48h-48v-71.1c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v80c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-80C576 68 507.5-.3 423.5 0z"],"long-arrow-alt-down":[256,512,[],"f309","M168 345.941V44c0-6.627-5.373-12-12-12h-56c-6.627 0-12 5.373-12 12v301.941H41.941c-21.382 0-32.09 25.851-16.971 40.971l86.059 86.059c9.373 9.373 24.569 9.373 33.941 0l86.059-86.059c15.119-15.119 4.411-40.971-16.971-40.971H168z"],"long-arrow-alt-left":[448,512,[],"f30a","M134.059 296H436c6.627 0 12-5.373 12-12v-56c0-6.627-5.373-12-12-12H134.059v-46.059c0-21.382-25.851-32.09-40.971-16.971L7.029 239.029c-9.373 9.373-9.373 24.569 0 33.941l86.059 86.059c15.119 15.119 40.971 4.411 40.971-16.971V296z"],"long-arrow-alt-right":[448,512,[],"f30b","M313.941 216H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h301.941v46.059c0 21.382 25.851 32.09 40.971 16.971l86.059-86.059c9.373-9.373 9.373-24.569 0-33.941l-86.059-86.059c-15.119-15.119-40.971-4.411-40.971 16.971V216z"],"long-arrow-alt-up":[256,512,[],"f30c","M88 166.059V468c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12V166.059h46.059c21.382 0 32.09-25.851 16.971-40.971l-86.059-86.059c-9.373-9.373-24.569-9.373-33.941 0l-86.059 86.059c-15.119 15.119-4.411 40.971 16.971 40.971H88z"],"low-vision":[576,512,[],"f2a8","M569.344 231.631C512.96 135.949 407.81 72 288 72c-28.468 0-56.102 3.619-82.451 10.409L152.778 10.24c-7.601-10.858-22.564-13.5-33.423-5.9l-13.114 9.178c-10.86 7.601-13.502 22.566-5.9 33.426l43.131 58.395C89.449 131.73 40.228 174.683 6.682 231.581c-.01.017-.023.033-.034.05-8.765 14.875-8.964 33.528 0 48.739 38.5 65.332 99.742 115.862 172.859 141.349L55.316 244.302A272.194 272.194 0 0 1 83.61 208.39l119.4 170.58h.01l40.63 58.04a330.055 330.055 0 0 0 78.94 1.17l-189.98-271.4a277.628 277.628 0 0 1 38.777-21.563l251.836 356.544c7.601 10.858 22.564 13.499 33.423 5.9l13.114-9.178c10.86-7.601 13.502-22.567 5.9-33.426l-43.12-58.377-.007-.009c57.161-27.978 104.835-72.04 136.81-126.301a47.938 47.938 0 0 0 .001-48.739zM390.026 345.94l-19.066-27.23c24.682-32.567 27.711-76.353 8.8-111.68v.03c0 23.65-19.17 42.82-42.82 42.82-23.828 0-42.82-19.349-42.82-42.82 0-23.65 19.17-42.82 42.82-42.82h.03c-24.75-13.249-53.522-15.643-79.51-7.68l-19.068-27.237C253.758 123.306 270.488 120 288 120c75.162 0 136 60.826 136 136 0 34.504-12.833 65.975-33.974 89.94z"],magic:[512,512,[],"f0d0","M101.1 505L7 410.9c-9.4-9.4-9.4-24.6 0-33.9L377 7c9.4-9.4 24.6-9.4 33.9 0l94.1 94.1c9.4 9.4 9.4 24.6 0 33.9L135 505c-9.3 9.3-24.5 9.3-33.9 0zM304 159.2l48.8 48.8 89.9-89.9-48.8-48.8-89.9 89.9zM138.9 39.3l-11.7 23.8-26.2 3.8c-4.7.7-6.6 6.5-3.2 9.8l19 18.5-4.5 26.1c-.8 4.7 4.1 8.3 8.3 6.1L144 115l23.4 12.3c4.2 2.2 9.1-1.4 8.3-6.1l-4.5-26.1 19-18.5c3.4-3.3 1.5-9.1-3.2-9.8L160.8 63l-11.7-23.8c-2-4.1-8.1-4.1-10.2.1zm97.7-20.7l-7.8 15.8-17.5 2.6c-3.1.5-4.4 4.3-2.1 6.5l12.6 12.3-3 17.4c-.5 3.1 2.8 5.5 5.6 4L240 69l15.6 8.2c2.8 1.5 6.1-.9 5.6-4l-3-17.4 12.6-12.3c2.3-2.2 1-6.1-2.1-6.5l-17.5-2.5-7.8-15.8c-1.4-3-5.4-3-6.8-.1zm-192 0l-7.8 15.8L19.3 37c-3.1.5-4.4 4.3-2.1 6.5l12.6 12.3-3 17.4c-.5 3.1 2.8 5.5 5.6 4L48 69l15.6 8.2c2.8 1.5 6.1-.9 5.6-4l-3-17.4 12.6-12.3c2.3-2.2 1-6.1-2.1-6.5l-17.5-2.5-7.8-15.8c-1.4-3-5.4-3-6.8-.1zm416 223.5l-7.8 15.8-17.5 2.5c-3.1.5-4.4 4.3-2.1 6.5l12.6 12.3-3 17.4c-.5 3.1 2.8 5.5 5.6 4l15.6-8.2 15.6 8.2c2.8 1.5 6.1-.9 5.6-4l-3-17.4 12.6-12.3c2.3-2.2 1-6.1-2.1-6.5l-17.5-2.5-7.8-15.8c-1.4-2.8-5.4-2.8-6.8 0z"],magnet:[512,512,[],"f076","M164.1 160H12c-6.6 0-12-5.4-12-12V68c0-19.9 16.1-36 36-36h104c19.9 0 36 16.1 36 36v80c.1 6.6-5.3 12-11.9 12zm348-12V67.9c0-19.9-16.1-36-36-36h-104c-19.9 0-36 16.1-36 36v80c0 6.6 5.4 12 12 12h152c6.6.1 12-5.3 12-11.9zm-164 44c-6.6 0-12 5.4-12 12v52c0 128.1-160 127.9-160 0v-52c0-6.6-5.4-12-12-12h-152c-6.7 0-12 5.4-12 12.1.1 21.4.6 40.3 0 53.3C.1 408 136.3 504 256.9 504 377.5 504 512 408 512 257.3c-.6-12.8-.2-33 0-53.2 0-6.7-5.3-12.1-12-12.1H348.1z"],male:[192,512,[],"f183","M96 0c35.346 0 64 28.654 64 64s-28.654 64-64 64-64-28.654-64-64S60.654 0 96 0m48 144h-11.36c-22.711 10.443-49.59 10.894-73.28 0H48c-26.51 0-48 21.49-48 48v136c0 13.255 10.745 24 24 24h16v136c0 13.255 10.745 24 24 24h64c13.255 0 24-10.745 24-24V352h16c13.255 0 24-10.745 24-24V192c0-26.51-21.49-48-48-48z"],map:[576,512,[],"f279","M576 56.015v335.97a23.998 23.998 0 0 1-13.267 21.466l-128 64C418.948 485.344 400 473.992 400 455.985v-335.97a23.998 23.998 0 0 1 13.267-21.466l128-64C557.052 26.656 576 38.008 576 56.015zm-206.253 42.07l-144-64c-15.751-7-33.747 4.461-33.747 21.932v335.967a24 24 0 0 0 14.253 21.931l144 64c15.751 7 33.747-4.461 33.747-21.931V120.017a24 24 0 0 0-14.253-21.932zm-228.48-63.536l-128 63.985A23.998 23.998 0 0 0 0 120v335.985c0 18.007 18.948 29.359 34.733 21.466l128-63.985A23.998 23.998 0 0 0 176 392V56.015c0-18.007-18.948-29.359-34.733-21.466z"],"map-marker":[384,512,[],"f041","M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0z"],"map-marker-alt":[384,512,[],"f3c5","M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z"],"map-pin":[320,512,[],"f276","M192 300.813v172.82l-22.015 33.023c-4.75 7.125-15.219 7.125-19.969 0L128 473.633v-172.82a162.221 162.221 0 0 0 64 0zM160 0c79.529 0 144 64.471 144 144s-64.471 144-144 144S16 223.529 16 144 80.471 0 160 0M80 136c0-39.701 32.299-72 72-72a8 8 0 0 0 0-16c-48.523 0-88 39.477-88 88a8 8 0 0 0 16 0z"],"map-signs":[512,512,[],"f277","M487.515 104.485L439.03 152.97a23.998 23.998 0 0 1-16.97 7.029H56c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h160v-8c0-13.255 10.745-24 24-24h32c13.255 0 24 10.745 24 24v8h126.059a24 24 0 0 1 16.97 7.029l48.485 48.485c4.687 4.687 4.687 12.285.001 16.971zM216 368v120c0 13.255 10.745 24 24 24h32c13.255 0 24-10.745 24-24V368h-80zm240-144H296v-48h-80v48H89.941a24 24 0 0 0-16.97 7.029l-48.485 48.485c-4.686 4.686-4.686 12.284 0 16.971l48.485 48.485a23.998 23.998 0 0 0 16.97 7.029H456c13.255 0 24-10.745 24-24v-80C480 234.745 469.255 224 456 224z"],mars:[384,512,[],"f222","M372 64h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-80.7 80.7c-22.2-14-48.5-22.1-76.7-22.1C64.5 160 0 224.5 0 304s64.5 144 144 144 144-64.5 144-144c0-28.2-8.1-54.5-22.1-76.7l80.7-80.7 16.9 16.9c7.6 7.6 20.5 2.2 20.5-8.5V76c0-6.6-5.4-12-12-12zM144 384c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],"mars-double":[512,512,[],"f227","M340 0h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-48.7 48.7C198.5 72.1 172.2 64 144 64 64.5 64 0 128.5 0 208s64.5 144 144 144 144-64.5 144-144c0-28.2-8.1-54.5-22.1-76.7l48.7-48.7 16.9 16.9c2.4 2.4 5.5 3.5 8.4 3.5 6.2 0 12.1-4.8 12.1-12V12c0-6.6-5.4-12-12-12zM144 288c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80zm356-128.1h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-48.7 48.7c-18.2-11.4-39-18.9-61.5-21.3-2.1 21.8-8.2 43.3-18.4 63.3 1.1 0 2.2-.1 3.2-.1 44.1 0 80 35.9 80 80s-35.9 80-80 80-80-35.9-80-80c0-1.1 0-2.2.1-3.2-20 10.2-41.5 16.4-63.3 18.4C168.4 455.6 229.6 512 304 512c79.5 0 144-64.5 144-144 0-28.2-8.1-54.5-22.1-76.7l48.7-48.7 16.9 16.9c2.4 2.4 5.4 3.5 8.4 3.5 6.2 0 12.1-4.8 12.1-12v-79c0-6.7-5.4-12.1-12-12.1z"],"mars-stroke":[384,512,[],"f229","M372 64h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-17.5 17.5-14.1-14.1c-4.7-4.7-12.3-4.7-17 0L224.5 133c-4.7 4.7-4.7 12.3 0 17l14.1 14.1-18 18c-22.2-14-48.5-22.1-76.7-22.1C64.5 160 0 224.5 0 304s64.5 144 144 144 144-64.5 144-144c0-28.2-8.1-54.5-22.1-76.7l18-18 14.1 14.1c4.7 4.7 12.3 4.7 17 0l28.3-28.3c4.7-4.7 4.7-12.3 0-17L329.2 164l17.5-17.5 16.9 16.9c7.6 7.6 20.5 2.2 20.5-8.5V76c-.1-6.6-5.5-12-12.1-12zM144 384c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],"mars-stroke-h":[480,512,[],"f22b","M476.2 247.5l-55.9-55.9c-7.6-7.6-20.5-2.2-20.5 8.5V224H376v-20c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v20h-27.6c-5.8-25.6-18.7-49.9-38.6-69.8C189.6 98 98.4 98 42.2 154.2c-56.2 56.2-56.2 147.4 0 203.6 56.2 56.2 147.4 56.2 203.6 0 19.9-19.9 32.8-44.2 38.6-69.8H312v20c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-20h23.9v23.9c0 10.7 12.9 16 20.5 8.5l55.9-55.9c4.6-4.7 4.6-12.3-.1-17zm-275.6 65.1c-31.2 31.2-81.9 31.2-113.1 0-31.2-31.2-31.2-81.9 0-113.1 31.2-31.2 81.9-31.2 113.1 0 31.2 31.1 31.2 81.9 0 113.1z"],"mars-stroke-v":[288,512,[],"f22a","M245.8 234.2c-19.9-19.9-44.2-32.8-69.8-38.6v-25.4h20c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-20V81.4h23.9c10.7 0 16-12.9 8.5-20.5L152.5 5.1c-4.7-4.7-12.3-4.7-17 0L79.6 61c-7.6 7.6-2.2 20.5 8.5 20.5H112v24.7H92c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h20v25.4c-25.6 5.8-49.9 18.7-69.8 38.6-56.2 56.2-56.2 147.4 0 203.6 56.2 56.2 147.4 56.2 203.6 0 56.3-56.2 56.3-147.4 0-203.6zm-45.2 158.4c-31.2 31.2-81.9 31.2-113.1 0-31.2-31.2-31.2-81.9 0-113.1 31.2-31.2 81.9-31.2 113.1 0 31.2 31.1 31.2 81.9 0 113.1z"],medkit:[512,512,[],"f0fa","M96 480h320V128h-32V80c0-26.51-21.49-48-48-48H176c-26.51 0-48 21.49-48 48v48H96v352zm96-384h128v32H192V96zm320 80v256c0 26.51-21.49 48-48 48h-16V128h16c26.51 0 48 21.49 48 48zM64 480H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v352zm288-208v32c0 8.837-7.163 16-16 16h-48v48c0 8.837-7.163 16-16 16h-32c-8.837 0-16-7.163-16-16v-48h-48c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h48v-48c0-8.837 7.163-16 16-16h32c8.837 0 16 7.163 16 16v48h48c8.837 0 16 7.163 16 16z"],meh:[512,512,[],"f11a","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-396-64c0 37.497 30.503 68 68 68s68-30.503 68-68-30.503-68-68-68-68 30.503-68 68zm160.5 0c0 37.221 30.279 67.5 67.5 67.5s67.5-30.279 67.5-67.5-30.279-67.5-67.5-67.5-67.5 30.279-67.5 67.5zm67.5-48a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 288 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48zm-160 0a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 128 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48zm160 208H176c-21.178 0-21.169 32 0 32h160c21.178 0 21.169-32 0-32z"],mercury:[288,512,[],"f223","M288 208c0-44.2-19.9-83.7-51.2-110.1 2.5-1.8 4.9-3.8 7.2-5.8 24.7-21.2 39.8-48.8 43.2-78.8.9-7.1-4.7-13.3-11.9-13.3h-40.5C229 0 224.1 4.1 223 9.8c-2.4 12.5-9.6 24.3-20.7 33.8C187 56.8 166.3 64 144 64s-43-7.2-58.4-20.4C74.5 34.1 67.4 22.3 64.9 9.8 63.8 4.1 58.9 0 53.2 0H12.7C5.5 0-.1 6.2.8 13.3 4.2 43.4 19.2 71 44 92.2c2.3 2 4.7 3.9 7.2 5.8C19.9 124.3 0 163.8 0 208c0 68.5 47.9 125.9 112 140.4V400H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v36c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-36h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-51.6c64.1-14.5 112-71.9 112-140.4zm-224 0c0-44.1 35.9-80 80-80s80 35.9 80 80-35.9 80-80 80-80-35.9-80-80z"],microchip:[512,512,[],"f2db","M416 48v416c0 26.51-21.49 48-48 48H144c-26.51 0-48-21.49-48-48V48c0-26.51 21.49-48 48-48h224c26.51 0 48 21.49 48 48zm96 58v12a6 6 0 0 1-6 6h-18v6a6 6 0 0 1-6 6h-42V88h42a6 6 0 0 1 6 6v6h18a6 6 0 0 1 6 6zm0 96v12a6 6 0 0 1-6 6h-18v6a6 6 0 0 1-6 6h-42v-48h42a6 6 0 0 1 6 6v6h18a6 6 0 0 1 6 6zm0 96v12a6 6 0 0 1-6 6h-18v6a6 6 0 0 1-6 6h-42v-48h42a6 6 0 0 1 6 6v6h18a6 6 0 0 1 6 6zm0 96v12a6 6 0 0 1-6 6h-18v6a6 6 0 0 1-6 6h-42v-48h42a6 6 0 0 1 6 6v6h18a6 6 0 0 1 6 6zM30 376h42v48H30a6 6 0 0 1-6-6v-6H6a6 6 0 0 1-6-6v-12a6 6 0 0 1 6-6h18v-6a6 6 0 0 1 6-6zm0-96h42v48H30a6 6 0 0 1-6-6v-6H6a6 6 0 0 1-6-6v-12a6 6 0 0 1 6-6h18v-6a6 6 0 0 1 6-6zm0-96h42v48H30a6 6 0 0 1-6-6v-6H6a6 6 0 0 1-6-6v-12a6 6 0 0 1 6-6h18v-6a6 6 0 0 1 6-6zm0-96h42v48H30a6 6 0 0 1-6-6v-6H6a6 6 0 0 1-6-6v-12a6 6 0 0 1 6-6h18v-6a6 6 0 0 1 6-6z"],microphone:[384,512,[],"f130","M96 256V96c0-53.019 42.981-96 96-96s96 42.981 96 96v160c0 53.019-42.981 96-96 96s-96-42.981-96-96zm252-56h-24c-6.627 0-12 5.373-12 12v42.68c0 66.217-53.082 120.938-119.298 121.318C126.213 376.38 72 322.402 72 256v-44c0-6.627-5.373-12-12-12H36c-6.627 0-12 5.373-12 12v44c0 84.488 62.693 154.597 144 166.278V468h-68c-6.627 0-12 5.373-12 12v20c0 6.627 5.373 12 12 12h184c6.627 0 12-5.373 12-12v-20c0-6.627-5.373-12-12-12h-68v-45.722c81.307-11.681 144-81.79 144-166.278v-44c0-6.627-5.373-12-12-12z"],"microphone-slash":[512,512,[],"f131","M421.45 285.195L376 239.746V212c0-6.627 5.373-12 12-12h24c6.627 0 12 5.373 12 12v44c0 9.957-.881 19.71-2.55 29.195zM352 96c0-53.019-42.981-96-96-96-32.574 0-61.354 16.227-78.71 41.035L352 215.746V96zm152.971 363.716L52.284 7.029c-9.373-9.373-24.569-9.373-33.941 0L7.029 18.343c-9.372 9.373-9.372 24.568 0 33.941L160 205.254v49.577c0 53.089 43.436 97.452 96.524 97.167 14.626-.078 28.471-3.44 40.854-9.366l17.746 17.746c-17.529 9.971-37.794 15.666-59.372 15.622C189.355 375.864 136 321.053 136 254.656V212c0-6.627-5.373-12-12-12h-24c-6.627 0-12 5.373-12 12v44c0 84.488 62.693 154.597 144 166.278V468h-68c-6.627 0-12 5.373-12 12v20c0 6.627 5.373 12 12 12h184c6.627 0 12-5.373 12-12v-20c0-6.627-5.373-12-12-12h-68v-45.722c25.625-3.682 49.396-13.172 69.942-27.083L459.717 504.97c9.373 9.373 24.569 9.373 33.941 0l11.313-11.313c9.372-9.373 9.372-24.568 0-33.941z"],minus:[448,512,[],"f068","M424 318.2c13.3 0 24-10.7 24-24v-76.4c0-13.3-10.7-24-24-24H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h400z"],"minus-circle":[512,512,[],"f056","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zM124 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H124z"],"minus-square":[448,512,[],"f146","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM92 296c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h264c6.6 0 12 5.4 12 12v56c0 6.6-5.4 12-12 12H92z"],mobile:[320,512,[],"f10b","M272 0H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h224c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM160 480c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"],"mobile-alt":[320,512,[],"f3cd","M272 0H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h224c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM160 480c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm112-108c0 6.6-5.4 12-12 12H60c-6.6 0-12-5.4-12-12V60c0-6.6 5.4-12 12-12h200c6.6 0 12 5.4 12 12v312z"],"money-bill-alt":[640,512,[],"f3d1","M640 120v272c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V120c0-13.255 10.745-24 24-24h592c13.255 0 24 10.745 24 24zM96 384c0-35.346-28.654-64-64-64v64h64zm0-256H32v64c35.346 0 64-28.654 64-64zm304 128c0-53.021-35.816-96-80-96s-80 42.979-80 96c0 53.012 35.814 96 80 96 44.167 0 80-42.969 80-96zm208 64c-35.346 0-64 28.654-64 64h64v-64zm0-192h-64c0 35.346 28.654 64 64 64v-64zM277.563 299.527c0-7.477 3.917-11.572 11.573-11.572h15.131v-39.878c0-5.163.534-10.503.534-10.503h-.356s-1.779 2.67-2.848 3.738c-4.451 4.273-10.504 4.451-15.666-1.068l-5.518-6.231c-5.342-5.341-4.984-11.216.534-16.379l21.72-19.939c4.449-4.095 8.366-5.697 14.42-5.697h12.105c7.656 0 11.749 3.916 11.749 11.572v84.384h15.488c7.655 0 11.572 4.094 11.572 11.572v8.901c0 7.477-3.917 11.572-11.572 11.572h-67.293c-7.656 0-11.573-4.095-11.573-11.572v-8.9z"],moon:[512,512,[],"f186","M283.211 512c78.962 0 151.079-35.925 198.857-94.792 7.068-8.708-.639-21.43-11.562-19.35-124.203 23.654-238.262-71.576-238.262-196.954 0-72.222 38.662-138.635 101.498-174.394 9.686-5.512 7.25-20.197-3.756-22.23A258.156 258.156 0 0 0 283.211 0c-141.309 0-256 114.511-256 256 0 141.309 114.511 256 256 256z"],motorcycle:[640,512,[],"f21c","M512.949 192.003c-14.862-.108-29.14 2.322-42.434 6.874L437.589 144H520c13.255 0 24-10.745 24-24V88c0-13.255-10.745-24-24-24h-45.311a24 24 0 0 0-17.839 7.945l-37.496 41.663-22.774-37.956A24 24 0 0 0 376 64h-80c-8.837 0-16 7.163-16 16v16c0 8.837 7.163 16 16 16h66.411l19.2 32H227.904c-17.727-23.073-44.924-40-99.904-40H72.54c-13.455 0-24.791 11.011-24.536 24.464C48.252 141.505 58.9 152 72 152h56c24.504 0 38.686 10.919 47.787 24.769l-11.291 20.529c-13.006-3.865-26.871-5.736-41.251-5.21C55.857 194.549 1.565 249.605.034 317.021-1.603 389.076 56.317 448 128 448c59.642 0 109.744-40.794 123.953-96h84.236c13.673 0 24.589-11.421 23.976-25.077-2.118-47.12 17.522-93.665 56.185-125.026l12.485 20.808c-27.646 23.654-45.097 58.88-44.831 98.179.47 69.556 57.203 126.452 126.758 127.11 71.629.678 129.839-57.487 129.234-129.099-.588-69.591-57.455-126.386-127.047-126.892zM128 400c-44.112 0-80-35.888-80-80s35.888-80 80-80c4.242 0 8.405.341 12.469.982L98.97 316.434C90.187 332.407 101.762 352 120 352h81.297c-12.37 28.225-40.56 48-73.297 48zm388.351-.116C470.272 402.337 432 365.554 432 320c0-21.363 8.434-40.781 22.125-55.144l49.412 82.352c4.546 7.577 14.375 10.034 21.952 5.488l13.72-8.232c7.577-4.546 10.034-14.375 5.488-21.952l-48.556-80.927A80.005 80.005 0 0 1 512 240c45.554 0 82.338 38.273 79.884 84.352-2.16 40.558-34.974 73.372-75.533 75.532z"],"mouse-pointer":[320,512,[],"f245","M302.189 329.126H196.105l55.831 135.993c3.889 9.428-.555 19.999-9.444 23.999l-49.165 21.427c-9.165 4-19.443-.571-23.332-9.714l-53.053-129.136-86.664 89.138C18.729 472.71 0 463.554 0 447.977V18.299C0 1.899 19.921-6.096 30.277 5.443l284.412 292.542c11.472 11.179 3.007 31.141-12.5 31.141z"],music:[512,512,[],"f001","M470.4 1.5l-304 96C153.1 101.7 144 114 144 128v264.6c-14.1-5.4-30.5-8.6-48-8.6-53 0-96 28.7-96 64s43 64 96 64 96-28.7 96-64V220.5l272-85.9v194c-14.1-5.4-30.5-8.6-48-8.6-53 0-96 28.7-96 64s43 64 96 64 96-28.7 96-64V32c0-21.7-21.1-37-41.6-30.5z"],neuter:[288,512,[],"f22c","M288 176c0-79.5-64.5-144-144-144S0 96.5 0 176c0 68.5 47.9 125.9 112 140.4V468c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12V316.4c64.1-14.5 112-71.9 112-140.4zm-144 80c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],newspaper:[576,512,[],"f1ea","M552 64H88c-13.255 0-24 10.745-24 24v8H24c-13.255 0-24 10.745-24 24v272c0 30.928 25.072 56 56 56h472c26.51 0 48-21.49 48-48V88c0-13.255-10.745-24-24-24zM56 400a8 8 0 0 1-8-8V144h16v248a8 8 0 0 1-8 8zm236-16H140c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h152c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12zm208 0H348c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h152c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12zm-208-96H140c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h152c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12zm208 0H348c-6.627 0-12-5.373-12-12v-8c0-6.627 5.373-12 12-12h152c6.627 0 12 5.373 12 12v8c0 6.627-5.373 12-12 12zm0-96H140c-6.627 0-12-5.373-12-12v-40c0-6.627 5.373-12 12-12h360c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12z"],"object-group":[512,512,[],"f247","M480 128V96h20c6.627 0 12-5.373 12-12V44c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v20H64V44c0-6.627-5.373-12-12-12H12C5.373 32 0 37.373 0 44v40c0 6.627 5.373 12 12 12h20v320H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-20h384v20c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20V128zM96 276V140c0-6.627 5.373-12 12-12h168c6.627 0 12 5.373 12 12v136c0 6.627-5.373 12-12 12H108c-6.627 0-12-5.373-12-12zm320 96c0 6.627-5.373 12-12 12H236c-6.627 0-12-5.373-12-12v-52h72c13.255 0 24-10.745 24-24v-72h84c6.627 0 12 5.373 12 12v136z"],"object-ungroup":[576,512,[],"f248","M64 320v26a6 6 0 0 1-6 6H6a6 6 0 0 1-6-6v-52a6 6 0 0 1 6-6h26V96H6a6 6 0 0 1-6-6V38a6 6 0 0 1 6-6h52a6 6 0 0 1 6 6v26h288V38a6 6 0 0 1 6-6h52a6 6 0 0 1 6 6v52a6 6 0 0 1-6 6h-26v192h26a6 6 0 0 1 6 6v52a6 6 0 0 1-6 6h-52a6 6 0 0 1-6-6v-26H64zm480-64v-32h26a6 6 0 0 0 6-6v-52a6 6 0 0 0-6-6h-52a6 6 0 0 0-6 6v26H408v72h8c13.255 0 24 10.745 24 24v64c0 13.255-10.745 24-24 24h-64c-13.255 0-24-10.745-24-24v-8H192v72h-26a6 6 0 0 0-6 6v52a6 6 0 0 0 6 6h52a6 6 0 0 0 6-6v-26h288v26a6 6 0 0 0 6 6h52a6 6 0 0 0 6-6v-52a6 6 0 0 0-6-6h-26V256z"],outdent:[448,512,[],"f03b","M0 84V44c0-8.837 7.163-16 16-16h416c8.837 0 16 7.163 16 16v40c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16zm208 144h224c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H208c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zM16 484h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm192-128h224c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H208c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zM4.687 267.313l96 95.984C110.734 373.348 128 366.224 128 351.984V160.008c0-14.329-17.325-21.304-27.313-11.313l-96 95.992c-6.249 6.248-6.249 16.378 0 22.626z"],"paint-brush":[512,512,[],"f1fc","M269.9 364.6c1.4 6.4 2.1 13 2.1 19.7 0 81.2-54.2 127.7-134.8 127.7C41.5 512 0 435.1 0 347.6c10.4 7.1 46.9 36.5 58.7 36.5 7 0 13-4 15.5-10.6 23.6-62.2 66.5-76.5 112.9-77.4 15.6 33.8 46.1 59.6 82.8 68.5zM460.6 0c-14.4 0-27.9 6.4-38.2 15.7C228.2 190 208 194.1 208 245.4c0 48.8 40.5 90.6 90.2 90.6 59 0 93.2-43.4 200.6-244.8 7-13.7 13.2-28.5 13.2-43.9C512 19.7 487.3 0 460.6 0z"],"paper-plane":[512,512,[],"f1d8","M476 3.2L12.5 270.6c-18.1 10.4-15.8 35.6 2.2 43.2L121 358.4l287.3-253.2c5.5-4.9 13.3 2.6 8.6 8.3L176 407v80.5c0 23.6 28.5 32.9 42.5 15.8L282 426l124.6 52.2c14.2 6 30.4-2.9 33-18.2l72-432C515 7.8 493.3-6.8 476 3.2z"],paperclip:[448,512,[],"f0c6","M43.246 466.142c-58.43-60.289-57.341-157.511 1.386-217.581L254.392 34c44.316-45.332 116.351-45.336 160.671 0 43.89 44.894 43.943 117.329 0 162.276L232.214 383.128c-29.855 30.537-78.633 30.111-107.982-.998-28.275-29.97-27.368-77.473 1.452-106.953l143.743-146.835c6.182-6.314 16.312-6.422 22.626-.241l22.861 22.379c6.315 6.182 6.422 16.312.241 22.626L171.427 319.927c-4.932 5.045-5.236 13.428-.648 18.292 4.372 4.634 11.245 4.711 15.688.165l182.849-186.851c19.613-20.062 19.613-52.725-.011-72.798-19.189-19.627-49.957-19.637-69.154 0L90.39 293.295c-34.763 35.56-35.299 93.12-1.191 128.313 34.01 35.093 88.985 35.137 123.058.286l172.06-175.999c6.177-6.319 16.307-6.433 22.626-.256l22.877 22.364c6.319 6.177 6.434 16.307.256 22.626l-172.06 175.998c-59.576 60.938-155.943 60.216-214.77-.485z"],paragraph:[448,512,[],"f1dd","M408 32H177.531C88.948 32 16.045 103.335 16 191.918 15.956 280.321 87.607 352 176 352v104c0 13.255 10.745 24 24 24h32c13.255 0 24-10.745 24-24V112h32v344c0 13.255 10.745 24 24 24h32c13.255 0 24-10.745 24-24V112h40c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24z"],paste:[448,512,[],"f0ea","M128 184c0-30.879 25.122-56 56-56h136V56c0-13.255-10.745-24-24-24h-80.61C204.306 12.89 183.637 0 160 0s-44.306 12.89-55.39 32H24C10.745 32 0 42.745 0 56v336c0 13.255 10.745 24 24 24h104V184zm32-144c13.255 0 24 10.745 24 24s-10.745 24-24 24-24-10.745-24-24 10.745-24 24-24zm184 248h104v200c0 13.255-10.745 24-24 24H184c-13.255 0-24-10.745-24-24V184c0-13.255 10.745-24 24-24h136v104c0 13.2 10.8 24 24 24zm104-38.059V256h-96v-96h6.059a24 24 0 0 1 16.97 7.029l65.941 65.941a24.002 24.002 0 0 1 7.03 16.971z"],pause:[448,512,[],"f04c","M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z"],"pause-circle":[512,512,[],"f28b","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm-16 328c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16v160zm112 0c0 8.8-7.2 16-16 16h-48c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h48c8.8 0 16 7.2 16 16v160z"],paw:[512,512,[],"f1b0","M85.231 330.958C36 330.958 0 273.792 0 231.5c0-28.292 16-58.042 49.538-58.042 49.231 0 85.231 57.458 85.231 99.75 0 28.292-15.692 57.75-49.538 57.75zm348 106.167c0 37.042-32 42.875-63.385 42.875-41.231 0-74.462-26.25-113.846-26.25-41.231 0-76.308 25.958-120.923 25.958-29.847 0-56.308-9.625-56.308-42.583C78.769 368 180.616 265.333 256 265.333s177.231 102.959 177.231 171.792zM182.462 203.792c-49.847 0-80-59.5-80-100.333C102.462 70.792 120.308 32 160 32c50.154 0 80 59.5 80 100.333 0 32.667-17.846 71.459-57.538 71.459zM272 132.333C272 91.5 301.846 32 352 32c39.692 0 57.539 38.792 57.539 71.458 0 40.833-30.154 100.333-80.001 100.333C289.846 203.792 272 165 272 132.333zM512 231.5c0 42.292-36 99.458-85.231 99.458-33.847 0-49.538-29.458-49.538-57.75 0-42.291 35.999-99.75 85.231-99.75C496 173.458 512 203.208 512 231.5z"],"pen-square":[448,512,[],"f14b","M400 480H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zM238.1 177.9L102.4 313.6l-6.3 57.1c-.8 7.6 5.6 14.1 13.3 13.3l57.1-6.3L302.2 242c2.3-2.3 2.3-6.1 0-8.5L246.7 178c-2.5-2.4-6.3-2.4-8.6-.1zM345 165.1L314.9 135c-9.4-9.4-24.6-9.4-33.9 0l-23.1 23.1c-2.3 2.3-2.3 6.1 0 8.5l55.5 55.5c2.3 2.3 6.1 2.3 8.5 0L345 199c9.3-9.3 9.3-24.5 0-33.9z"],"pencil-alt":[512,512,[],"f303","M497.9 142.1l-46.1 46.1c-4.7 4.7-12.3 4.7-17 0l-111-111c-4.7-4.7-4.7-12.3 0-17l46.1-46.1c18.7-18.7 49.1-18.7 67.9 0l60.1 60.1c18.8 18.7 18.8 49.1 0 67.9zM284.2 99.8L21.6 362.4.4 483.9c-2.9 16.4 11.4 30.6 27.8 27.8l121.5-21.3 262.6-262.6c4.7-4.7 4.7-12.3 0-17l-111-111c-4.8-4.7-12.4-4.7-17.1 0zM124.1 339.9c-5.5-5.5-5.5-14.3 0-19.8l154-154c5.5-5.5 14.3-5.5 19.8 0s5.5 14.3 0 19.8l-154 154c-5.5 5.5-14.3 5.5-19.8 0zM88 424h48v36.3l-64.5 11.3-31.1-31.1L51.7 376H88v48z"],percent:[448,512,[],"f295","M112 224c61.9 0 112-50.1 112-112S173.9 0 112 0 0 50.1 0 112s50.1 112 112 112zm0-160c26.5 0 48 21.5 48 48s-21.5 48-48 48-48-21.5-48-48 21.5-48 48-48zm224 224c-61.9 0-112 50.1-112 112s50.1 112 112 112 112-50.1 112-112-50.1-112-112-112zm0 160c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48zM392.3.2l31.6-.1c19.4-.1 30.9 21.8 19.7 37.8L77.4 501.6a23.95 23.95 0 0 1-19.6 10.2l-33.4.1c-19.5 0-30.9-21.9-19.7-37.8l368-463.7C377.2 4 384.5.2 392.3.2z"],phone:[512,512,[],"f095","M493.397 24.615l-104-23.997c-11.314-2.611-22.879 3.252-27.456 13.931l-48 111.997a24 24 0 0 0 6.862 28.029l60.617 49.596c-35.973 76.675-98.938 140.508-177.249 177.248l-49.596-60.616a24 24 0 0 0-28.029-6.862l-111.997 48C3.873 366.516-1.994 378.08.618 389.397l23.997 104C27.109 504.204 36.748 512 48 512c256.087 0 464-207.532 464-464 0-11.176-7.714-20.873-18.603-23.385z"],"phone-square":[448,512,[],"f098","M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM94 416c-7.033 0-13.057-4.873-14.616-11.627l-14.998-65a15 15 0 0 1 8.707-17.16l69.998-29.999a15 15 0 0 1 17.518 4.289l30.997 37.885c48.944-22.963 88.297-62.858 110.781-110.78l-37.886-30.997a15.001 15.001 0 0 1-4.289-17.518l30-69.998a15 15 0 0 1 17.16-8.707l65 14.998A14.997 14.997 0 0 1 384 126c0 160.292-129.945 290-290 290z"],"phone-volume":[384,512,[],"f2a0","M97.333 506.966c-129.874-129.874-129.681-340.252 0-469.933 5.698-5.698 14.527-6.632 21.263-2.422l64.817 40.513a17.187 17.187 0 0 1 6.849 20.958l-32.408 81.021a17.188 17.188 0 0 1-17.669 10.719l-55.81-5.58c-21.051 58.261-20.612 122.471 0 179.515l55.811-5.581a17.188 17.188 0 0 1 17.669 10.719l32.408 81.022a17.188 17.188 0 0 1-6.849 20.958l-64.817 40.513a17.19 17.19 0 0 1-21.264-2.422zM247.126 95.473c11.832 20.047 11.832 45.008 0 65.055-3.95 6.693-13.108 7.959-18.718 2.581l-5.975-5.726c-3.911-3.748-4.793-9.622-2.261-14.41a32.063 32.063 0 0 0 0-29.945c-2.533-4.788-1.65-10.662 2.261-14.41l5.975-5.726c5.61-5.378 14.768-4.112 18.718 2.581zm91.787-91.187c60.14 71.604 60.092 175.882 0 247.428-4.474 5.327-12.53 5.746-17.552.933l-5.798-5.557c-4.56-4.371-4.977-11.529-.93-16.379 49.687-59.538 49.646-145.933 0-205.422-4.047-4.85-3.631-12.008.93-16.379l5.798-5.557c5.022-4.813 13.078-4.394 17.552.933zm-45.972 44.941c36.05 46.322 36.108 111.149 0 157.546-4.39 5.641-12.697 6.251-17.856 1.304l-5.818-5.579c-4.4-4.219-4.998-11.095-1.285-15.931 26.536-34.564 26.534-82.572 0-117.134-3.713-4.836-3.115-11.711 1.285-15.931l5.818-5.579c5.159-4.947 13.466-4.337 17.856 1.304z"],plane:[576,512,[],"f072","M472 200H360.211L256.013 5.711A12 12 0 0 0 245.793 0h-57.787c-7.85 0-13.586 7.413-11.616 15.011L209.624 200H99.766l-34.904-58.174A12 12 0 0 0 54.572 136H12.004c-7.572 0-13.252 6.928-11.767 14.353l21.129 105.648L.237 361.646c-1.485 7.426 4.195 14.354 11.768 14.353l42.568-.002c4.215 0 8.121-2.212 10.289-5.826L99.766 312h109.858L176.39 496.989c-1.97 7.599 3.766 15.011 11.616 15.011h57.787a12 12 0 0 0 10.22-5.711L360.212 312H472c57.438 0 104-25.072 104-56s-46.562-56-104-56z"],play:[448,512,[],"f04b","M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"],"play-circle":[512,512,[],"f144","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm115.7 272l-176 101c-15.8 8.8-35.7-2.5-35.7-21V152c0-18.4 19.8-29.8 35.7-21l176 107c16.4 9.2 16.4 32.9 0 42z"],plug:[384,512,[],"f1e6","M256 144V32c0-17.673 14.327-32 32-32s32 14.327 32 32v112h-64zm112 16H16c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16h16v32c0 77.406 54.969 141.971 128 156.796V512h64v-99.204c73.031-14.825 128-79.39 128-156.796v-32h16c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16zm-240-16V32c0-17.673-14.327-32-32-32S64 14.327 64 32v112h64z"],plus:[448,512,[],"f067","M448 294.2v-76.4c0-13.3-10.7-24-24-24H286.2V56c0-13.3-10.7-24-24-24h-76.4c-13.3 0-24 10.7-24 24v137.8H24c-13.3 0-24 10.7-24 24v76.4c0 13.3 10.7 24 24 24h137.8V456c0 13.3 10.7 24 24 24h76.4c13.3 0 24-10.7 24-24V318.2H424c13.3 0 24-10.7 24-24z"],"plus-circle":[512,512,[],"f055","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm144 276c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92h-92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"],"plus-square":[448,512,[],"f0fe","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-32 252c0 6.6-5.4 12-12 12h-92v92c0 6.6-5.4 12-12 12h-56c-6.6 0-12-5.4-12-12v-92H92c-6.6 0-12-5.4-12-12v-56c0-6.6 5.4-12 12-12h92v-92c0-6.6 5.4-12 12-12h56c6.6 0 12 5.4 12 12v92h92c6.6 0 12 5.4 12 12v56z"],podcast:[448,512,[],"f2ce","M267.429 488.563C262.286 507.573 242.858 512 224 512c-18.857 0-38.286-4.427-43.428-23.437C172.927 460.134 160 388.898 160 355.75c0-35.156 31.142-43.75 64-43.75s64 8.594 64 43.75c0 32.949-12.871 104.179-20.571 132.813zM156.867 288.554c-18.693-18.308-29.958-44.173-28.784-72.599 2.054-49.724 42.395-89.956 92.124-91.881C274.862 121.958 320 165.807 320 220c0 26.827-11.064 51.116-28.866 68.552-2.675 2.62-2.401 6.986.628 9.187 9.312 6.765 16.46 15.343 21.234 25.363 1.741 3.654 6.497 4.66 9.449 1.891 28.826-27.043 46.553-65.783 45.511-108.565-1.855-76.206-63.595-138.208-139.793-140.369C146.869 73.753 80 139.215 80 220c0 41.361 17.532 78.7 45.55 104.989 2.953 2.771 7.711 1.77 9.453-1.887 4.774-10.021 11.923-18.598 21.235-25.363 3.029-2.2 3.304-6.566.629-9.185zM224 0C100.204 0 0 100.185 0 224c0 89.992 52.602 165.647 125.739 201.408 4.333 2.118 9.267-1.544 8.535-6.31-2.382-15.512-4.342-30.946-5.406-44.339-.146-1.836-1.149-3.486-2.678-4.512-47.4-31.806-78.564-86.016-78.187-147.347.592-96.237 79.29-174.648 175.529-174.899C320.793 47.747 400 126.797 400 224c0 61.932-32.158 116.49-80.65 147.867-.999 14.037-3.069 30.588-5.624 47.23-.732 4.767 4.203 8.429 8.535 6.31C395.227 389.727 448 314.187 448 224 448 100.205 347.815 0 224 0zm0 160c-35.346 0-64 28.654-64 64s28.654 64 64 64 64-28.654 64-64-28.654-64-64-64z"],"pound-sign":[320,512,[],"f154","M308 352h-45.495c-6.627 0-12 5.373-12 12v50.848H128V288h84c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-84v-63.556c0-32.266 24.562-57.086 61.792-57.086 23.658 0 45.878 11.505 57.652 18.849 5.151 3.213 11.888 2.051 15.688-2.685l28.493-35.513c4.233-5.276 3.279-13.005-2.119-17.081C273.124 54.56 236.576 32 187.931 32 106.026 32 48 84.742 48 157.961V224H20c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h28v128H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h296c6.627 0 12-5.373 12-12V364c0-6.627-5.373-12-12-12z"],"power-off":[512,512,[],"f011","M400 54.1c63 45 104 118.6 104 201.9 0 136.8-110.8 247.7-247.5 248C120 504.3 8.2 393 8 256.4 7.9 173.1 48.9 99.3 111.8 54.2c11.7-8.3 28-4.8 35 7.7L162.6 90c5.9 10.5 3.1 23.8-6.6 31-41.5 30.8-68 79.6-68 134.9-.1 92.3 74.5 168.1 168 168.1 91.6 0 168.6-74.2 168-169.1-.3-51.8-24.7-101.8-68.1-134-9.7-7.2-12.4-20.5-6.5-30.9l15.8-28.1c7-12.4 23.2-16.1 34.8-7.8zM296 264V24c0-13.3-10.7-24-24-24h-32c-13.3 0-24 10.7-24 24v240c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24z"],print:[512,512,[],"f02f","M464 192h-16V81.941a24 24 0 0 0-7.029-16.97L383.029 7.029A24 24 0 0 0 366.059 0H88C74.745 0 64 10.745 64 24v168H48c-26.51 0-48 21.49-48 48v132c0 6.627 5.373 12 12 12h52v104c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V384h52c6.627 0 12-5.373 12-12V240c0-26.51-21.49-48-48-48zm-80 256H128v-96h256v96zM128 224V64h192v40c0 13.2 10.8 24 24 24h40v96H128zm304 72c-13.254 0-24-10.746-24-24s10.746-24 24-24 24 10.746 24 24-10.746 24-24 24z"],"puzzle-piece":[576,512,[],"f12e","M519.442 288.651c-41.519 0-59.5 31.593-82.058 31.593C377.409 320.244 432 144 432 144s-196.288 80-196.288-3.297c0-35.827 36.288-46.25 36.288-85.985C272 19.216 243.885 0 210.539 0c-34.654 0-66.366 18.891-66.366 56.346 0 41.364 31.711 59.277 31.711 81.75C175.885 207.719 0 166.758 0 166.758v333.237s178.635 41.047 178.635-28.662c0-22.473-40-40.107-40-81.471 0-37.456 29.25-56.346 63.577-56.346 33.673 0 61.788 19.216 61.788 54.717 0 39.735-36.288 50.158-36.288 85.985 0 60.803 129.675 25.73 181.23 25.73 0 0-34.725-120.101 25.827-120.101 35.962 0 46.423 36.152 86.308 36.152C556.712 416 576 387.99 576 354.443c0-34.199-18.962-65.792-56.558-65.792z"],qrcode:[448,512,[],"f029","M0 224h192V32H0v192zM64 96h64v64H64V96zm192-64v192h192V32H256zm128 128h-64V96h64v64zM0 480h192V288H0v192zm64-128h64v64H64v-64zm352-64h32v128h-96v-32h-32v96h-64V288h96v32h64v-32zm0 160h32v32h-32v-32zm-64 0h32v32h-32v-32z"],question:[384,512,[],"f128","M202.021 0C122.202 0 70.503 32.703 29.914 91.026c-7.363 10.58-5.093 25.086 5.178 32.874l43.138 32.709c10.373 7.865 25.132 6.026 33.253-4.148 25.049-31.381 43.63-49.449 82.757-49.449 30.764 0 68.816 19.799 68.816 49.631 0 22.552-18.617 34.134-48.993 51.164-35.423 19.86-82.299 44.576-82.299 106.405V320c0 13.255 10.745 24 24 24h72.471c13.255 0 24-10.745 24-24v-5.773c0-42.86 125.268-44.645 125.268-160.627C377.504 66.256 286.902 0 202.021 0zM192 373.459c-38.196 0-69.271 31.075-69.271 69.271 0 38.195 31.075 69.27 69.271 69.27s69.271-31.075 69.271-69.271-31.075-69.27-69.271-69.27z"],"question-circle":[512,512,[],"f059","M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zM262.655 90c-54.497 0-89.255 22.957-116.549 63.758-3.536 5.286-2.353 12.415 2.715 16.258l34.699 26.31c5.205 3.947 12.621 3.008 16.665-2.122 17.864-22.658 30.113-35.797 57.303-35.797 20.429 0 45.698 13.148 45.698 32.958 0 14.976-12.363 22.667-32.534 33.976C247.128 238.528 216 254.941 216 296v4c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-1.333c0-28.462 83.186-29.647 83.186-106.667 0-58.002-60.165-102-116.531-102zM256 338c-25.365 0-46 20.635-46 46 0 25.364 20.635 46 46 46s46-20.636 46-46c0-25.365-20.635-46-46-46z"],"quote-left":[512,512,[],"f10d","M0 432V304C0 166.982 63.772 67.676 193.827 32.828 209.052 28.748 224 40.265 224 56.027v33.895c0 10.057-6.228 19.133-15.687 22.55C142.316 136.312 104 181.946 104 256h72c26.51 0 48 21.49 48 48v128c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48zm336 48h128c26.51 0 48-21.49 48-48V304c0-26.51-21.49-48-48-48h-72c0-74.054 38.316-119.688 104.313-143.528C505.772 109.055 512 99.979 512 89.922V56.027c0-15.762-14.948-27.279-30.173-23.199C351.772 67.676 288 166.982 288 304v128c0 26.51 21.49 48 48 48z"],"quote-right":[512,512,[],"f10e","M512 80v128c0 137.018-63.772 236.324-193.827 271.172-15.225 4.08-30.173-7.437-30.173-23.199v-33.895c0-10.057 6.228-19.133 15.687-22.55C369.684 375.688 408 330.054 408 256h-72c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h128c26.51 0 48 21.49 48 48zM176 32H48C21.49 32 0 53.49 0 80v128c0 26.51 21.49 48 48 48h72c0 74.054-38.316 119.688-104.313 143.528C6.228 402.945 0 412.021 0 422.078v33.895c0 15.762 14.948 27.279 30.173 23.199C160.228 444.324 224 345.018 224 208V80c0-26.51-21.49-48-48-48z"],random:[512,512,[],"f074","M504.971 359.029c9.373 9.373 9.373 24.569 0 33.941l-80 79.984c-15.01 15.01-40.971 4.49-40.971-16.971V416h-58.785a12.004 12.004 0 0 1-8.773-3.812l-70.556-75.596 53.333-57.143L352 336h32v-39.981c0-21.438 25.943-31.998 40.971-16.971l80 79.981zM12 176h84l52.781 56.551 53.333-57.143-70.556-75.596A11.999 11.999 0 0 0 122.785 96H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12zm372 0v39.984c0 21.46 25.961 31.98 40.971 16.971l80-79.984c9.373-9.373 9.373-24.569 0-33.941l-80-79.981C409.943 24.021 384 34.582 384 56.019V96h-58.785a12.004 12.004 0 0 0-8.773 3.812L96 336H12c-6.627 0-12 5.373-12 12v56c0 6.627 5.373 12 12 12h110.785c3.326 0 6.503-1.381 8.773-3.812L352 176h32z"],recycle:[512,512,[],"f1b8","M184.561 261.903c3.232 13.997-12.123 24.635-24.068 17.168l-40.736-25.455-50.867 81.402C55.606 356.273 70.96 384 96.012 384H148c6.627 0 12 5.373 12 12v40c0 6.627-5.373 12-12 12H96.115c-75.334 0-121.302-83.048-81.408-146.88l50.822-81.388-40.725-25.448c-12.081-7.547-8.966-25.961 4.879-29.158l110.237-25.45c8.611-1.988 17.201 3.381 19.189 11.99l25.452 110.237zm98.561-182.915l41.289 66.076-40.74 25.457c-12.051 7.528-9 25.953 4.879 29.158l110.237 25.45c8.672 1.999 17.215-3.438 19.189-11.99l25.45-110.237c3.197-13.844-11.99-24.719-24.068-17.168l-40.687 25.424-41.263-66.082c-37.521-60.033-125.209-60.171-162.816 0l-17.963 28.766c-3.51 5.62-1.8 13.021 3.82 16.533l33.919 21.195c5.62 3.512 13.024 1.803 16.536-3.817l17.961-28.743c12.712-20.341 41.973-19.676 54.257-.022zM497.288 301.12l-27.515-44.065c-3.511-5.623-10.916-7.334-16.538-3.821l-33.861 21.159c-5.62 3.512-7.33 10.915-3.818 16.536l27.564 44.112c13.257 21.211-2.057 48.96-27.136 48.96H320V336.02c0-14.213-17.242-21.383-27.313-11.313l-80 79.981c-6.249 6.248-6.249 16.379 0 22.627l80 79.989C302.689 517.308 320 510.3 320 495.989V448h95.88c75.274 0 121.335-82.997 81.408-146.88z"],redo:[512,512,[],"f01e","M500.333 0h-47.411c-6.853 0-12.314 5.729-11.986 12.574l3.966 82.759C399.416 41.899 331.672 8 256.001 8 119.34 8 7.899 119.526 8 256.187 8.101 393.068 119.096 504 256 504c63.926 0 122.202-24.187 166.178-63.908 5.113-4.618 5.354-12.561.482-17.433l-33.971-33.971c-4.466-4.466-11.64-4.717-16.38-.543C341.308 415.448 300.606 432 256 432c-97.267 0-176-78.716-176-176 0-97.267 78.716-176 176-176 60.892 0 114.506 30.858 146.099 77.8l-101.525-4.865c-6.845-.328-12.574 5.133-12.574 11.986v47.411c0 6.627 5.373 12 12 12h200.333c6.627 0 12-5.373 12-12V12c0-6.627-5.373-12-12-12z"],"redo-alt":[512,512,[],"f2f9","M256.455 8c66.269.119 126.437 26.233 170.859 68.685l35.715-35.715C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.75c-30.864-28.899-70.801-44.907-113.23-45.273-92.398-.798-170.283 73.977-169.484 169.442C88.764 348.009 162.184 424 256 424c41.127 0 79.997-14.678 110.629-41.556 4.743-4.161 11.906-3.908 16.368.553l39.662 39.662c4.872 4.872 4.631 12.815-.482 17.433C378.202 479.813 319.926 504 256 504 119.034 504 8.001 392.967 8 256.002 7.999 119.193 119.646 7.755 256.455 8z"],registered:[512,512,[],"f25d","M285.363 207.475c0 18.6-9.831 28.431-28.431 28.431h-29.876v-56.14h23.378c28.668 0 34.929 8.773 34.929 27.709zM504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM363.411 360.414c-46.729-84.825-43.299-78.636-44.702-80.98 23.432-15.172 37.945-42.979 37.945-74.486 0-54.244-31.5-89.252-105.498-89.252h-70.667c-13.255 0-24 10.745-24 24V372c0 13.255 10.745 24 24 24h22.567c13.255 0 24-10.745 24-24v-71.663h25.556l44.129 82.937a24.001 24.001 0 0 0 21.188 12.727h24.464c18.261-.001 29.829-19.591 21.018-35.587z"],reply:[512,512,[],"f3e5","M8.309 189.836L184.313 37.851C199.719 24.546 224 35.347 224 56.015v80.053c160.629 1.839 288 34.032 288 186.258 0 61.441-39.581 122.309-83.333 154.132-13.653 9.931-33.111-2.533-28.077-18.631 45.344-145.012-21.507-183.51-176.59-185.742V360c0 20.7-24.3 31.453-39.687 18.164l-176.004-152c-11.071-9.562-11.086-26.753 0-36.328z"],"reply-all":[576,512,[],"f122","M136.309 189.836L312.313 37.851C327.72 24.546 352 35.348 352 56.015v82.763c129.182 10.231 224 52.212 224 183.548 0 61.441-39.582 122.309-83.333 154.132-13.653 9.931-33.111-2.533-28.077-18.631 38.512-123.162-3.922-169.482-112.59-182.015v84.175c0 20.701-24.3 31.453-39.687 18.164L136.309 226.164c-11.071-9.561-11.086-26.753 0-36.328zm-128 36.328L184.313 378.15C199.7 391.439 224 380.687 224 359.986v-15.818l-108.606-93.785A55.96 55.96 0 0 1 96 207.998a55.953 55.953 0 0 1 19.393-42.38L224 71.832V56.015c0-20.667-24.28-31.469-39.687-18.164L8.309 189.836c-11.086 9.575-11.071 26.767 0 36.328z"],retweet:[640,512,[],"f079","M629.657 343.598L528.971 444.284c-9.373 9.372-24.568 9.372-33.941 0L394.343 343.598c-9.373-9.373-9.373-24.569 0-33.941l10.823-10.823c9.562-9.562 25.133-9.34 34.419.492L480 342.118V160H292.451a24.005 24.005 0 0 1-16.971-7.029l-16-16C244.361 121.851 255.069 96 276.451 96H520c13.255 0 24 10.745 24 24v222.118l40.416-42.792c9.285-9.831 24.856-10.054 34.419-.492l10.823 10.823c9.372 9.372 9.372 24.569-.001 33.941zm-265.138 15.431A23.999 23.999 0 0 0 347.548 352H160V169.881l40.416 42.792c9.286 9.831 24.856 10.054 34.419.491l10.822-10.822c9.373-9.373 9.373-24.569 0-33.941L144.971 67.716c-9.373-9.373-24.569-9.373-33.941 0L10.343 168.402c-9.373 9.373-9.373 24.569 0 33.941l10.822 10.822c9.562 9.562 25.133 9.34 34.419-.491L96 169.881V392c0 13.255 10.745 24 24 24h243.549c21.382 0 32.09-25.851 16.971-40.971l-16.001-16z"],road:[576,512,[],"f018","M567.3 383.6L429.9 78.2C426 69.5 417.4 64 408 64h-96.1l1.9 18.8c.7 7.1-4.8 13.2-11.9 13.2H274c-7.1 0-12.7-6.2-11.9-13.2L264 64h-96c-9.4 0-18 5.5-21.9 14.2L8.7 383.6C3.2 395.8 0 409.6 0 424c0 13.3 10.7 24 24 24h213.6c-7.1 0-12.7-6.2-11.9-13.2l10.8-104c.6-6.1 5.8-10.8 11.9-10.8h79.2c6.1 0 11.3 4.6 11.9 10.8l10.8 104c.7 7.1-4.8 13.2-11.9 13.2H552c13.2 0 24-10.7 24-24 0-13.9-3-27.7-8.7-40.4zM254.7 154.8l3.3-32c.6-6.1 5.8-10.8 11.9-10.8h36.2c6.1 0 11.3 4.6 11.9 10.8l3.3 32c.7 7.1-4.8 13.2-11.9 13.2h-42.8c-7.1 0-12.7-6.2-11.9-13.2zM321.8 288h-67.6c-7.1 0-12.7-6.2-11.9-13.2l7.4-72c.6-6.1 5.8-10.8 11.9-10.8h52.7c6.1 0 11.3 4.6 11.9 10.8l7.4 72c.9 7-4.7 13.2-11.8 13.2z"],rocket:[512,512,[],"f135","M505.1 19.1C503.8 13 499 8.2 492.9 6.9 460.7 0 435.5 0 410.4 0 307.2 0 245.3 55.2 199.1 128H94.9c-18.2 0-34.8 10.3-42.9 26.5L2.6 253.3c-8 16 3.6 34.7 21.5 34.7h95.1c-5.9 12.8-11.9 25.5-18 37.7-3.1 6.2-1.9 13.6 3 18.5l63.6 63.6c4.9 4.9 12.3 6.1 18.5 3 12.2-6.1 24.9-12 37.7-17.9V488c0 17.8 18.8 29.4 34.7 21.5l98.7-49.4c16.3-8.1 26.5-24.8 26.5-42.9V312.8c72.6-46.3 128-108.4 128-211.1.1-25.2.1-50.4-6.8-82.6zM400 160c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48z"],rss:[448,512,[],"f09e","M128.081 415.959c0 35.369-28.672 64.041-64.041 64.041S0 451.328 0 415.959s28.672-64.041 64.041-64.041 64.04 28.673 64.04 64.041zm175.66 47.25c-8.354-154.6-132.185-278.587-286.95-286.95C7.656 175.765 0 183.105 0 192.253v48.069c0 8.415 6.49 15.472 14.887 16.018 111.832 7.284 201.473 96.702 208.772 208.772.547 8.397 7.604 14.887 16.018 14.887h48.069c9.149.001 16.489-7.655 15.995-16.79zm144.249.288C439.596 229.677 251.465 40.445 16.503 32.01 7.473 31.686 0 38.981 0 48.016v48.068c0 8.625 6.835 15.645 15.453 15.999 191.179 7.839 344.627 161.316 352.465 352.465.353 8.618 7.373 15.453 15.999 15.453h48.068c9.034-.001 16.329-7.474 16.005-16.504z"],"rss-square":[448,512,[],"f143","M400 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM112 416c-26.51 0-48-21.49-48-48s21.49-48 48-48 48 21.49 48 48-21.49 48-48 48zm157.533 0h-34.335c-6.011 0-11.051-4.636-11.442-10.634-5.214-80.05-69.243-143.92-149.123-149.123-5.997-.39-10.633-5.431-10.633-11.441v-34.335c0-6.535 5.468-11.777 11.994-11.425 110.546 5.974 198.997 94.536 204.964 204.964.352 6.526-4.89 11.994-11.425 11.994zm103.027 0h-34.334c-6.161 0-11.175-4.882-11.427-11.038-5.598-136.535-115.204-246.161-251.76-251.76C68.882 152.949 64 147.935 64 141.774V107.44c0-6.454 5.338-11.664 11.787-11.432 167.83 6.025 302.21 141.191 308.205 308.205.232 6.449-4.978 11.787-11.432 11.787z"],"ruble-sign":[384,512,[],"f158","M239.36 320C324.48 320 384 260.542 384 175.071S324.48 32 239.36 32H76c-6.627 0-12 5.373-12 12v206.632H12c-6.627 0-12 5.373-12 12V308c0 6.627 5.373 12 12 12h52v32H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h52v52c0 6.627 5.373 12 12 12h58.56c6.627 0 12-5.373 12-12v-52H308c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12H146.56v-32h92.8zm-92.8-219.252h78.72c46.72 0 74.88 29.11 74.88 74.323 0 45.832-28.16 75.561-76.16 75.561h-77.44V100.748z"],"rupee-sign":[320,512,[],"f156","M308 96c6.627 0 12-5.373 12-12V44c0-6.627-5.373-12-12-12H12C5.373 32 0 37.373 0 44v44.748c0 6.627 5.373 12 12 12h85.28c27.308 0 48.261 9.958 60.97 27.252H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h158.757c-6.217 36.086-32.961 58.632-74.757 58.632H12c-6.627 0-12 5.373-12 12v53.012c0 3.349 1.4 6.546 3.861 8.818l165.052 152.356a12.001 12.001 0 0 0 8.139 3.182h82.562c10.924 0 16.166-13.408 8.139-20.818L116.871 319.906c76.499-2.34 131.144-53.395 138.318-127.906H308c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-58.69c-3.486-11.541-8.28-22.246-14.252-32H308z"],save:[448,512,[],"f0c7","M433.941 129.941l-83.882-83.882A48 48 0 0 0 316.118 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48V163.882a48 48 0 0 0-14.059-33.941zM224 416c-35.346 0-64-28.654-64-64 0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64zm96-304.52V212c0 6.627-5.373 12-12 12H76c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h228.52c3.183 0 6.235 1.264 8.485 3.515l3.48 3.48A11.996 11.996 0 0 1 320 111.48z"],search:[512,512,[],"f002","M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"],"search-minus":[512,512,[],"f010","M304 192v32c0 6.6-5.4 12-12 12H124c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h168c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"],"search-plus":[512,512,[],"f00e","M304 192v32c0 6.6-5.4 12-12 12h-56v56c0 6.6-5.4 12-12 12h-32c-6.6 0-12-5.4-12-12v-56h-56c-6.6 0-12-5.4-12-12v-32c0-6.6 5.4-12 12-12h56v-56c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v56h56c6.6 0 12 5.4 12 12zm201 284.7L476.7 505c-9.4 9.4-24.6 9.4-33.9 0L343 405.3c-4.5-4.5-7-10.6-7-17V372c-35.3 27.6-79.7 44-128 44C93.1 416 0 322.9 0 208S93.1 0 208 0s208 93.1 208 208c0 48.3-16.4 92.7-44 128h16.3c6.4 0 12.5 2.5 17 7l99.7 99.7c9.3 9.4 9.3 24.6 0 34zM344 208c0-75.2-60.8-136-136-136S72 132.8 72 208s60.8 136 136 136 136-60.8 136-136z"],server:[512,512,[],"f233","M480 160H32c-17.673 0-32-14.327-32-32V64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm112 248H32c-17.673 0-32-14.327-32-32v-64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm112 248H32c-17.673 0-32-14.327-32-32v-64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24z"],share:[512,512,[],"f064","M503.691 189.836L327.687 37.851C312.281 24.546 288 35.347 288 56.015v80.053C127.371 137.907 0 170.1 0 322.326c0 61.441 39.581 122.309 83.333 154.132 13.653 9.931 33.111-2.533 28.077-18.631C66.066 312.814 132.917 274.316 288 272.085V360c0 20.7 24.3 31.453 39.687 18.164l176.004-152c11.071-9.562 11.086-26.753 0-36.328z"],"share-alt":[448,512,[],"f1e0","M352 320c-22.608 0-43.387 7.819-59.79 20.895l-102.486-64.054a96.551 96.551 0 0 0 0-41.683l102.486-64.054C308.613 184.181 329.392 192 352 192c53.019 0 96-42.981 96-96S405.019 0 352 0s-96 42.981-96 96c0 7.158.79 14.13 2.276 20.841L155.79 180.895C139.387 167.819 118.608 160 96 160c-53.019 0-96 42.981-96 96s42.981 96 96 96c22.608 0 43.387-7.819 59.79-20.895l102.486 64.054A96.301 96.301 0 0 0 256 416c0 53.019 42.981 96 96 96s96-42.981 96-96-42.981-96-96-96z"],"share-alt-square":[448,512,[],"f1e1","M448 80v352c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48V80c0-26.51 21.49-48 48-48h352c26.51 0 48 21.49 48 48zM304 296c-14.562 0-27.823 5.561-37.783 14.671l-67.958-40.775a56.339 56.339 0 0 0 0-27.793l67.958-40.775C276.177 210.439 289.438 216 304 216c30.928 0 56-25.072 56-56s-25.072-56-56-56-56 25.072-56 56c0 4.797.605 9.453 1.74 13.897l-67.958 40.775C171.823 205.561 158.562 200 144 200c-30.928 0-56 25.072-56 56s25.072 56 56 56c14.562 0 27.823-5.561 37.783-14.671l67.958 40.775a56.088 56.088 0 0 0-1.74 13.897c0 30.928 25.072 56 56 56s56-25.072 56-56C360 321.072 334.928 296 304 296z"],"share-square":[576,512,[],"f14d","M568.482 177.448L424.479 313.433C409.3 327.768 384 317.14 384 295.985v-71.963c-144.575.97-205.566 35.113-164.775 171.353 4.483 14.973-12.846 26.567-25.006 17.33C155.252 383.105 120 326.488 120 269.339c0-143.937 117.599-172.5 264-173.312V24.012c0-21.174 25.317-31.768 40.479-17.448l144.003 135.988c10.02 9.463 10.028 25.425 0 34.896zM384 379.128V448H64V128h50.916a11.99 11.99 0 0 0 8.648-3.693c14.953-15.568 32.237-27.89 51.014-37.676C185.708 80.83 181.584 64 169.033 64H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h352c26.51 0 48-21.49 48-48v-88.806c0-8.288-8.197-14.066-16.011-11.302a71.83 71.83 0 0 1-34.189 3.377c-7.27-1.046-13.8 4.514-13.8 11.859z"],"shekel-sign":[448,512,[],"f20b","M170.12 96H80v372c0 6.627-5.373 12-12 12H12c-6.627 0-12-5.373-12-12V44c0-6.627 5.373-12 12-12h168.36C265.48 32 325 89.6 325 175.071V359c0 6.627-5.373 12-12 12h-44c-13.255 0-24-10.745-24-24V170.323C245 125.11 216.839 96 170.12 96zM436 32h-56c-6.627 0-12 5.373-12 12v372h-90.12c-46.72 0-74.88-29.11-74.88-74.323V165c0-13.255-10.745-24-24-24h-44c-6.627 0-12 5.373-12 12v183.929C123 422.4 182.52 480 267.64 480H436c6.627 0 12-5.373 12-12V44c0-6.627-5.373-12-12-12z"],"shield-alt":[512,512,[],"f3ed","M496 128c0 221.282-135.934 344.645-221.539 380.308a48 48 0 0 1-36.923 0C130.495 463.713 16 326.487 16 128a48 48 0 0 1 29.539-44.308l192-80a48 48 0 0 1 36.923 0l192 80A48 48 0 0 1 496 128zM256 446.313l.066.034c93.735-46.689 172.497-156.308 175.817-307.729L256 65.333v380.98z"],ship:[640,512,[],"f21a","M496.616 372.639l70.012-70.012c16.899-16.9 9.942-45.771-12.836-53.092L512 236.102V96c0-17.673-14.327-32-32-32h-64V24c0-13.255-10.745-24-24-24H248c-13.255 0-24 10.745-24 24v40h-64c-17.673 0-32 14.327-32 32v140.102l-41.792 13.433c-22.753 7.313-29.754 36.173-12.836 53.092l70.012 70.012C125.828 416.287 85.587 448 24 448c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24 61.023 0 107.499-20.61 143.258-59.396C181.677 487.432 216.021 512 256 512h128c39.979 0 74.323-24.568 88.742-59.396C508.495 491.384 554.968 512 616 512c13.255 0 24-10.745 24-24v-16c0-13.255-10.745-24-24-24-60.817 0-101.542-31.001-119.384-75.361zM192 128h256v87.531l-118.208-37.995a31.995 31.995 0 0 0-19.584 0L192 215.531V128z"],"shopping-bag":[448,512,[],"f290","M352 160v-32C352 57.42 294.579 0 224 0 153.42 0 96 57.42 96 128v32H0v272c0 44.183 35.817 80 80 80h288c44.183 0 80-35.817 80-80V160h-96zm-192-32c0-35.29 28.71-64 64-64s64 28.71 64 64v32H160v-32zm160 120c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24zm-192 0c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24z"],"shopping-basket":[576,512,[],"f291","M576 216v16c0 13.255-10.745 24-24 24h-8l-26.113 182.788C514.509 462.435 494.257 480 470.37 480H105.63c-23.887 0-44.139-17.565-47.518-41.212L32 256h-8c-13.255 0-24-10.745-24-24v-16c0-13.255 10.745-24 24-24h67.341l106.78-146.821c10.395-14.292 30.407-17.453 44.701-7.058 14.293 10.395 17.453 30.408 7.058 44.701L170.477 192h235.046L326.12 82.821c-10.395-14.292-7.234-34.306 7.059-44.701 14.291-10.395 34.306-7.235 44.701 7.058L484.659 192H552c13.255 0 24 10.745 24 24zM312 392V280c0-13.255-10.745-24-24-24s-24 10.745-24 24v112c0 13.255 10.745 24 24 24s24-10.745 24-24zm112 0V280c0-13.255-10.745-24-24-24s-24 10.745-24 24v112c0 13.255 10.745 24 24 24s24-10.745 24-24zm-224 0V280c0-13.255-10.745-24-24-24s-24 10.745-24 24v112c0 13.255 10.745 24 24 24s24-10.745 24-24z"],"shopping-cart":[576,512,[],"f07a","M528.12 301.319l47.273-208C578.806 78.301 567.391 64 551.99 64H159.208l-9.166-44.81C147.758 8.021 137.93 0 126.529 0H24C10.745 0 0 10.745 0 24v16c0 13.255 10.745 24 24 24h69.883l70.248 343.435C147.325 417.1 136 435.222 136 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-15.674-6.447-29.835-16.824-40h209.647C430.447 426.165 424 440.326 424 456c0 30.928 25.072 56 56 56s56-25.072 56-56c0-22.172-12.888-41.332-31.579-50.405l5.517-24.276c3.413-15.018-8.002-29.319-23.403-29.319H218.117l-6.545-32h293.145c11.206 0 20.92-7.754 23.403-18.681z"],shower:[512,512,[],"f2cc","M389.66 135.6L231.6 293.66c-9.37 9.37-24.57 9.37-33.94 0l-11.32-11.32c-9.37-9.37-9.37-24.57 0-33.94l.11-.11c-34.03-40.21-35.16-98.94-3.39-140.38-11.97-7.55-26.14-11.91-41.3-11.91C98.88 96 64 130.88 64 173.76V480H0V173.76C0 95.59 63.59 32 141.76 32c36.93 0 70.61 14.2 95.86 37.42 35.9-11.51 76.5-4.5 106.67 21.03l.11-.11c9.37-9.37 24.57-9.37 33.94 0l11.32 11.32c9.37 9.37 9.37 24.57 0 33.94zM384 208c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm32 0c0-8.837 7.163-16 16-16s16 7.163 16 16-7.163 16-16 16-16-7.163-16-16zm96 0c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-160 32c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm48-16c8.837 0 16 7.163 16 16s-7.163 16-16 16-16-7.163-16-16 7.163-16 16-16zm80 16c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-160 32c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm32 0c0-8.837 7.163-16 16-16s16 7.163 16 16-7.163 16-16 16-16-7.163-16-16zm96 0c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-128 32c0-8.837 7.163-16 16-16s16 7.163 16 16-7.163 16-16 16-16-7.163-16-16zm96 0c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-96 32c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm64 0c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-32 32c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16zm-32 32c0 8.837-7.163 16-16 16s-16-7.163-16-16 7.163-16 16-16 16 7.163 16 16z"],"sign-in-alt":[512,512,[],"f2f6","M416 448h-84c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h84c17.7 0 32-14.3 32-32V160c0-17.7-14.3-32-32-32h-84c-6.6 0-12-5.4-12-12V76c0-6.6 5.4-12 12-12h84c53 0 96 43 96 96v192c0 53-43 96-96 96zm-47-201L201 79c-15-15-41-4.5-41 17v96H24c-13.3 0-24 10.7-24 24v96c0 13.3 10.7 24 24 24h136v96c0 21.5 26 32 41 17l168-168c9.3-9.4 9.3-24.6 0-34z"],"sign-language":[448,512,[],"f2a7","M91.434 483.987c-.307-16.018 13.109-29.129 29.13-29.129h62.293v-5.714H56.993c-16.021 0-29.437-13.111-29.13-29.129C28.16 404.491 40.835 392 56.428 392h126.429v-5.714H29.136c-16.021 0-29.437-13.111-29.13-29.129.297-15.522 12.973-28.013 28.566-28.013h154.286v-5.714H57.707c-16.021 0-29.437-13.111-29.13-29.129.297-15.522 12.973-28.013 28.566-28.013h168.566l-31.085-22.606c-12.762-9.281-15.583-27.149-6.302-39.912 9.281-12.761 27.15-15.582 39.912-6.302l123.361 89.715a34.287 34.287 0 0 1 14.12 27.728v141.136c0 15.91-10.946 29.73-26.433 33.374l-80.471 18.934a137.16 137.16 0 0 1-31.411 3.646H120c-15.593-.001-28.269-12.492-28.566-28.014zm73.249-225.701h36.423l-11.187-8.136c-18.579-13.511-20.313-40.887-3.17-56.536l-13.004-16.7c-9.843-12.641-28.43-15.171-40.88-5.088-12.065 9.771-14.133 27.447-4.553 39.75l36.371 46.71zm283.298-2.103l-5.003-152.452c-.518-15.771-13.722-28.136-29.493-27.619-15.773.518-28.137 13.722-27.619 29.493l1.262 38.415L283.565 11.019c-9.58-12.303-27.223-14.63-39.653-5.328-12.827 9.599-14.929 28.24-5.086 40.881l76.889 98.745-4.509 3.511-94.79-121.734c-9.58-12.303-27.223-14.63-39.653-5.328-12.827 9.599-14.929 28.24-5.086 40.881l94.443 121.288-4.509 3.511-77.675-99.754c-9.58-12.303-27.223-14.63-39.653-5.328-12.827 9.599-14.929 28.24-5.086 40.881l52.053 66.849c12.497-8.257 29.055-8.285 41.69.904l123.36 89.714c10.904 7.93 17.415 20.715 17.415 34.198v16.999l61.064-47.549a34.285 34.285 0 0 0 13.202-28.177z"],"sign-out-alt":[512,512,[],"f2f5","M497 273L329 441c-15 15-41 4.5-41-17v-96H152c-13.3 0-24-10.7-24-24v-96c0-13.3 10.7-24 24-24h136V88c0-21.4 25.9-32 41-17l168 168c9.3 9.4 9.3 24.6 0 34zM192 436v-40c0-6.6-5.4-12-12-12H96c-17.7 0-32-14.3-32-32V160c0-17.7 14.3-32 32-32h84c6.6 0 12-5.4 12-12V76c0-6.6-5.4-12-12-12H96c-53 0-96 43-96 96v192c0 53 43 96 96 96h84c6.6 0 12-5.4 12-12z"],signal:[640,512,[],"f012","M36 384h56c6.6 0 12 5.4 12 12v104c0 6.6-5.4 12-12 12H36c-6.6 0-12-5.4-12-12V396c0-6.6 5.4-12 12-12zm116-36v152c0 6.6 5.4 12 12 12h56c6.6 0 12-5.4 12-12V348c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12zm128-80v232c0 6.6 5.4 12 12 12h56c6.6 0 12-5.4 12-12V268c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12zm128-112v344c0 6.6 5.4 12 12 12h56c6.6 0 12-5.4 12-12V156c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12zM536 12v488c0 6.6 5.4 12 12 12h56c6.6 0 12-5.4 12-12V12c0-6.6-5.4-12-12-12h-56c-6.6 0-12 5.4-12 12z"],sitemap:[640,512,[],"f0e8","M616 320h-48v-48c0-22.056-17.944-40-40-40H344v-40h48c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24H248c-13.255 0-24 10.745-24 24v144c0 13.255 10.745 24 24 24h48v40H112c-22.056 0-40 17.944-40 40v48H24c-13.255 0-24 10.745-24 24v144c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24V344c0-13.255-10.745-24-24-24h-48v-40h176v40h-48c-13.255 0-24 10.745-24 24v144c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24V344c0-13.255-10.745-24-24-24h-48v-40h176v40h-48c-13.255 0-24 10.745-24 24v144c0 13.255 10.745 24 24 24h144c13.255 0 24-10.745 24-24V344c0-13.255-10.745-24-24-24z"],"sliders-h":[576,512,[],"f1de","M576 80v40c0 6.6-5.4 12-12 12H160v8c0 13.3-10.7 24-24 24h-16c-13.3 0-24-10.7-24-24v-8H12c-6.6 0-12-5.4-12-12V80c0-6.6 5.4-12 12-12h84v-8c0-13.3 10.7-24 24-24h16c13.3 0 24 10.7 24 24v8h404c6.6 0 12 5.4 12 12zm-12 148h-84v-8c0-13.3-10.7-24-24-24h-16c-13.3 0-24 10.7-24 24v8H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h404v8c0 13.3 10.7 24 24 24h16c13.3 0 24-10.7 24-24v-8h84c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12zm0 160H288v-8c0-13.3-10.7-24-24-24h-16c-13.3 0-24 10.7-24 24v8H12c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h212v8c0 13.3 10.7 24 24 24h16c13.3 0 24-10.7 24-24v-8h276c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12z"],smile:[512,512,[],"f118","M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-122.526 75.34c11.479-17.755-15.349-35.194-26.873-17.374-53.418 82.627-143.71 82.681-197.164 0-11.502-17.79-38.364-.401-26.873 17.374 66.014 102.107 184.795 102.265 250.91 0zM108 192c0 37.497 30.503 68 68 68s68-30.503 68-68-30.503-68-68-68-68 30.503-68 68zm160.5 0c0 37.221 30.279 67.5 67.5 67.5s67.5-30.279 67.5-67.5-30.279-67.5-67.5-67.5-67.5 30.279-67.5 67.5zm67.5-48a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 288 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48zm-160 0a47.789 47.789 0 0 0-22.603 5.647h.015c10.916 0 19.765 8.849 19.765 19.765s-8.849 19.765-19.765 19.765-19.765-8.849-19.765-19.765v-.015A47.789 47.789 0 0 0 128 192c0 26.51 21.49 48 48 48s48-21.49 48-48-21.49-48-48-48z"],snowflake:[448,512,[],"f2dc","M444.816 301.639a24.12 24.12 0 0 0 2.661-16.978c-2.725-12.966-15.339-21.245-28.174-18.492l-87.407 25.046L264 256l67.896-35.215 87.407 25.046c12.835 2.753 25.449-5.526 28.174-18.492 2.725-12.966-5.471-25.708-18.305-28.461l-47.477-7.137 53.077-30.956c11.363-6.627 15.257-21.306 8.696-32.785-6.561-11.479-21.091-15.412-32.454-8.785l-53.077 30.956 17.621-45.104c4.057-12.606-2.768-26.146-15.247-30.245-12.478-4.099-25.883 2.797-29.94 15.402l-22.232 88.99-60.38 35.215V144l65.175-63.945c8.778-9.852 7.987-25.027-1.766-33.894-9.753-8.867-24.775-8.068-33.552 1.784l-29.857 37.967V24c0-13.255-10.637-24-23.758-24s-23.758 10.745-23.758 24v61.912l-29.857-37.967c-8.779-9.852-23.799-10.652-33.552-1.784-9.753 8.867-10.543 24.042-1.766 33.894L200.242 144v70.431l-60.38-35.215-22.232-88.99c-4.057-12.605-17.462-19.501-29.94-15.402-12.478 4.099-19.304 17.64-15.247 30.245l17.62 45.104-53.077-30.956c-11.363-6.627-25.893-2.694-32.454 8.785s-2.667 26.157 8.696 32.785l53.077 30.956-47.477 7.137C5.993 201.634-2.203 214.375.523 227.341c2.725 12.965 15.339 21.245 28.174 18.492l87.407-25.046L184 256l-67.896 35.215-87.406-25.045c-12.835-2.753-25.449 5.526-28.174 18.492-2.725 12.967 5.47 25.708 18.305 28.461l47.477 7.137-53.077 30.956C1.866 357.843-2.027 372.521 4.533 384s21.091 15.412 32.454 8.785l53.077-30.956-17.62 45.104a24.157 24.157 0 0 0 2.022 19.428c2.831 4.953 7.416 8.909 13.224 10.816 12.478 4.099 25.883-2.797 29.94-15.402l22.232-88.99 60.38-35.215V368l-65.175 63.945c-8.778 9.852-7.987 25.027 1.766 33.894 9.754 8.868 24.774 8.068 33.552-1.784l29.857-37.967V488c0 13.255 10.637 24 23.758 24s23.758-10.745 23.758-24v-61.912l29.857 37.967A23.59 23.59 0 0 0 295.282 472a23.534 23.534 0 0 0 15.885-6.161c9.753-8.867 10.544-24.042 1.766-33.894L247.758 368v-70.431l60.38 35.215 22.232 88.99c4.057 12.605 17.462 19.501 29.94 15.402 12.479-4.099 19.304-17.64 15.247-30.245l-17.621-45.104 53.077 30.956c11.363 6.627 25.893 2.694 32.454-8.785s2.667-26.157-8.696-32.785l-53.077-30.956 47.477-7.137c6.86-1.469 12.394-5.793 15.645-11.481z"],sort:[320,512,[],"f0dc","M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41zm255-105L177 64c-9.4-9.4-24.6-9.4-33.9 0L24 183c-15.1 15.1-4.4 41 17 41h238c21.4 0 32.1-25.9 17-41z"],"sort-alpha-down":[448,512,[],"f15d","M187.298 395.314l-79.984 80.002c-6.248 6.247-16.383 6.245-22.627 0L4.705 395.314C-5.365 385.244 1.807 368 16.019 368H64V48c0-8.837 7.163-16 16-16h32c8.837 0 16 7.163 16 16v320h47.984c14.241 0 21.363 17.264 11.314 27.314zm119.075-180.007A12 12 0 0 1 294.838 224h-35.717c-8.22 0-14.007-8.078-11.362-15.861l57.096-168A12 12 0 0 1 316.217 32h39.566c5.139 0 9.708 3.273 11.362 8.139l57.096 168C426.886 215.922 421.1 224 412.879 224h-35.735a12 12 0 0 1-11.515-8.622l-8.301-28.299h-42.863l-8.092 28.228zm22.857-78.697h13.367l-6.6-22.937-6.767 22.937zm12.575 287.323l67.451-95.698a12 12 0 0 0 2.192-6.913V300c0-6.627-5.373-12-12-12H274.522c-6.627 0-12 5.373-12 12v28.93c0 6.627 5.373 12 12 12h56.469c-.739.991-1.497 2.036-2.27 3.133l-67.203 95.205a12.001 12.001 0 0 0-2.196 6.92V468c0 6.627 5.373 12 12 12h129.355c6.627 0 12-5.373 12-12v-28.93c0-6.627-5.373-12-12-12h-61.146c.74-.993 1.5-2.039 2.274-3.137z"],"sort-alpha-up":[448,512,[],"f15e","M4.702 116.686l79.984-80.002c6.248-6.247 16.383-6.245 22.627 0l79.981 80.002c10.07 10.07 2.899 27.314-11.314 27.314H128v320c0 8.837-7.163 16-16 16H80c-8.837 0-16-7.163-16-16V144H16.016c-14.241 0-21.363-17.264-11.314-27.314zm301.671 98.621A12 12 0 0 1 294.838 224h-35.717c-8.22 0-14.007-8.078-11.362-15.861l57.096-168A12 12 0 0 1 316.217 32h39.566c5.139 0 9.708 3.273 11.362 8.139l57.096 168C426.886 215.922 421.1 224 412.879 224h-35.735a12 12 0 0 1-11.515-8.622l-8.301-28.299h-42.863l-8.092 28.228zm22.857-78.697h13.367l-6.6-22.937-6.767 22.937zm12.575 287.323l67.451-95.698a12 12 0 0 0 2.192-6.913V300c0-6.627-5.373-12-12-12H274.522c-6.627 0-12 5.373-12 12v28.93c0 6.627 5.373 12 12 12h56.469c-.739.991-1.497 2.036-2.27 3.133l-67.203 95.205a12.001 12.001 0 0 0-2.196 6.92V468c0 6.627 5.373 12 12 12h129.355c6.627 0 12-5.373 12-12v-28.93c0-6.627-5.373-12-12-12h-61.146c.74-.993 1.5-2.039 2.274-3.137z"],"sort-amount-down":[512,512,[],"f160","M187.298 395.314l-79.984 80.002c-6.248 6.247-16.383 6.245-22.627 0L4.705 395.314C-5.365 385.244 1.807 368 16.019 368H64V48c0-8.837 7.163-16 16-16h32c8.837 0 16 7.163 16 16v320h47.984c14.241 0 21.363 17.264 11.314 27.314zM240 96h256c8.837 0 16-7.163 16-16V48c0-8.837-7.163-16-16-16H240c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16zm-16 112v-32c0-8.837 7.163-16 16-16h192c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H240c-8.837 0-16-7.163-16-16zm0 256v-32c0-8.837 7.163-16 16-16h64c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-64c-8.837 0-16-7.163-16-16zm0-128v-32c0-8.837 7.163-16 16-16h128c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H240c-8.837 0-16-7.163-16-16z"],"sort-amount-up":[512,512,[],"f161","M4.702 116.686l79.984-80.002c6.248-6.247 16.383-6.245 22.627 0l79.981 80.002c10.07 10.07 2.899 27.314-11.314 27.314H128v320c0 8.837-7.163 16-16 16H80c-8.837 0-16-7.163-16-16V144H16.016c-14.241 0-21.363-17.264-11.314-27.314zM240 96h256c8.837 0 16-7.163 16-16V48c0-8.837-7.163-16-16-16H240c-8.837 0-16 7.163-16 16v32c0 8.837 7.163 16 16 16zm-16 112v-32c0-8.837 7.163-16 16-16h192c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H240c-8.837 0-16-7.163-16-16zm0 256v-32c0-8.837 7.163-16 16-16h64c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-64c-8.837 0-16-7.163-16-16zm0-128v-32c0-8.837 7.163-16 16-16h128c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H240c-8.837 0-16-7.163-16-16z"],"sort-down":[320,512,[],"f0dd","M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41z"],"sort-numeric-down":[448,512,[],"f162","M308.811 113.787l-19.448-20.795c-4.522-4.836-4.274-12.421.556-16.95l43.443-40.741a11.999 11.999 0 0 1 8.209-3.247h31.591c6.627 0 12 5.373 12 12v127.07h25.66c6.627 0 12 5.373 12 12v28.93c0 6.627-5.373 12-12 12H301.649c-6.627 0-12-5.373-12-12v-28.93c0-6.627 5.373-12 12-12h25.414v-57.938c-7.254 6.58-14.211 4.921-18.252.601zm-30.57 238.569c0-32.653 23.865-67.356 68.094-67.356 38.253 0 79.424 28.861 79.424 92.228 0 51.276-32.237 105.772-91.983 105.772-17.836 0-30.546-3.557-38.548-6.781-5.79-2.333-8.789-8.746-6.922-14.703l9.237-29.48c2.035-6.496 9.049-9.983 15.467-7.716 13.029 4.602 27.878 5.275 38.103-4.138-38.742 5.072-72.872-25.36-72.872-67.826zm92.273 19.338c0-22.285-15.302-36.505-25.835-36.505-8.642 0-13.164 7.965-13.164 15.832 0 5.669 1.815 24.168 25.168 24.168 9.973 0 13.377-2.154 13.744-2.731.021-.046.087-.291.087-.764zM175.984 368H128V48c0-8.837-7.163-16-16-16H80c-8.837 0-16 7.163-16 16v320H16.019c-14.212 0-21.384 17.244-11.314 27.314l79.981 80.002c6.245 6.245 16.38 6.247 22.627 0l79.984-80.002c10.05-10.05 2.928-27.314-11.313-27.314z"],"sort-numeric-up":[448,512,[],"f163","M308.811 113.787l-19.448-20.795c-4.522-4.836-4.274-12.421.556-16.95l43.443-40.741a11.999 11.999 0 0 1 8.209-3.247h31.591c6.627 0 12 5.373 12 12v127.07h25.66c6.627 0 12 5.373 12 12v28.93c0 6.627-5.373 12-12 12H301.649c-6.627 0-12-5.373-12-12v-28.93c0-6.627 5.373-12 12-12h25.414v-57.938c-7.254 6.58-14.211 4.921-18.252.601zm-30.57 238.569c0-32.653 23.865-67.356 68.094-67.356 38.253 0 79.424 28.861 79.424 92.228 0 51.276-32.237 105.772-91.983 105.772-17.836 0-30.546-3.557-38.548-6.781-5.79-2.333-8.789-8.746-6.922-14.703l9.237-29.48c2.035-6.496 9.049-9.983 15.467-7.716 13.029 4.602 27.878 5.275 38.103-4.138-38.742 5.072-72.872-25.36-72.872-67.826zm92.273 19.338c0-22.285-15.302-36.505-25.835-36.505-8.642 0-13.164 7.965-13.164 15.832 0 5.669 1.815 24.168 25.168 24.168 9.973 0 13.377-2.154 13.744-2.731.021-.046.087-.291.087-.764zM16.016 144H64v320c0 8.837 7.163 16 16 16h32c8.837 0 16-7.163 16-16V144h47.981c14.212 0 21.384-17.244 11.314-27.314l-79.981-80.002c-6.245-6.245-16.38-6.247-22.627 0L4.702 116.686C-5.347 126.736 1.775 144 16.016 144z"],"sort-up":[320,512,[],"f0de","M279 224H41c-21.4 0-32.1-25.9-17-41L143 64c9.4-9.4 24.6-9.4 33.9 0l119 119c15.2 15.1 4.5 41-16.9 41z"],"space-shuttle":[640,512,[],"f197","M592.604 208.244C559.735 192.836 515.777 184 472 184H186.327c-4.952-6.555-10.585-11.978-16.72-16H376C229.157 137.747 219.403 32 96.003 32H96v128H80V32c-26.51 0-48 28.654-48 64v64c-23.197 0-32 10.032-32 24v40c0 13.983 8.819 24 32 24v16c-23.197 0-32 10.032-32 24v40c0 13.983 8.819 24 32 24v64c0 35.346 21.49 64 48 64V352h16v128h.003c123.4 0 133.154-105.747 279.997-136H169.606c6.135-4.022 11.768-9.445 16.72-16H472c43.777 0 87.735-8.836 120.604-24.244C622.282 289.845 640 271.992 640 256s-17.718-33.845-47.396-47.756zM488 296a8 8 0 0 1-8-8v-64a8 8 0 0 1 8-8c31.909 0 31.942 80 0 80z"],spinner:[512,512,[],"f110","M304 48c0 26.51-21.49 48-48 48s-48-21.49-48-48 21.49-48 48-48 48 21.49 48 48zm-48 368c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm208-208c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zM96 256c0-26.51-21.49-48-48-48S0 229.49 0 256s21.49 48 48 48 48-21.49 48-48zm12.922 99.078c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.491-48-48-48zm294.156 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48c0-26.509-21.49-48-48-48zM108.922 60.922c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.491-48-48-48z"],square:[448,512,[],"f0c8","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48z"],star:[576,512,[],"f005","M259.3 17.8L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0z"],"star-half":[576,512,[],"f089","M288 0c-11.4 0-22.8 5.9-28.7 17.8L194 150.2 47.9 171.4c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.1 23 46 46.4 33.7L288 439.6V0z"],"step-backward":[448,512,[],"f048","M64 468V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12v176.4l195.5-181C352.1 22.3 384 36.6 384 64v384c0 27.4-31.9 41.7-52.5 24.6L136 292.7V468c0 6.6-5.4 12-12 12H76c-6.6 0-12-5.4-12-12z"],"step-forward":[448,512,[],"f051","M384 44v424c0 6.6-5.4 12-12 12h-48c-6.6 0-12-5.4-12-12V291.6l-195.5 181C95.9 489.7 64 475.4 64 448V64c0-27.4 31.9-41.7 52.5-24.6L312 219.3V44c0-6.6 5.4-12 12-12h48c6.6 0 12 5.4 12 12z"],stethoscope:[512,512,[],"f0f1","M512 176c0-35.659-29.164-64.507-64.941-63.993-34.21.492-62.296 28.357-63.043 62.562-.531 24.282 12.476 45.558 31.984 56.848V344c0 57.346-50.243 104-112 104-60.039 0-109.189-44.096-111.878-99.24C265.005 333.847 320 269.225 320 192V36.584c0-11.44-8.075-21.29-19.293-23.534L237.81.471c-12.997-2.599-25.641 5.83-28.241 18.827l-3.138 15.689c-2.6 12.997 5.83 25.641 18.827 28.241L256 69.376v121.4c0 52.852-42.203 96.707-95.053 97.22C107.58 288.513 64 245.25 64 192V69.376l30.742-6.149c12.997-2.6 21.427-15.243 18.827-28.241l-3.138-15.689C107.831 6.3 95.188-2.129 82.19.471L19.293 13.05C8.075 15.294 0 25.144 0 36.584V192c0 77.295 55.096 141.961 128.076 156.798C130.747 439.223 208.634 512 304 512c97.047 0 176-75.364 176-168V231.417c19.124-11.068 32-31.732 32-55.417zm-64-16c8.822 0 16 7.178 16 16s-7.178 16-16 16-16-7.178-16-16 7.178-16 16-16z"],"sticky-note":[448,512,[],"f249","M312 320h136V56c0-13.3-10.7-24-24-24H24C10.7 32 0 42.7 0 56v400c0 13.3 10.7 24 24 24h264V344c0-13.2 10.8-24 24-24zm129 55l-98 98c-4.5 4.5-10.6 7-17 7h-6V352h128v6.1c0 6.3-2.5 12.4-7 16.9z"],stop:[448,512,[],"f04d","M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48z"],"stop-circle":[512,512,[],"f28d","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm96 328c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V176c0-8.8 7.2-16 16-16h160c8.8 0 16 7.2 16 16v160z"],"street-view":[512,512,[],"f21d","M192 64c0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64s-64-28.654-64-64zm112 80h-11.36c-22.711 10.443-49.59 10.894-73.28 0H208c-26.51 0-48 21.49-48 48v104c0 13.255 10.745 24 24 24h16v104c0 13.255 10.745 24 24 24h64c13.255 0 24-10.745 24-24V320h16c13.255 0 24-10.745 24-24V192c0-26.51-21.49-48-48-48zm85.642 189.152a72.503 72.503 0 0 1-29.01 27.009C391.133 365.251 480 385.854 480 416c0 46.304-167.656 64-224 64-70.303 0-224-20.859-224-64 0-30.123 88.361-50.665 119.367-55.839a72.516 72.516 0 0 1-29.01-27.009C74.959 343.395 0 367.599 0 416c0 77.111 178.658 96 256 96 77.249 0 256-18.865 256-96 0-48.403-74.967-72.606-122.358-82.848z"],strikethrough:[512,512,[],"f0cc","M496 288H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h480c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16zm-214.666 16c27.258 12.937 46.524 28.683 46.524 56.243 0 33.108-28.977 53.676-75.621 53.676-32.325 0-76.874-12.08-76.874-44.271V368c0-8.837-7.164-16-16-16H113.75c-8.836 0-16 7.163-16 16v19.204c0 66.845 77.717 101.82 154.487 101.82 88.578 0 162.013-45.438 162.013-134.424 0-19.815-3.618-36.417-10.143-50.6H281.334zm-30.952-96c-32.422-13.505-56.836-28.946-56.836-59.683 0-33.92 30.901-47.406 64.962-47.406 42.647 0 64.962 16.593 64.962 32.985V136c0 8.837 7.164 16 16 16h45.613c8.836 0 16-7.163 16-16v-30.318c0-52.438-71.725-79.875-142.575-79.875-85.203 0-150.726 40.972-150.726 125.646 0 22.71 4.665 41.176 12.777 56.547h129.823z"],subscript:[512,512,[],"f12c","M395.198 416c3.461-10.526 18.796-21.28 36.265-32.425 16.625-10.605 35.467-22.626 50.341-38.862 17.458-19.054 25.944-40.175 25.944-64.567 0-60.562-50.702-88.146-97.81-88.146-42.491 0-76.378 22.016-94.432 50.447-4.654 7.329-2.592 17.036 4.623 21.865l30.328 20.296c7.032 4.706 16.46 3.084 21.63-3.614 8.022-10.394 18.818-18.225 31.667-18.225 19.387 0 26.266 12.901 26.266 23.948 0 36.159-119.437 57.023-119.437 160.024 0 6.654.561 13.014 1.415 19.331 1.076 7.964 7.834 13.928 15.87 13.928H496c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16H395.198zM272 256c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-62.399a16 16 0 0 1-13.541-7.478l-45.701-72.615c-2.297-3.352-4.422-6.969-6.195-10.209-1.65 3.244-3.647 6.937-5.874 10.582l-44.712 72.147a15.999 15.999 0 0 1-13.6 7.572H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h26.325l56.552-82.709L46.111 96H16C7.163 96 0 88.837 0 80V48c0-8.837 7.163-16 16-16h68.806a16 16 0 0 1 13.645 7.644l39.882 65.126c2.072 3.523 4.053 7.171 5.727 10.37 1.777-3.244 3.92-6.954 6.237-10.537l40.332-65.035A15.999 15.999 0 0 1 204.226 32H272c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-27.979l-52.69 75.671L249.974 256H272z"],subway:[448,512,[],"f239","M448 96v256c0 51.815-61.624 96-130.022 96l62.98 49.721C386.905 502.417 383.562 512 376 512H72c-7.578 0-10.892-9.594-4.957-14.279L130.022 448C61.82 448 0 403.954 0 352V96C0 42.981 64 0 128 0h192c65 0 128 42.981 128 96zM200 232V120c0-13.255-10.745-24-24-24H72c-13.255 0-24 10.745-24 24v112c0 13.255 10.745 24 24 24h104c13.255 0 24-10.745 24-24zm200 0V120c0-13.255-10.745-24-24-24H272c-13.255 0-24 10.745-24 24v112c0 13.255 10.745 24 24 24h104c13.255 0 24-10.745 24-24zm-48 56c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48zm-256 0c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"],suitcase:[512,512,[],"f0f2","M96 480h320V128h-32V80c0-26.51-21.49-48-48-48H176c-26.51 0-48 21.49-48 48v48H96v352zm96-384h128v32H192V96zm320 80v256c0 26.51-21.49 48-48 48h-16V128h16c26.51 0 48 21.49 48 48zM64 480H48c-26.51 0-48-21.49-48-48V176c0-26.51 21.49-48 48-48h16v352z"],sun:[512,512,[],"f185","M274.835 12.646l25.516 62.393c4.213 10.301 16.671 14.349 26.134 8.492l57.316-35.479c15.49-9.588 34.808 4.447 30.475 22.142l-16.03 65.475c-2.647 10.81 5.053 21.408 16.152 22.231l67.224 4.987c18.167 1.348 25.546 24.057 11.641 35.826L441.81 242.26c-8.495 7.19-8.495 20.289 0 27.479l51.454 43.548c13.906 11.769 6.527 34.478-11.641 35.826l-67.224 4.987c-11.099.823-18.799 11.421-16.152 22.231l16.03 65.475c4.332 17.695-14.986 31.73-30.475 22.142l-57.316-35.479c-9.463-5.858-21.922-1.81-26.134 8.492l-25.516 62.393c-6.896 16.862-30.774 16.862-37.67 0l-25.516-62.393c-4.213-10.301-16.671-14.349-26.134-8.492l-57.317 35.479c-15.49 9.588-34.808-4.447-30.475-22.142l16.03-65.475c2.647-10.81-5.053-21.408-16.152-22.231l-67.224-4.987c-18.167-1.348-25.546-24.057-11.641-35.826L70.19 269.74c8.495-7.19 8.495-20.289 0-27.479l-51.454-43.548c-13.906-11.769-6.527-34.478 11.641-35.826l67.224-4.987c11.099-.823 18.799-11.421 16.152-22.231l-16.03-65.475c-4.332-17.695 14.986-31.73 30.475-22.142l57.317 35.479c9.463 5.858 21.921 1.81 26.134-8.492l25.516-62.393c6.896-16.861 30.774-16.861 37.67 0zM392 256c0-74.991-61.01-136-136-136-74.991 0-136 61.009-136 136s61.009 136 136 136c74.99 0 136-61.009 136-136zm-32 0c0 57.346-46.654 104-104 104s-104-46.654-104-104 46.654-104 104-104 104 46.654 104 104z"],superscript:[512,512,[],"f12b","M395.198 256c3.461-10.526 18.796-21.28 36.265-32.425 16.625-10.605 35.467-22.626 50.341-38.862 17.458-19.054 25.944-40.175 25.944-64.567 0-60.562-50.702-88.146-97.81-88.146-42.491 0-76.378 22.016-94.432 50.447-4.654 7.329-2.592 17.036 4.623 21.865l30.328 20.296c7.032 4.706 16.46 3.084 21.63-3.614 8.022-10.394 18.818-18.225 31.667-18.225 19.387 0 26.266 12.901 26.266 23.948 0 36.159-119.437 57.023-119.437 160.024 0 6.654.561 13.014 1.415 19.331 1.076 7.964 7.834 13.928 15.87 13.928H496c8.837 0 16-7.163 16-16v-32c0-8.837-7.163-16-16-16H395.198zM272 416c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-62.399a16 16 0 0 1-13.541-7.478l-45.701-72.615c-2.297-3.352-4.422-6.969-6.195-10.209-1.65 3.244-3.647 6.937-5.874 10.582l-44.712 72.147a15.999 15.999 0 0 1-13.6 7.572H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h26.325l56.552-82.709L46.111 256H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h68.806a16 16 0 0 1 13.645 7.644l39.882 65.126c2.072 3.523 4.053 7.171 5.727 10.37 1.777-3.244 3.92-6.954 6.237-10.537l40.332-65.035a16 16 0 0 1 13.598-7.567H272c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-27.979l-52.69 75.671L249.974 416H272z"],sync:[512,512,[],"f021","M440.935 12.574l3.966 82.766C399.416 41.904 331.674 8 256 8 134.813 8 33.933 94.924 12.296 209.824 10.908 217.193 16.604 224 24.103 224h49.084c5.57 0 10.377-3.842 11.676-9.259C103.407 137.408 172.931 80 256 80c60.893 0 114.512 30.856 146.104 77.801l-101.53-4.865c-6.845-.328-12.574 5.133-12.574 11.986v47.411c0 6.627 5.373 12 12 12h200.333c6.627 0 12-5.373 12-12V12c0-6.627-5.373-12-12-12h-47.411c-6.853 0-12.315 5.729-11.987 12.574zM256 432c-60.895 0-114.517-30.858-146.109-77.805l101.868 4.871c6.845.327 12.573-5.134 12.573-11.986v-47.412c0-6.627-5.373-12-12-12H12c-6.627 0-12 5.373-12 12V500c0 6.627 5.373 12 12 12h47.385c6.863 0 12.328-5.745 11.985-12.599l-4.129-82.575C112.725 470.166 180.405 504 256 504c121.187 0 222.067-86.924 243.704-201.824 1.388-7.369-4.308-14.176-11.807-14.176h-49.084c-5.57 0-10.377 3.842-11.676 9.259C408.593 374.592 339.069 432 256 432z"],"sync-alt":[512,512,[],"f2f1","M370.72 133.28C339.458 104.008 298.888 87.962 255.848 88c-77.458.068-144.328 53.178-162.791 126.85-1.344 5.363-6.122 9.15-11.651 9.15H24.103c-7.498 0-13.194-6.807-11.807-14.176C33.933 94.924 134.813 8 256 8c66.448 0 126.791 26.136 171.315 68.685L463.03 40.97C478.149 25.851 504 36.559 504 57.941V192c0 13.255-10.745 24-24 24H345.941c-21.382 0-32.09-25.851-16.971-40.971l41.75-41.749zM32 296h134.059c21.382 0 32.09 25.851 16.971 40.971l-41.75 41.75c31.262 29.273 71.835 45.319 114.876 45.28 77.418-.07 144.315-53.144 162.787-126.849 1.344-5.363 6.122-9.15 11.651-9.15h57.304c7.498 0 13.194 6.807 11.807 14.176C478.067 417.076 377.187 504 256 504c-66.448 0-126.791-26.136-171.315-68.685L48.97 471.03C33.851 486.149 8 475.441 8 454.059V320c0-13.255 10.745-24 24-24z"],table:[512,512,[],"f0ce","M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64v-96h160v96zm0-160H64v-96h160v96zm224 160H288v-96h160v96zm0-160H288v-96h160v96z"],tablet:[448,512,[],"f10a","M400 0H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM224 480c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32z"],"tablet-alt":[448,512,[],"f3fa","M400 0H48C21.5 0 0 21.5 0 48v416c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zM224 480c-17.7 0-32-14.3-32-32s14.3-32 32-32 32 14.3 32 32-14.3 32-32 32zm176-108c0 6.6-5.4 12-12 12H60c-6.6 0-12-5.4-12-12V60c0-6.6 5.4-12 12-12h328c6.6 0 12 5.4 12 12v312z"],"tachometer-alt":[576,512,[],"f3fd","M75.694 480a48.02 48.02 0 0 1-42.448-25.571C12.023 414.3 0 368.556 0 320 0 160.942 128.942 32 288 32s288 128.942 288 288c0 48.556-12.023 94.3-33.246 134.429A48.018 48.018 0 0 1 500.306 480H75.694zM512 288c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32zM288 128c17.673 0 32-14.327 32-32 0-17.673-14.327-32-32-32s-32 14.327-32 32c0 17.673 14.327 32 32 32zM64 288c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32zm65.608-158.392c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32zm316.784 0c-17.673 0-32 14.327-32 32 0 17.673 14.327 32 32 32s32-14.327 32-32c0-17.673-14.327-32-32-32zm-87.078 31.534c-12.627-4.04-26.133 2.92-30.173 15.544l-45.923 143.511C250.108 322.645 224 350.264 224 384c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-19.773-8.971-37.447-23.061-49.187l45.919-143.498c4.039-12.625-2.92-26.133-15.544-30.173z"],tag:[512,512,[],"f02b","M0 252.118V48C0 21.49 21.49 0 48 0h204.118a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882L293.823 497.941c-18.745 18.745-49.137 18.745-67.882 0L14.059 286.059A48 48 0 0 1 0 252.118zM112 64c-26.51 0-48 21.49-48 48s21.49 48 48 48 48-21.49 48-48-21.49-48-48-48z"],tags:[640,512,[],"f02c","M497.941 225.941L286.059 14.059A48 48 0 0 0 252.118 0H48C21.49 0 0 21.49 0 48v204.118a48 48 0 0 0 14.059 33.941l211.882 211.882c18.744 18.745 49.136 18.746 67.882 0l204.118-204.118c18.745-18.745 18.745-49.137 0-67.882zM112 160c-26.51 0-48-21.49-48-48s21.49-48 48-48 48 21.49 48 48-21.49 48-48 48zm513.941 133.823L421.823 497.941c-18.745 18.745-49.137 18.745-67.882 0l-.36-.36L527.64 323.522c16.999-16.999 26.36-39.6 26.36-63.64s-9.362-46.641-26.36-63.64L331.397 0h48.721a48 48 0 0 1 33.941 14.059l211.882 211.882c18.745 18.745 18.745 49.137 0 67.882z"],tasks:[512,512,[],"f0ae","M208 132h288c8.8 0 16-7.2 16-16V76c0-8.8-7.2-16-16-16H208c-8.8 0-16 7.2-16 16v40c0 8.8 7.2 16 16 16zm0 160h288c8.8 0 16-7.2 16-16v-40c0-8.8-7.2-16-16-16H208c-8.8 0-16 7.2-16 16v40c0 8.8 7.2 16 16 16zm0 160h288c8.8 0 16-7.2 16-16v-40c0-8.8-7.2-16-16-16H208c-8.8 0-16 7.2-16 16v40c0 8.8 7.2 16 16 16zM64 368c-26.5 0-48.6 21.5-48.6 48s22.1 48 48.6 48 48-21.5 48-48-21.5-48-48-48zm92.5-299l-72.2 72.2-15.6 15.6c-4.7 4.7-12.9 4.7-17.6 0L3.5 109.4c-4.7-4.7-4.7-12.3 0-17l15.7-15.7c4.7-4.7 12.3-4.7 17 0l22.7 22.1 63.7-63.3c4.7-4.7 12.3-4.7 17 0l17 16.5c4.6 4.7 4.6 12.3-.1 17zm0 159.6l-72.2 72.2-15.7 15.7c-4.7 4.7-12.9 4.7-17.6 0L3.5 269c-4.7-4.7-4.7-12.3 0-17l15.7-15.7c4.7-4.7 12.3-4.7 17 0l22.7 22.1 63.7-63.7c4.7-4.7 12.3-4.7 17 0l17 17c4.6 4.6 4.6 12.2-.1 16.9z"],taxi:[512,512,[],"f1ba","M461.951 243.865l-21.816-87.268A79.885 79.885 0 0 0 362.522 96H352V56c0-13.255-10.745-24-24-24H184c-13.255 0-24 10.745-24 24v40h-10.522a79.885 79.885 0 0 0-77.612 60.597L50.05 243.865C25.515 252.823 8 276.366 8 304v48c0 20.207 9.374 38.214 24 49.943V456c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24v-40h256v40c0 13.255 10.745 24 24 24h48c13.255 0 24-10.745 24-24v-54.057c14.626-11.729 24-29.737 24-49.943v-48c0-27.634-17.515-51.177-42.049-60.135zM149.478 160h213.045a15.975 15.975 0 0 1 15.522 12.12l16.97 67.88h-278.03l16.97-67.881A15.976 15.976 0 0 1 149.478 160zM132 336c0 19.882-16.118 36-36 36s-36-16.118-36-36 16.118-36 36-36 36 16.118 36 36zm320 0c0 19.882-16.118 36-36 36s-36-16.118-36-36 16.118-36 36-36 36 16.118 36 36z"],terminal:[640,512,[],"f120","M257.981 272.971L63.638 467.314c-9.373 9.373-24.569 9.373-33.941 0L7.029 444.647c-9.357-9.357-9.375-24.522-.04-33.901L161.011 256 6.99 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L257.981 239.03c9.373 9.372 9.373 24.568 0 33.941zM640 456v-32c0-13.255-10.745-24-24-24H312c-13.255 0-24 10.745-24 24v32c0 13.255 10.745 24 24 24h304c13.255 0 24-10.745 24-24z"],"text-height":[576,512,[],"f034","M16 32h288c8.837 0 16 7.163 16 16v96c0 8.837-7.163 16-16 16h-35.496c-8.837 0-16-7.163-16-16V96h-54.761v320H232c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H88c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h34.257V96H67.496v48c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16V48c0-8.837 7.163-16 16-16zm475.308 4.685l79.995 80.001C581.309 126.693 574.297 144 559.99 144H512v224h48c15.639 0 20.635 17.991 11.313 27.314l-79.995 80.001c-6.247 6.247-16.381 6.245-22.626 0l-79.995-80.001C378.691 385.307 385.703 368 400.01 368H448V144h-48c-15.639 0-20.635-17.991-11.313-27.314l79.995-80.001c6.247-6.248 16.381-6.245 22.626 0z"],"text-width":[448,512,[],"f035","M16 32h416c8.837 0 16 7.163 16 16v96c0 8.837-7.163 16-16 16h-35.496c-8.837 0-16-7.163-16-16V96H261.743v128H296c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H152c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16h34.257V96H67.496v48c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16V48c0-8.837 7.163-16 16-16zm427.315 340.682l-80.001-79.995C353.991 283.365 336 288.362 336 304v48H112v-47.99c0-14.307-17.307-21.319-27.314-11.313L4.685 372.692c-6.245 6.245-6.247 16.379 0 22.626l80.001 79.995C94.009 484.635 112 479.638 112 464v-48h224v47.99c0 14.307 17.307 21.319 27.314 11.313l80.001-79.995c6.245-6.245 6.248-16.379 0-22.626z"],th:[512,512,[],"f00a","M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z"],"th-large":[512,512,[],"f009","M296 32h192c13.255 0 24 10.745 24 24v160c0 13.255-10.745 24-24 24H296c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24zm-80 0H24C10.745 32 0 42.745 0 56v160c0 13.255 10.745 24 24 24h192c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24zM0 296v160c0 13.255 10.745 24 24 24h192c13.255 0 24-10.745 24-24V296c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm296 184h192c13.255 0 24-10.745 24-24V296c0-13.255-10.745-24-24-24H296c-13.255 0-24 10.745-24 24v160c0 13.255 10.745 24 24 24z"],"th-list":[512,512,[],"f00b","M149.333 216v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-80c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zM125.333 32H24C10.745 32 0 42.745 0 56v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24zm80 448H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm-24-424v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24zm24 264H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24z"],"thermometer-empty":[256,512,[],"f2cb","M192 384c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-35.346 28.654-64 64-64s64 28.654 64 64zm32-84.653c19.912 22.563 32 52.194 32 84.653 0 70.696-57.303 128-128 128-.299 0-.609-.001-.909-.003C56.789 511.509-.357 453.636.002 383.333.166 351.135 12.225 321.755 32 299.347V96c0-53.019 42.981-96 96-96s96 42.981 96 96v203.347zM208 384c0-34.339-19.37-52.19-32-66.502V96c0-26.467-21.533-48-48-48S80 69.533 80 96v221.498c-12.732 14.428-31.825 32.1-31.999 66.08-.224 43.876 35.563 80.116 79.423 80.42L128 464c44.112 0 80-35.888 80-80z"],"thermometer-full":[256,512,[],"f2c7","M224 96c0-53.019-42.981-96-96-96S32 42.981 32 96v203.347C12.225 321.756.166 351.136.002 383.333c-.359 70.303 56.787 128.176 127.089 128.664.299.002.61.003.909.003 70.698 0 128-57.304 128-128 0-32.459-12.088-62.09-32-84.653V96zm-96 368l-.576-.002c-43.86-.304-79.647-36.544-79.423-80.42.173-33.98 19.266-51.652 31.999-66.08V96c0-26.467 21.533-48 48-48s48 21.533 48 48v221.498c12.63 14.312 32 32.164 32 66.502 0 44.112-35.888 80-80 80zm64-80c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-23.685 12.876-44.349 32-55.417V96c0-17.673 14.327-32 32-32s32 14.327 32 32v232.583c19.124 11.068 32 31.732 32 55.417z"],"thermometer-half":[256,512,[],"f2c9","M192 384c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-23.685 12.876-44.349 32-55.417V224c0-17.673 14.327-32 32-32s32 14.327 32 32v104.583c19.124 11.068 32 31.732 32 55.417zm32-84.653c19.912 22.563 32 52.194 32 84.653 0 70.696-57.303 128-128 128-.299 0-.609-.001-.909-.003C56.789 511.509-.357 453.636.002 383.333.166 351.135 12.225 321.755 32 299.347V96c0-53.019 42.981-96 96-96s96 42.981 96 96v203.347zM208 384c0-34.339-19.37-52.19-32-66.502V96c0-26.467-21.533-48-48-48S80 69.533 80 96v221.498c-12.732 14.428-31.825 32.1-31.999 66.08-.224 43.876 35.563 80.116 79.423 80.42L128 464c44.112 0 80-35.888 80-80z"],"thermometer-quarter":[256,512,[],"f2ca","M192 384c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-23.685 12.876-44.349 32-55.417V288c0-17.673 14.327-32 32-32s32 14.327 32 32v40.583c19.124 11.068 32 31.732 32 55.417zm32-84.653c19.912 22.563 32 52.194 32 84.653 0 70.696-57.303 128-128 128-.299 0-.609-.001-.909-.003C56.789 511.509-.357 453.636.002 383.333.166 351.135 12.225 321.755 32 299.347V96c0-53.019 42.981-96 96-96s96 42.981 96 96v203.347zM208 384c0-34.339-19.37-52.19-32-66.502V96c0-26.467-21.533-48-48-48S80 69.533 80 96v221.498c-12.732 14.428-31.825 32.1-31.999 66.08-.224 43.876 35.563 80.116 79.423 80.42L128 464c44.112 0 80-35.888 80-80z"],"thermometer-three-quarters":[256,512,[],"f2c8","M192 384c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64 0-23.685 12.876-44.349 32-55.417V160c0-17.673 14.327-32 32-32s32 14.327 32 32v168.583c19.124 11.068 32 31.732 32 55.417zm32-84.653c19.912 22.563 32 52.194 32 84.653 0 70.696-57.303 128-128 128-.299 0-.609-.001-.909-.003C56.789 511.509-.357 453.636.002 383.333.166 351.135 12.225 321.755 32 299.347V96c0-53.019 42.981-96 96-96s96 42.981 96 96v203.347zM208 384c0-34.339-19.37-52.19-32-66.502V96c0-26.467-21.533-48-48-48S80 69.533 80 96v221.498c-12.732 14.428-31.825 32.1-31.999 66.08-.224 43.876 35.563 80.116 79.423 80.42L128 464c44.112 0 80-35.888 80-80z"],"thumbs-down":[512,512,[],"f165","M0 56v240c0 13.255 10.745 24 24 24h80c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H24C10.745 32 0 42.745 0 56zm40 200c0-13.255 10.745-24 24-24s24 10.745 24 24-10.745 24-24 24-24-10.745-24-24zm272 256c-20.183 0-29.485-39.293-33.931-57.795-5.206-21.666-10.589-44.07-25.393-58.902-32.469-32.524-49.503-73.967-89.117-113.111a11.98 11.98 0 0 1-3.558-8.521V59.901c0-6.541 5.243-11.878 11.783-11.998 15.831-.29 36.694-9.079 52.651-16.178C256.189 17.598 295.709.017 343.995 0h2.844c42.777 0 93.363.413 113.774 29.737 8.392 12.057 10.446 27.034 6.148 44.632 16.312 17.053 25.063 48.863 16.382 74.757 17.544 23.432 19.143 56.132 9.308 79.469l.11.11c11.893 11.949 19.523 31.259 19.439 49.197-.156 30.352-26.157 58.098-59.553 58.098H350.723C358.03 364.34 384 388.132 384 430.548 384 504 336 512 312 512z"],"thumbs-up":[512,512,[],"f164","M104 224H24c-13.255 0-24 10.745-24 24v240c0 13.255 10.745 24 24 24h80c13.255 0 24-10.745 24-24V248c0-13.255-10.745-24-24-24zM64 472c-13.255 0-24-10.745-24-24s10.745-24 24-24 24 10.745 24 24-10.745 24-24 24zM384 81.452c0 42.416-25.97 66.208-33.277 94.548h101.723c33.397 0 59.397 27.746 59.553 58.098.084 17.938-7.546 37.249-19.439 49.197l-.11.11c9.836 23.337 8.237 56.037-9.308 79.469 8.681 25.895-.069 57.704-16.382 74.757 4.298 17.598 2.244 32.575-6.148 44.632C440.202 511.587 389.616 512 346.839 512l-2.845-.001c-48.287-.017-87.806-17.598-119.56-31.725-15.957-7.099-36.821-15.887-52.651-16.178-6.54-.12-11.783-5.457-11.783-11.998v-213.77c0-3.2 1.282-6.271 3.558-8.521 39.614-39.144 56.648-80.587 89.117-113.111 14.804-14.832 20.188-37.236 25.393-58.902C282.515 39.293 291.817 0 312 0c24 0 72 8 72 81.452z"],thumbtack:[384,512,[],"f08d","M298.028 214.267L285.793 96H328c13.255 0 24-10.745 24-24V24c0-13.255-10.745-24-24-24H56C42.745 0 32 10.745 32 24v48c0 13.255 10.745 24 24 24h42.207L85.972 214.267C37.465 236.82 0 277.261 0 328c0 13.255 10.745 24 24 24h136v104.007c0 1.242.289 2.467.845 3.578l24 48c2.941 5.882 11.364 5.893 14.311 0l24-48a8.008 8.008 0 0 0 .845-3.578V352h136c13.255 0 24-10.745 24-24-.001-51.183-37.983-91.42-85.973-113.733z"],"ticket-alt":[576,512,[],"f3ff","M128 160h320v192H128V160zm400 96c0 26.51 21.49 48 48 48v96c0 26.51-21.49 48-48 48H48c-26.51 0-48-21.49-48-48v-96c26.51 0 48-21.49 48-48s-21.49-48-48-48v-96c0-26.51 21.49-48 48-48h480c26.51 0 48 21.49 48 48v96c-26.51 0-48 21.49-48 48zm-48-104c0-13.255-10.745-24-24-24H120c-13.255 0-24 10.745-24 24v208c0 13.255 10.745 24 24 24h336c13.255 0 24-10.745 24-24V152z"],times:[384,512,[],"f00d","M323.1 441l53.9-53.9c9.4-9.4 9.4-24.5 0-33.9L279.8 256l97.2-97.2c9.4-9.4 9.4-24.5 0-33.9L323.1 71c-9.4-9.4-24.5-9.4-33.9 0L192 168.2 94.8 71c-9.4-9.4-24.5-9.4-33.9 0L7 124.9c-9.4 9.4-9.4 24.5 0 33.9l97.2 97.2L7 353.2c-9.4 9.4-9.4 24.5 0 33.9L60.9 441c9.4 9.4 24.5 9.4 33.9 0l97.2-97.2 97.2 97.2c9.3 9.3 24.5 9.3 33.9 0z"],"times-circle":[512,512,[],"f057","M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm121.6 313.1c4.7 4.7 4.7 12.3 0 17L338 377.6c-4.7 4.7-12.3 4.7-17 0L256 312l-65.1 65.6c-4.7 4.7-12.3 4.7-17 0L134.4 338c-4.7-4.7-4.7-12.3 0-17l65.6-65-65.6-65.1c-4.7-4.7-4.7-12.3 0-17l39.6-39.6c4.7-4.7 12.3-4.7 17 0l65 65.7 65.1-65.6c4.7-4.7 12.3-4.7 17 0l39.6 39.6c4.7 4.7 4.7 12.3 0 17L312 256l65.6 65.1z"],tint:[384,512,[],"f043","M192 512c-98.435 0-178.087-79.652-178.087-178.087 0-111.196 101.194-154.065 148.522-311.825 9.104-30.116 51.099-28.778 59.13 0 47.546 158.486 148.522 200.069 148.522 311.825C370.087 432.348 290.435 512 192 512zm-42.522-171.826c-1.509-5.533-9.447-5.532-10.956 0-9.223 29.425-27.913 37.645-27.913 58.435C110.609 417.13 125.478 432 144 432s33.391-14.87 33.391-33.391c0-20.839-18.673-28.956-27.913-58.435z"],"toggle-off":[576,512,[],"f204","M384 64H192C85.961 64 0 149.961 0 256s85.961 192 192 192h192c106.039 0 192-85.961 192-192S490.039 64 384 64zM64 256c0-70.741 57.249-128 128-128 70.741 0 128 57.249 128 128 0 70.741-57.249 128-128 128-70.741 0-128-57.249-128-128zm320 128h-48.905c65.217-72.858 65.236-183.12 0-256H384c70.741 0 128 57.249 128 128 0 70.74-57.249 128-128 128z"],"toggle-on":[576,512,[],"f205","M576 256c0 106.039-85.961 192-192 192H192C85.961 448 0 362.039 0 256S85.961 64 192 64h192c106.039 0 192 85.961 192 192zM384 128c-70.741 0-128 57.249-128 128 0 70.741 57.249 128 128 128 70.741 0 128-57.249 128-128 0-70.741-57.249-128-128-128"],trademark:[640,512,[],"f25c","M97.119 163.133H12c-6.627 0-12-5.373-12-12V108c0-6.627 5.373-12 12-12h248.559c6.627 0 12 5.373 12 12v43.133c0 6.627-5.373 12-12 12H175.44V404c0 6.627-5.373 12-12 12h-54.322c-6.627 0-12-5.373-12-12V163.133zM329.825 96h65.425a12 12 0 0 1 11.346 8.093l43.759 127.068c7.161 20.588 16.111 52.812 16.111 52.812h.896s8.95-32.224 16.111-52.812l43.758-127.068A12 12 0 0 1 538.577 96h65.41a12 12 0 0 1 11.961 11.03l24.012 296c.567 6.987-4.951 12.97-11.961 12.97h-54.101a12 12 0 0 1-11.972-11.182l-9.082-132.93c-1.79-24.168 0-53.706 0-53.706h-.896s-10.741 33.566-17.902 53.706l-30.7 84.731a12 12 0 0 1-11.282 7.912h-50.302a12 12 0 0 1-11.282-7.912l-30.7-84.731c-7.161-20.14-17.903-53.706-17.903-53.706h-.895s1.79 29.538 0 53.706l-9.082 132.93c-.428 6.295-5.66 11.182-11.97 11.182H305.4c-7.017 0-12.536-5.994-11.959-12.987l24.425-296A11.999 11.999 0 0 1 329.825 96z"],train:[448,512,[],"f238","M448 96v256c0 51.815-61.624 96-130.022 96l62.98 49.721C386.905 502.417 383.562 512 376 512H72c-7.578 0-10.892-9.594-4.957-14.279L130.022 448C61.82 448 0 403.954 0 352V96C0 42.981 64 0 128 0h192c65 0 128 42.981 128 96zm-48 136V120c0-13.255-10.745-24-24-24H72c-13.255 0-24 10.745-24 24v112c0 13.255 10.745 24 24 24h304c13.255 0 24-10.745 24-24zm-176 64c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56z"],transgender:[384,512,[],"f224","M372 0h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-80.7 80.7C198.5 104.1 172.2 96 144 96 64.5 96 0 160.5 0 240c0 68.5 47.9 125.9 112 140.4V408H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v28c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-28h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-27.6c64.1-14.6 112-71.9 112-140.4 0-28.2-8.1-54.5-22.1-76.7l80.7-80.7 16.9 16.9c7.6 7.6 20.5 2.2 20.5-8.5V12c0-6.6-5.4-12-12-12zM144 320c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],"transgender-alt":[480,512,[],"f225","M468 0h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-80.7 80.7C294.5 104.1 268.2 96 240 96c-28.2 0-54.5 8.1-76.7 22.1l-16.5-16.5 19.8-19.8c4.7-4.7 4.7-12.3 0-17l-28.3-28.3c-4.7-4.7-12.3-4.7-17 0l-19.8 19.8-19-19 16.9-16.9C107.1 12.9 101.7 0 91 0H12C5.4 0 0 5.4 0 12v79c0 10.7 12.9 16 20.5 8.5l16.9-16.9 19 19-19.8 19.8c-4.7 4.7-4.7 12.3 0 17l28.3 28.3c4.7 4.7 12.3 4.7 17 0l19.8-19.8 16.5 16.5C104.1 185.5 96 211.8 96 240c0 68.5 47.9 125.9 112 140.4V408h-36c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v28c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-28h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-27.6c64.1-14.6 112-71.9 112-140.4 0-28.2-8.1-54.5-22.1-76.7l80.7-80.7 16.9 16.9c7.6 7.6 20.5 2.2 20.5-8.5V12c0-6.6-5.4-12-12-12zM240 320c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],trash:[448,512,[],"f1f8","M0 84V56c0-13.3 10.7-24 24-24h112l9.4-18.7c4-8.2 12.3-13.3 21.4-13.3h114.3c9.1 0 17.4 5.1 21.5 13.3L312 32h112c13.3 0 24 10.7 24 24v28c0 6.6-5.4 12-12 12H12C5.4 96 0 90.6 0 84zm415.2 56.7L394.8 467c-1.6 25.3-22.6 45-47.9 45H101.1c-25.3 0-46.3-19.7-47.9-45L32.8 140.7c-.4-6.9 5.1-12.7 12-12.7h358.5c6.8 0 12.3 5.8 11.9 12.7z"],"trash-alt":[448,512,[],"f2ed","M0 84V56c0-13.3 10.7-24 24-24h112l9.4-18.7c4-8.2 12.3-13.3 21.4-13.3h114.3c9.1 0 17.4 5.1 21.5 13.3L312 32h112c13.3 0 24 10.7 24 24v28c0 6.6-5.4 12-12 12H12C5.4 96 0 90.6 0 84zm416 56v324c0 26.5-21.5 48-48 48H80c-26.5 0-48-21.5-48-48V140c0-6.6 5.4-12 12-12h360c6.6 0 12 5.4 12 12zm-272 68c0-8.8-7.2-16-16-16s-16 7.2-16 16v224c0 8.8 7.2 16 16 16s16-7.2 16-16V208zm96 0c0-8.8-7.2-16-16-16s-16 7.2-16 16v224c0 8.8 7.2 16 16 16s16-7.2 16-16V208zm96 0c0-8.8-7.2-16-16-16s-16 7.2-16 16v224c0 8.8 7.2 16 16 16s16-7.2 16-16V208z"],tree:[384,512,[],"f1bb","M377.33 375.429L293.906 288H328c21.017 0 31.872-25.207 17.448-40.479L262.79 160H296c20.878 0 31.851-24.969 17.587-40.331l-104-112.003c-9.485-10.214-25.676-10.229-35.174 0l-104 112.003C56.206 134.969 67.037 160 88 160h33.21l-82.659 87.521C24.121 262.801 34.993 288 56 288h34.094L6.665 375.429C-7.869 390.655 2.925 416 24.025 416H144c0 32.781-11.188 49.26-33.995 67.506C98.225 492.93 104.914 512 120 512h144c15.086 0 21.776-19.069 9.995-28.494-19.768-15.814-33.992-31.665-33.995-67.496V416h119.97c21.05 0 31.929-25.309 17.36-40.571z"],trophy:[576,512,[],"f091","M552 64H448V24c0-13.3-10.7-24-24-24H152c-13.3 0-24 10.7-24 24v40H24C10.7 64 0 74.7 0 88v56c0 35.7 22.5 72.4 61.9 100.7 31.5 22.7 69.8 37.1 110 41.7C203.3 338.5 240 360 240 360v72h-48c-35.3 0-64 20.7-64 56v12c0 6.6 5.4 12 12 12h296c6.6 0 12-5.4 12-12v-12c0-35.3-28.7-56-64-56h-48v-72s36.7-21.5 68.1-73.6c40.3-4.6 78.6-19 110-41.7 39.3-28.3 61.9-65 61.9-100.7V88c0-13.3-10.7-24-24-24zM99.3 192.8C74.9 175.2 64 155.6 64 144v-16h64.2c1 32.6 5.8 61.2 12.8 86.2-15.1-5.2-29.2-12.4-41.7-21.4zM512 144c0 16.1-17.7 36.1-35.3 48.8-12.5 9-26.7 16.2-41.8 21.4 7-25 11.8-53.6 12.8-86.2H512v16z"],truck:[640,512,[],"f0d1","M592 0H272c-26.51 0-48 21.49-48 48v48h-44.118a48 48 0 0 0-33.941 14.059l-99.882 99.882A48 48 0 0 0 32 243.882V352h-8c-13.255 0-24 10.745-24 24v16c0 13.255 10.745 24 24 24h40c0 53.019 42.981 96 96 96s96-42.981 96-96h128c0 53.019 42.981 96 96 96s96-42.981 96-96h40c13.255 0 24-10.745 24-24V48c0-26.51-21.49-48-48-48zM160 464c-26.467 0-48-21.533-48-48s21.533-48 48-48 48 21.533 48 48-21.533 48-48 48zm64-208H80v-12.118L179.882 144H224v112zm256 208c-26.467 0-48-21.533-48-48s21.533-48 48-48 48 21.533 48 48-21.533 48-48 48z"],tty:[512,512,[],"f1e4","M5.37 103.822c138.532-138.532 362.936-138.326 501.262 0 6.078 6.078 7.074 15.496 2.583 22.681l-43.214 69.138a18.332 18.332 0 0 1-22.356 7.305l-86.422-34.569a18.335 18.335 0 0 1-11.434-18.846L351.741 90c-62.145-22.454-130.636-21.986-191.483 0l5.953 59.532a18.331 18.331 0 0 1-11.434 18.846l-86.423 34.568a18.334 18.334 0 0 1-22.356-7.305L2.787 126.502a18.333 18.333 0 0 1 2.583-22.68zM96 308v-40c0-6.627-5.373-12-12-12H44c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm-336 96v-40c0-6.627-5.373-12-12-12H92c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zM96 500v-40c0-6.627-5.373-12-12-12H44c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12zm288 0v-40c0-6.627-5.373-12-12-12H140c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zm96 0v-40c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z"],tv:[640,512,[],"f26c","M592 0H48C21.5 0 0 21.5 0 48v320c0 26.5 21.5 48 48 48h245.1v32h-160c-17.7 0-32 14.3-32 32s14.3 32 32 32h384c17.7 0 32-14.3 32-32s-14.3-32-32-32h-160v-32H592c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48zm-16 352H64V64h512v288z"],umbrella:[576,512,[],"f0e9","M557.011 267.631c-51.432-45.217-107.572-43.698-158.567 30.731-5.298 7.861-14.906 7.165-19.736 0-2.483-3.624-32.218-60.808-90.708-60.808-45.766 0-70.542 31.378-90.709 60.808-4.829 7.165-14.436 7.861-19.734 0-50.904-74.285-106.613-76.406-158.567-30.731-10.21 8.264-20.912-1.109-18.696-9.481C32.146 134.573 158.516 64.612 288.001 64.612c128.793 0 256.546 69.961 287.706 193.538 2.206 8.322-8.426 17.793-18.696 9.481zM256 261.001V416c0 17.645-14.355 32-32 32s-32-14.355-32-32c0-17.673-14.327-32-32-32s-32 14.327-32 32c0 52.935 43.065 96 96 96s96-43.065 96-96V261.288c-21.836-10.806-45.425-9.737-64-.287zm64-211.007V32c0-17.673-14.327-32-32-32s-32 14.327-32 32v17.987a372.105 372.105 0 0 1 64 .007z"],underline:[448,512,[],"f0cd","M224.264 388.24c-91.669 0-156.603-51.165-156.603-151.392V64H39.37c-8.837 0-16-7.163-16-16V16c0-8.837 7.163-16 16-16h137.39c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-28.813v172.848c0 53.699 28.314 79.444 76.317 79.444 46.966 0 75.796-25.434 75.796-79.965V64h-28.291c-8.837 0-16-7.163-16-16V16c0-8.837 7.163-16 16-16h136.868c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16h-28.291v172.848c0 99.405-64.881 151.392-156.082 151.392zM16 448h416c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H16c-8.837 0-16-7.163-16-16v-32c0-8.837 7.163-16 16-16z"],undo:[512,512,[],"f0e2","M212.333 224.333H12c-6.627 0-12-5.373-12-12V12C0 5.373 5.373 0 12 0h48c6.627 0 12 5.373 12 12v78.112C117.773 39.279 184.26 7.47 258.175 8.007c136.906.994 246.448 111.623 246.157 248.532C504.041 393.258 393.12 504 256.333 504c-64.089 0-122.496-24.313-166.51-64.215-5.099-4.622-5.334-12.554-.467-17.42l33.967-33.967c4.474-4.474 11.662-4.717 16.401-.525C170.76 415.336 211.58 432 256.333 432c97.268 0 176-78.716 176-176 0-97.267-78.716-176-176-176-58.496 0-110.28 28.476-142.274 72.333h98.274c6.627 0 12 5.373 12 12v48c0 6.627-5.373 12-12 12z"],"undo-alt":[512,512,[],"f2ea","M255.545 8c-66.269.119-126.438 26.233-170.86 68.685L48.971 40.971C33.851 25.851 8 36.559 8 57.941V192c0 13.255 10.745 24 24 24h134.059c21.382 0 32.09-25.851 16.971-40.971l-41.75-41.75c30.864-28.899 70.801-44.907 113.23-45.273 92.398-.798 170.283 73.977 169.484 169.442C423.236 348.009 349.816 424 256 424c-41.127 0-79.997-14.678-110.63-41.556-4.743-4.161-11.906-3.908-16.368.553L89.34 422.659c-4.872 4.872-4.631 12.815.482 17.433C133.798 479.813 192.074 504 256 504c136.966 0 247.999-111.033 248-247.998C504.001 119.193 392.354 7.755 255.545 8z"],"universal-access":[512,512,[],"f29a","M256 48c114.953 0 208 93.029 208 208 0 114.953-93.029 208-208 208-114.953 0-208-93.029-208-208 0-114.953 93.029-208 208-208m0-40C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zm0 56C149.961 64 64 149.961 64 256s85.961 192 192 192 192-85.961 192-192S362.039 64 256 64zm0 44c19.882 0 36 16.118 36 36s-16.118 36-36 36-36-16.118-36-36 16.118-36 36-36zm117.741 98.023c-28.712 6.779-55.511 12.748-82.14 15.807.851 101.023 12.306 123.052 25.037 155.621 3.617 9.26-.957 19.698-10.217 23.315-9.261 3.617-19.699-.957-23.316-10.217-8.705-22.308-17.086-40.636-22.261-78.549h-9.686c-5.167 37.851-13.534 56.208-22.262 78.549-3.615 9.255-14.05 13.836-23.315 10.217-9.26-3.617-13.834-14.056-10.217-23.315 12.713-32.541 24.185-54.541 25.037-155.621-26.629-3.058-53.428-9.027-82.141-15.807-8.6-2.031-13.926-10.648-11.895-19.249s10.647-13.926 19.249-11.895c96.686 22.829 124.283 22.783 220.775 0 8.599-2.03 17.218 3.294 19.249 11.895 2.029 8.601-3.297 17.219-11.897 19.249z"],university:[512,512,[],"f19c","M480 128v16a8 8 0 0 1-8 8h-24v12c0 6.627-5.373 12-12 12H44c-6.627 0-12-5.373-12-12v-12H8a8 8 0 0 1-8-8v-16a8 8 0 0 1 4.941-7.392l232-88a7.996 7.996 0 0 1 6.118 0l232 88A8 8 0 0 1 480 128zm-24 304H24c-13.255 0-24 10.745-24 24v16a8 8 0 0 0 8 8h464a8 8 0 0 0 8-8v-16c0-13.255-10.745-24-24-24zM64 192v192H44c-6.627 0-12 5.373-12 12v20h416v-20c0-6.627-5.373-12-12-12h-20V192h-64v192h-32V192h-64v192h-32V192h-64v192h-32V192H64z"],unlink:[512,512,[],"f127","M304.083 405.907c4.686 4.686 4.686 12.284 0 16.971l-44.674 44.674c-59.263 59.262-155.693 59.266-214.961 0-59.264-59.265-59.264-155.696 0-214.96l44.675-44.675c4.686-4.686 12.284-4.686 16.971 0l39.598 39.598c4.686 4.686 4.686 12.284 0 16.971l-44.675 44.674c-28.072 28.073-28.072 73.75 0 101.823 28.072 28.072 73.75 28.073 101.824 0l44.674-44.674c4.686-4.686 12.284-4.686 16.971 0l39.597 39.598zm-56.568-260.216c4.686 4.686 12.284 4.686 16.971 0l44.674-44.674c28.072-28.075 73.75-28.073 101.824 0 28.072 28.073 28.072 73.75 0 101.823l-44.675 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.598 39.598c4.686 4.686 12.284 4.686 16.971 0l44.675-44.675c59.265-59.265 59.265-155.695 0-214.96-59.266-59.264-155.695-59.264-214.961 0l-44.674 44.674c-4.686 4.686-4.686 12.284 0 16.971l39.597 39.598zm234.828 359.28l22.627-22.627c9.373-9.373 9.373-24.569 0-33.941L63.598 7.029c-9.373-9.373-24.569-9.373-33.941 0L7.029 29.657c-9.373 9.373-9.373 24.569 0 33.941l441.373 441.373c9.373 9.372 24.569 9.372 33.941 0z"],unlock:[448,512,[],"f09c","M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z"],"unlock-alt":[448,512,[],"f13e","M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48zM264 408c0 22.1-17.9 40-40 40s-40-17.9-40-40v-48c0-22.1 17.9-40 40-40s40 17.9 40 40v48z"],upload:[512,512,[],"f093","M296 384h-80c-13.3 0-24-10.7-24-24V192h-87.7c-17.8 0-26.7-21.5-14.1-34.1L242.3 5.7c7.5-7.5 19.8-7.5 27.3 0l152.2 152.2c12.6 12.6 3.7 34.1-14.1 34.1H320v168c0 13.3-10.7 24-24 24zm216-8v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h136v8c0 30.9 25.1 56 56 56h80c30.9 0 56-25.1 56-56v-8h136c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"],user:[512,512,[],"f007","M96 160C96 71.634 167.635 0 256 0s160 71.634 160 160-71.635 160-160 160S96 248.366 96 160zm304 192h-28.556c-71.006 42.713-159.912 42.695-230.888 0H112C50.144 352 0 402.144 0 464v24c0 13.255 10.745 24 24 24h464c13.255 0 24-10.745 24-24v-24c0-61.856-50.144-112-112-112z"],"user-circle":[512,512,[],"f2bd","M256 8C119.033 8 8 119.033 8 256s111.033 248 248 248 248-111.033 248-248S392.967 8 256 8zM144 208c0-61.856 50.144-112 112-112s112 50.144 112 112-50.144 112-112 112-112-50.144-112-112zm268.408 172.663c-80.346 100.411-232.375 100.53-312.817 0C117.003 362.973 141.218 352 168 352h18.204c44.03 21.336 95.495 21.368 139.592 0H344c26.782 0 50.997 10.973 68.408 28.663z"],"user-md":[448,512,[],"f0f0","M96 128C96 57.308 153.308 0 224 0s128 57.308 128 128-57.308 128-128 128S96 198.692 96 128zm256 160v33.61c36.471 7.433 64 39.756 64 78.39v49.441c0 11.44-8.075 21.29-19.293 23.534l-21.802 4.361c-6.499 1.3-12.821-2.915-14.12-9.414l-1.569-7.845c-1.3-6.499 2.915-12.821 9.414-14.12l15.37-3.074v-42.078c0-26.283-20.793-48.297-47.071-48.797C310.039 351.498 288 373.224 288 400v42.883l15.371 3.074c6.499 1.3 10.713 7.622 9.414 14.12l-1.569 7.845c-1.3 6.499-7.622 10.714-14.12 9.414l-21.802-4.361C264.075 470.732 256 460.882 256 449.441V400c0-38.634 27.529-70.957 64-78.39V288h-22.624c-45.669 20.945-99.331 21.749-146.752 0H128v66.025c28.495 7.361 49.359 33.906 47.931 64.977-1.506 32.778-28.097 59.392-60.874 60.926C78.383 481.644 48 452.303 48 416c0-29.767 20.427-54.852 48-61.975V288c-53.019 0-96 42.981-96 96v104c0 13.255 10.745 24 24 24h400c13.255 0 24-10.745 24-24V384c0-53.019-42.981-96-96-96zM80 416c0 17.645 14.355 32 32 32s32-14.355 32-32-14.355-32-32-32-32 14.355-32 32z"],"user-plus":[640,512,[],"f234","M616 332c0-6.627-5.373-12-12-12h-60v-60c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v60h-60c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h60v60c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12v-60h60c6.627 0 12-5.373 12-12v-40zM448 444v15c0 11.598-9.402 21-21 21H21c-11.598 0-21-9.402-21-21v-21c0-54.124 43.876-98 98-98h24.986c62.104 37.358 139.897 37.374 202.027 0H350a98.09 98.09 0 0 1 26 3.493V372c0 24.262 19.738 44 44 44h25.519c2.768 12.064 2.481 20.659 2.481 28zM84 172c0-77.32 62.68-140 140-140s140 62.68 140 140-62.68 140-140 140S84 249.32 84 172z"],"user-secret":[448,512,[],"f21b","M388.829 295.324l20.972-55.052c2.992-7.854-2.809-16.272-11.214-16.272H340.39c7.45-16.236 11.61-34.297 11.61-53.333 0-3.631-.16-7.224-.456-10.778C391.083 152.074 416 140.684 416 128c0-13.263-27.231-25.112-69.947-32.937-9.185-32.805-27.178-65.797-40.714-82.85-9.452-11.908-25.873-15.634-39.471-8.834l-27.557 13.779a31.997 31.997 0 0 1-28.622 0l-27.557-13.78c-13.599-6.799-30.02-3.074-39.471 8.834-13.536 17.053-31.529 50.045-40.714 82.85C59.231 102.888 32 114.737 32 128c0 12.684 24.917 24.074 64.456 31.889A129.362 129.362 0 0 0 96 170.667c0 19.037 4.159 37.098 11.608 53.333h-57.41c-8.615 0-14.423 8.809-11.029 16.727l22.906 53.447C25.799 307.882 0 342.925 0 384v104c0 13.255 10.745 24 24 24h400c13.255 0 24-10.745 24-24V384c0-39.97-24.43-74.231-59.171-88.676zM184 488l-48-192 48 24 24 40-24 128zm80 0l-24-128 24-40 48-24-48 192zm54.778-303.746c-.008.043-4.299 3.231-5.125 5.771-3.861 11.864-7.026 24.572-16.514 33.359-10.071 9.327-47.957 22.405-63.996-25.029-2.837-8.395-15.447-8.398-18.285 0-16.963 50.168-56.019 32.417-63.996 25.029-9.488-8.786-12.653-21.495-16.514-33.359-.826-2.54-5.118-5.728-5.125-5.771-.554-2.925-.981-5.884-1.22-8.85-.309-3.848 10.078-3.658 11.078-3.747 26.303-2.326 52.303-.579 78.023 5.497 2.563.606 11.553.529 13.793 0 25.72-6.076 51.72-7.824 78.023-5.497 1.002.089 11.387-.102 11.078 3.747-.239 2.966-.666 5.925-1.22 8.85z"],"user-times":[640,512,[],"f235","M599.681 411.397c4.686-4.686 4.686-12.284 0-16.971L557.255 352l42.426-42.426c4.686-4.686 4.686-12.284 0-16.971l-28.284-28.284c-4.686-4.686-12.284-4.686-16.971 0L512 306.745l-42.426-42.426c-4.686-4.686-12.284-4.686-16.971 0l-28.284 28.284c-4.686 4.686-4.686 12.284 0 16.971L466.745 352l-42.426 42.426c-4.686 4.686-4.686 12.284 0 16.971l28.284 28.284c4.686 4.686 12.284 4.686 16.971 0L512 397.255l42.426 42.426c4.686 4.686 12.284 4.686 16.971 0l28.284-28.284zM84 172c0-77.32 62.68-140 140-140s140 62.68 140 140-62.68 140-140 140S84 249.32 84 172zm359.737 299.645C439.904 476.712 433.843 480 427 480H21c-11.598 0-21-9.402-21-21v-21c0-54.124 43.876-98 98-98h24.986c62.104 37.358 139.897 37.374 202.027 0H350c23.366 0 44.818 8.183 61.658 21.832l-9.967 9.967c-17.156 17.156-17.156 45.07 0 62.225l28.284 28.284a43.946 43.946 0 0 0 13.762 9.337z"],users:[640,512,[],"f0c0","M220 164c0-55.229 44.772-100 100-100s100 44.771 100 100-44.772 100-100 100-100-44.771-100-100zM48 208c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm384 0c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm-22 76c38.66 0 70 31.34 70 70v70c0 13.255-10.745 24-24 24H184c-13.255 0-24-10.745-24-24v-70c0-38.66 31.34-70 70-70h17.848c44.364 26.687 99.93 26.693 144.305 0H410m-282 70c0-11.975 2.081-23.472 5.889-34.156-21.93 1.152-44.122-4.121-63.611-15.844H56c-30.928 0-56 25.072-56 56v32c0 13.255 10.745 24 24 24h104v-62zm456-50h-14.278c-19.495 11.727-41.686 16.996-63.611 15.844A101.542 101.542 0 0 1 512 354v62h104c13.255 0 24-10.745 24-24v-32c0-30.928-25.072-56-56-56z"],"utensil-spoon":[512,512,[],"f2e5","M480.1 31.9c-55-55.1-164.9-34.5-227.8 28.5-49.3 49.3-55.1 110-28.8 160.4L9 413.2c-11.6 10.5-12.1 28.5-1 39.5L59.3 504c11 11 29.1 10.5 39.5-1.1l192.4-214.4c50.4 26.3 111.1 20.5 160.4-28.8 63-62.9 83.6-172.8 28.5-227.8z"],utensils:[416,512,[],"f2e7","M207.9 15.2c.8 4.7 16.1 94.5 16.1 128.8 0 52.3-27.8 89.6-68.9 104.6L168 486.7c.7 13.7-10.2 25.3-24 25.3H80c-13.7 0-24.7-11.5-24-25.3l12.9-238.1C27.7 233.6 0 196.2 0 144 0 109.6 15.3 19.9 16.1 15.2 19.3-5.1 61.4-5.4 64 16.3v141.2c1.3 3.4 15.1 3.2 16 0 1.4-25.3 7.9-139.2 8-141.8 3.3-20.8 44.7-20.8 47.9 0 .2 2.7 6.6 116.5 8 141.8.9 3.2 14.8 3.4 16 0V16.3c2.6-21.6 44.8-21.4 48-1.1zm119.2 285.7l-15 185.1c-1.2 14 9.9 26 23.9 26h56c13.3 0 24-10.7 24-24V24c0-13.2-10.7-24-24-24-82.5 0-221.4 178.5-64.9 300.9z"],venus:[288,512,[],"f221","M288 176c0-79.5-64.5-144-144-144S0 96.5 0 176c0 68.5 47.9 125.9 112 140.4V368H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v36c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-36h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-51.6c64.1-14.5 112-71.9 112-140.4zm-224 0c0-44.1 35.9-80 80-80s80 35.9 80 80-35.9 80-80 80-80-35.9-80-80z"],"venus-double":[512,512,[],"f226","M288 176c0-79.5-64.5-144-144-144S0 96.5 0 176c0 68.5 47.9 125.9 112 140.4V368H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v36c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-36h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-51.6c64.1-14.5 112-71.9 112-140.4zm-224 0c0-44.1 35.9-80 80-80s80 35.9 80 80-35.9 80-80 80-80-35.9-80-80zm336 140.4V368h36c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12h-36v36c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12v-36h-36c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h36v-51.6c-21.2-4.8-40.6-14.3-57.2-27.3 14-16.7 25-36 32.1-57.1 14.5 14.8 34.7 24 57.1 24 44.1 0 80-35.9 80-80s-35.9-80-80-80c-22.3 0-42.6 9.2-57.1 24-7.1-21.1-18-40.4-32.1-57.1C303.4 43.6 334.3 32 368 32c79.5 0 144 64.5 144 144 0 68.5-47.9 125.9-112 140.4z"],"venus-mars":[576,512,[],"f228","M564 0h-79c-10.7 0-16 12.9-8.5 20.5l16.9 16.9-48.7 48.7C422.5 72.1 396.2 64 368 64c-33.7 0-64.6 11.6-89.2 30.9 14 16.7 25 36 32.1 57.1 14.5-14.8 34.7-24 57.1-24 44.1 0 80 35.9 80 80s-35.9 80-80 80c-22.3 0-42.6-9.2-57.1-24-7.1 21.1-18 40.4-32.1 57.1 24.5 19.4 55.5 30.9 89.2 30.9 79.5 0 144-64.5 144-144 0-28.2-8.1-54.5-22.1-76.7l48.7-48.7 16.9 16.9c2.4 2.4 5.4 3.5 8.4 3.5 6.2 0 12.1-4.8 12.1-12V12c0-6.6-5.4-12-12-12zM144 64C64.5 64 0 128.5 0 208c0 68.5 47.9 125.9 112 140.4V400H76c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h36v36c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12v-36h36c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-36v-51.6c64.1-14.6 112-71.9 112-140.4 0-79.5-64.5-144-144-144zm0 224c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],video:[576,512,[],"f03d","M528 64h-12.118a48 48 0 0 0-33.941 14.059L384 176v-64c0-26.51-21.49-48-48-48H48C21.49 64 0 85.49 0 112v288c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48v-64l97.941 97.941A48 48 0 0 0 515.882 448H528c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48z"],"volume-down":[384,512,[],"f027","M256 88.017v335.964c0 21.438-25.943 31.998-40.971 16.971L126.059 352H24c-13.255 0-24-10.745-24-24V184c0-13.255 10.745-24 24-24h102.059l88.971-88.954c15.01-15.01 40.97-4.49 40.97 16.971zM384 256c0-33.717-17.186-64.35-45.972-81.944-15.079-9.214-34.775-4.463-43.992 10.616s-4.464 34.775 10.615 43.992C314.263 234.538 320 244.757 320 256a32.056 32.056 0 0 1-13.802 26.332c-14.524 10.069-18.136 30.006-8.067 44.53 10.07 14.525 30.008 18.136 44.53 8.067C368.546 316.983 384 287.478 384 256z"],"volume-off":[256,512,[],"f026","M256 88.017v335.964c0 21.438-25.943 31.998-40.971 16.971L126.059 352H24c-13.255 0-24-10.745-24-24V184c0-13.255 10.745-24 24-24h102.059l88.971-88.954c15.01-15.01 40.97-4.49 40.97 16.971z"],"volume-up":[576,512,[],"f028","M256 88.017v335.964c0 21.438-25.943 31.998-40.971 16.971L126.059 352H24c-13.255 0-24-10.745-24-24V184c0-13.255 10.745-24 24-24h102.059l88.971-88.954c15.01-15.01 40.97-4.49 40.97 16.971zm182.056-77.876C422.982.92 403.283 5.668 394.061 20.745c-9.221 15.077-4.473 34.774 10.604 43.995C468.967 104.063 512 174.983 512 256c0 73.431-36.077 142.292-96.507 184.206-14.522 10.072-18.129 30.01-8.057 44.532 10.076 14.528 30.016 18.126 44.531 8.057C529.633 438.927 576 350.406 576 256c0-103.244-54.579-194.877-137.944-245.859zM480 256c0-68.547-36.15-129.777-91.957-163.901-15.076-9.22-34.774-4.471-43.994 10.607-9.22 15.078-4.471 34.774 10.607 43.994C393.067 170.188 416 211.048 416 256c0 41.964-20.62 81.319-55.158 105.276-14.521 10.073-18.128 30.01-8.056 44.532 6.216 8.96 16.185 13.765 26.322 13.765a31.862 31.862 0 0 0 18.21-5.709C449.091 377.953 480 318.938 480 256zm-96 0c0-33.717-17.186-64.35-45.972-81.944-15.079-9.214-34.775-4.463-43.992 10.616s-4.464 34.775 10.615 43.992C314.263 234.538 320 244.757 320 256a32.056 32.056 0 0 1-13.802 26.332c-14.524 10.069-18.136 30.006-8.067 44.53 10.07 14.525 30.008 18.136 44.53 8.067C368.546 316.983 384 287.478 384 256z"],wheelchair:[512,512,[],"f193","M496.101 385.669l14.227 28.663c3.929 7.915.697 17.516-7.218 21.445l-65.465 32.886c-16.049 7.967-35.556 1.194-43.189-15.055L331.679 320H192c-15.925 0-29.426-11.71-31.679-27.475C126.433 55.308 128.38 70.044 128 64c0-36.358 30.318-65.635 67.052-63.929 33.271 1.545 60.048 28.905 60.925 62.201.868 32.933-23.152 60.423-54.608 65.039l4.67 32.69H336c8.837 0 16 7.163 16 16v32c0 8.837-7.163 16-16 16H215.182l4.572 32H352a32 32 0 0 1 28.962 18.392L438.477 396.8l36.178-18.349c7.915-3.929 17.517-.697 21.446 7.218zM311.358 352h-24.506c-7.788 54.204-54.528 96-110.852 96-61.757 0-112-50.243-112-112 0-41.505 22.694-77.809 56.324-97.156-3.712-25.965-6.844-47.86-9.488-66.333C45.956 198.464 0 261.963 0 336c0 97.047 78.953 176 176 176 71.87 0 133.806-43.308 161.11-105.192L311.358 352z"],wifi:[640,512,[],"f1eb","M384 416c0 35.346-28.654 64-64 64s-64-28.654-64-64c0-35.346 28.654-64 64-64s64 28.654 64 64zm136.659-124.443c6.465-6.465 6.245-17.065-.564-23.167-113.793-101.985-286.526-101.869-400.19 0-6.809 6.102-7.029 16.702-.564 23.167l34.006 34.006c5.927 5.927 15.464 6.32 21.769.796 82.88-72.609 207.074-72.447 289.768 0 6.305 5.524 15.842 5.132 21.769-.796l34.006-34.006zm112.11-113.718c6.385-6.385 6.254-16.816-.35-22.973-175.768-163.86-449.134-163.8-624.837 0-6.604 6.157-6.735 16.589-.35 22.973l33.966 33.966c6.095 6.095 15.891 6.231 22.224.383 144.763-133.668 368.356-133.702 513.156 0 6.333 5.848 16.129 5.712 22.224-.383l33.967-33.966z"],"window-close":[512,512,[],"f410","M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-83.6 290.5c4.8 4.8 4.8 12.6 0 17.4l-40.5 40.5c-4.8 4.8-12.6 4.8-17.4 0L256 313.3l-66.5 67.1c-4.8 4.8-12.6 4.8-17.4 0l-40.5-40.5c-4.8-4.8-4.8-12.6 0-17.4l67.1-66.5-67.1-66.5c-4.8-4.8-4.8-12.6 0-17.4l40.5-40.5c4.8-4.8 12.6-4.8 17.4 0l66.5 67.1 66.5-67.1c4.8-4.8 12.6-4.8 17.4 0l40.5 40.5c4.8 4.8 4.8 12.6 0 17.4L313.3 256l67.1 66.5z"],"window-maximize":[512,512,[],"f2d0","M464 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zm-16 160H64v-84c0-6.6 5.4-12 12-12h360c6.6 0 12 5.4 12 12v84z"],"window-minimize":[512,512,[],"f2d1","M464 352H48c-26.5 0-48 21.5-48 48v32c0 26.5 21.5 48 48 48h416c26.5 0 48-21.5 48-48v-32c0-26.5-21.5-48-48-48z"],"window-restore":[512,512,[],"f2d2","M512 48v288c0 26.5-21.5 48-48 48h-48V176c0-44.1-35.9-80-80-80H128V48c0-26.5 21.5-48 48-48h288c26.5 0 48 21.5 48 48zM384 176v288c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V176c0-26.5 21.5-48 48-48h288c26.5 0 48 21.5 48 48zm-68 28c0-6.6-5.4-12-12-12H76c-6.6 0-12 5.4-12 12v52h252v-52z"],"won-sign":[576,512,[],"f159","M564 192c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-48.028l18.572-80.61c1.732-7.518-3.978-14.694-11.693-14.694h-46.107a11.998 11.998 0 0 0-11.736 9.5L450.73 128H340.839l-19.725-85.987a12 12 0 0 0-11.696-9.317H265.43a12 12 0 0 0-11.687 9.277L233.696 128H124.975L107.5 42.299a12 12 0 0 0-11.758-9.602H53.628c-7.686 0-13.39 7.124-11.709 14.624L60 128H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h62.342l7.171 32H12c-6.627 0-12 5.373-12 12v40c0 6.627 5.373 12 12 12h83.856l40.927 182.624A12 12 0 0 0 148.492 480h56.767c5.583 0 10.428-3.85 11.689-9.288L259.335 288h55.086l42.386 182.712A12 12 0 0 0 368.496 480h56.826a12 12 0 0 0 11.694-9.306L479.108 288H564c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-70.146l7.373-32H564zm-425.976 0h80.757l-7.457 32h-66.776l-6.524-32zm45.796 150.029c-6.194 25.831-6.758 47.25-7.321 47.25h-1.126s-1.689-22.05-6.758-47.25L157.599 288h38.812l-12.591 54.029zM274.182 224l1.996-8.602c1.856-7.962 3.457-15.968 4.803-23.398h11.794c1.347 7.43 2.947 15.436 4.803 23.398l1.996 8.602h-25.392zm130.959 118.029c-5.068 25.2-6.758 47.25-6.758 47.25h-1.126c-.563 0-1.126-21.42-7.321-47.25L377.542 288h39.107l-11.508 54.029zM430.281 224h-67.42l-7.34-32h81.577l-6.817 32z"],wrench:[512,512,[],"f0ad","M481.156 200c9.3 0 15.12 10.155 10.325 18.124C466.295 259.992 420.419 288 368 288c-79.222 0-143.501-63.974-143.997-143.079C223.505 65.469 288.548-.001 368.002 0c52.362.001 98.196 27.949 123.4 69.743C496.24 77.766 490.523 88 481.154 88H376l-40 56 40 56h105.156zm-171.649 93.003L109.255 493.255c-24.994 24.993-65.515 24.994-90.51 0-24.993-24.994-24.993-65.516 0-90.51L218.991 202.5c16.16 41.197 49.303 74.335 90.516 90.503zM104 432c0-13.255-10.745-24-24-24s-24 10.745-24 24 10.745 24 24 24 24-10.745 24-24z"],"yen-sign":[384,512,[],"f157","M351.208 32h-65.277a12 12 0 0 0-10.778 6.724l-55.39 113.163c-14.513 34.704-27.133 71.932-27.133 71.932h-1.262s-12.62-37.228-27.133-71.932l-55.39-113.163A11.997 11.997 0 0 0 98.068 32H32.792c-9.057 0-14.85 9.65-10.59 17.643L102.322 200H44c-6.627 0-12 5.373-12 12v32c0 6.627 5.373 12 12 12h88.162L152 293.228V320H44c-6.627 0-12 5.373-12 12v32c0 6.627 5.373 12 12 12h108v92c0 6.627 5.373 12 12 12h56c6.627 0 12-5.373 12-12v-92h108c6.627 0 12-5.373 12-12v-32c0-6.627-5.373-12-12-12H232v-26.772L251.838 256H340c6.627 0 12-5.373 12-12v-32c0-6.627-5.373-12-12-12h-58.322l80.12-150.357C366.058 41.65 360.266 32 351.208 32z"]}),t=z||{};t.___FONT_AWESOME___||(t.___FONT_AWESOME___={}),t.___FONT_AWESOME___.styles||(t.___FONT_AWESOME___.styles={}),t.___FONT_AWESOME___.hooks||(t.___FONT_AWESOME___.hooks={}),t.___FONT_AWESOME___.shims||(t.___FONT_AWESOME___.shims=[]);var s=t.___FONT_AWESOME___,r=Object.assign||function(c){for(var l=1;l<arguments.length;l++){var h=arguments[l];for(var v in h)Object.prototype.hasOwnProperty.call(h,v)&&(c[v]=h[v])}return c};!function(c){try{c()}catch(c){}}(function(){c("fas"),c("fa")})}(),function(){"use strict";function c(c){var l=Object.keys(Hc);Object.keys(c).forEach(function(h){~l.indexOf(h)&&(Hc[h]=c[h])})}function l(c){return~mc.indexOf(c)}function h(c){if(c&&void 0!==K.createElement){var l=K.createElement("style");l.setAttribute("type","text/css"),l.innerHTML=c;for(var h=K.head.childNodes,v=null,z=h.length-1;z>-1;z--){var e=h[z],a=(e.tagName||"").toUpperCase();["STYLE","LINK"].indexOf(a)>-1&&(v=e)}return K.head.insertBefore(l,v),c}}function v(){return++Cc}function z(c){for(var l=[],h=(c||[]).length>>>0;h--;)l[h]=c[h];return l}function e(c){return c.classList?z(c.classList):(c.getAttribute("class")||"").split(" ").filter(function(c){return c})}function a(c,h){var v=h.split("-"),z=v[0],e=v.slice(1).join("-");return z!==c||""===e||l(e)?null:e}function m(c){return(""+c).replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function t(c){return Object.keys(c||{}).reduce(function(l,h){return l+(h+'="')+m(c[h])+'" '},"").trim()}function s(c){return Object.keys(c||{}).reduce(function(l,h){return l+(h+": ")+c[h]+";"},"")}function r(c){return c.size!==Vc.size||c.x!==Vc.x||c.y!==Vc.y||c.rotate!==Vc.rotate||c.flipX||c.flipY}function f(c){var l=c.transform,h=c.containerWidth,v=c.iconWidth;return{outer:{transform:"translate("+h/2+" 256)"},inner:{transform:"translate("+32*l.x+", "+32*l.y+") "+" "+("scale("+l.size/16*(l.flipX?-1:1)+", "+l.size/16*(l.flipY?-1:1)+") ")+" "+("rotate("+l.rotate+" 0 0)")},path:{transform:"translate("+v/2*-1+" -256)"}}}function M(c){var l=c.transform,h=c.width,v=void 0===h?$:h,z=c.height,e=void 0===z?$:z,a=c.startCentered,m=void 0!==a&&a,t="";return t+=m&&Z?"translate("+(l.x/oc-v/2)+"em, "+(l.y/oc-e/2)+"em) ":m?"translate(calc(-50% + "+l.x/oc+"em), calc(-50% + "+l.y/oc+"em)) ":"translate("+l.x/oc+"em, "+l.y/oc+"em) ",t+="scale("+l.size/oc*(l.flipX?-1:1)+", "+l.size/oc*(l.flipY?-1:1)+") ",t+="rotate("+l.rotate+"deg) "}function i(c){var l,h=c.icons,z=h.main,e=h.mask,a=c.prefix,m=c.iconName,t=c.transform,s=c.symbol,r=c.title,f=c.extra,M=e.found?e:z,i=M.width,n=M.height,H="fa-w-"+Math.ceil(i/n*16),o=[Hc.replacementClass,m?Hc.familyPrefix+"-"+m:"",H].concat(f.classes).join(" "),V={children:[],attributes:fc({},f.attributes,(l={},rc(l,cc,""),rc(l,"data-prefix",a),rc(l,"data-icon",m),rc(l,"class",o),rc(l,"role","img"),rc(l,"xmlns","http://www.w3.org/2000/svg"),rc(l,"viewBox","0 0 "+i+" "+n),l))};r&&V.children.push({tag:"title",attributes:{id:V.attributes["aria-labelledby"]||"title-"+v()},children:[r]});var C=fc({},V,{prefix:a,iconName:m,main:z,mask:e,transform:t,symbol:s,styles:f.styles}),L=e.found&&z.found?uc(C):dc(C),u=L.children,d=L.attributes;return C.children=u,C.attributes=d,s?gc(C):pc(C)}function n(c){var l,h=c.content,v=c.width,z=c.height,e=c.transform,a=c.title,m=c.extra,t=fc({},m.attributes,a?{title:a}:{},(l={},rc(l,cc,""),rc(l,"class",m.classes.join(" ")),l)),f=fc({},m.styles);r(e)&&(f.transform=M({transform:e,startCentered:!0,width:v,height:z}),f["-webkit-transform"]=f.transform);var i=s(f);i.length>0&&(t.style=i);var n=[];return n.push({tag:"span",attributes:t,children:[h]}),a&&n.push({tag:"span",attributes:{class:"sr-only"},children:[a]}),n}function H(c,l){return Nc[c][l]}function o(c,l){return qc[c][l]}function V(c){return Tc[c]||{prefix:null,iconName:null}}function C(c){return c.reduce(function(c,l){var h=a(Hc.familyPrefix,l);if(Fc[l])c.prefix=l;else if(h){var v="fa"===c.prefix?V(h):{};c.iconName=v.iconName||h,c.prefix=v.prefix||c.prefix}else l!==Hc.replacementClass&&0!==l.indexOf("fa-w-")&&c.rest.push(l);return c},Wc())}function L(c,l,h){if(c&&c[l]&&c[l][h])return{prefix:l,iconName:h,icon:c[l][h]}}function u(c){var l=c.tag,h=c.attributes,v=void 0===h?{}:h,z=c.children,e=void 0===z?[]:z;return"string"==typeof c?m(c):"<"+l+" "+t(v)+">"+e.map(u).join("")+"</"+l+">"}function d(c){var l=c.getAttribute?c.getAttribute("class"):null;return!!l&&(!!~l.toString().indexOf(Hc.replacementClass)||~l.toString().indexOf("fa-layers-text"))}function p(){return!0===Hc.autoReplaceSvg?Ic.replace:Ic[Hc.autoReplaceSvg]||Ic.replace}function g(c,l){var h="function"==typeof l?l:Pc;0===c.length?h():(U.requestAnimationFrame||function(c){return c()})(function(){var l=p(),v=kc.begin("mutate");c.map(l),v(),h()})}function b(c){Rc=!0,c(),Rc=!1}function w(c){if(G){var l=c.treeCallback,h=c.nodeCallback,v=c.pseudoElementsCallback,a=new G(function(c){Rc||z(c).forEach(function(c){if("childList"===c.type&&c.addedNodes.length>0&&!d(c.addedNodes[0])&&(Hc.searchPseudoElements&&v(c.target),l(c.target)),"attributes"===c.type&&"class"===c.attributeName&&c.target.parentNode&&Hc.searchPseudoElements&&v(c.target.parentNode),"attributes"===c.type&&d(c.target)&&~ac.indexOf(c.attributeName))if("class"===c.attributeName){var z=C(e(c.target)),a=z.prefix,m=z.iconName;a&&c.target.setAttribute("data-prefix",a),m&&c.target.setAttribute("data-icon",m)}else h(c.target)})});K.getElementsByTagName&&a.observe(K.getElementsByTagName("body")[0],{childList:!0,attributes:!0,characterData:!0,subtree:!0})}}function y(c){for(var l="",h=0;h<c.length;h++)l+=("000"+c.charCodeAt(h).toString(16)).slice(-4);return l}function S(c){var l=Xc(c),h=l.iconName,v=l.prefix,z=l.rest,e=Bc(c),a=Dc(c),m=Uc(c),t=Kc(c),s=Gc(c);return{iconName:h,title:c.getAttribute("title"),prefix:v,transform:a,symbol:m,mask:s,extra:{classes:z,styles:e,attributes:t}}}function _(c){this.name="MissingIcon",this.message=c||"Icon unavailable",this.stack=(new Error).stack}function k(c,l){var h={found:!1,width:512,height:512,icon:cl};if(c&&l&&ll[l]&&ll[l][c]){var v=ll[l][c];h={found:!0,width:v[0],height:v[1],icon:{tag:"path",attributes:{fill:"currentColor",d:v.slice(4)[0]}}}}else if(c&&l&&!Hc.showMissingIcons)throw new _("Icon is missing for prefix "+l+" with icon name "+c);return h}function A(c,l){var h=l.iconName,v=l.title,z=l.prefix,e=l.transform,a=l.symbol,m=l.mask,t=l.extra;return[c,i({icons:{main:k(h,z),mask:k(m.iconName,m.prefix)},prefix:z,iconName:h,transform:e,symbol:a,mask:m,title:v,extra:t})]}function x(c,l){var h=l.title,v=l.transform,z=l.extra,e=null,a=null;if(Z){var m=parseInt(getComputedStyle(c).fontSize,10),t=c.getBoundingClientRect();e=t.width/m,a=t.height/m}return Hc.autoA11y&&!h&&(z.attributes["aria-hidden"]="true"),[c,n({content:c.innerHTML,width:e,height:a,transform:v,title:h,extra:z})]}function O(c){var l=S(c);return~l.extra.classes.indexOf(hl)?x(c,l):A(c,l)}function E(c){var l=kc.begin("searchPseudoElements");b(function(){z(c.querySelectorAll("*")).forEach(function(c){[":before",":after"].forEach(function(l){var h=U.getComputedStyle(c,l),v=h.getPropertyValue("font-family").match(vl),e=z(c.children).filter(function(c){return c.getAttribute(lc)===l})[0];if(!v&&e&&e.remove(),v&&!e){var a=h.getPropertyValue("content"),m=K.createElement("i");m.setAttribute("class",""+zl[v[1]]),m.setAttribute(lc,l),m.innerText=3===a.length?a.substr(1,1):a,":before"===l?c.insertBefore(m,c.firstChild):c.appendChild(m)}})})}),l()}function N(c){var l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,h=K.documentElement.classList,v=function(c){return h.add(hc+"-"+c)},e=function(c){return h.remove(hc+"-"+c)},a=Object.keys(ll),m=["."+hl+":not(["+cc+"])"].concat(a.map(function(c){return"."+c+":not(["+cc+"])"})).join(", ");if(0!==m.length){var t=z(c.querySelectorAll(m));if(t.length>0){v("pending"),e("complete");var s=kc.begin("onTree"),r=t.reduce(function(c,l){try{var h=O(l);h&&c.push(h)}catch(c){vc||c instanceof _&&console.error(c)}return c},[]);s(),g(r,function(){v("active"),v("complete"),e("pending"),"function"==typeof l&&l()})}}}function q(c){var l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null,h=O(c);h&&g([h],l)}function T(c){return{found:!0,width:c[0],height:c[1],icon:{tag:"path",attributes:{fill:"currentColor",d:c.slice(4)[0]}}}}function j(){Hc.autoAddCss&&(sl||h(tl()),sl=!0)}function F(c,l){return Object.defineProperty(c,"abstract",{get:l}),Object.defineProperty(c,"html",{get:function(){return c.abstract.map(function(c){return u(c)})}}),Object.defineProperty(c,"node",{get:function(){if(K.createElement){var l=K.createElement("div");return l.innerHTML=c.html,l.children}}}),c}function W(c){var l=c.prefix,h=void 0===l?"fa":l,v=c.iconName;if(v)return L(rl.definitions,h,v)||L(wc.styles,h,v)}var P=function(){},I={},R={},B=null,X={mark:P,measure:P};try{"undefined"!=typeof window&&(I=window),"undefined"!=typeof document&&(R=document),"undefined"!=typeof MutationObserver&&(B=MutationObserver),"undefined"!=typeof performance&&(X=performance)}catch(c){}var Y=(I.navigator||{}).userAgent,D=void 0===Y?"":Y,U=I,K=R,G=B,J=X,Q=!!U.document,Z=~D.indexOf("MSIE")||~D.indexOf("Trident/"),$=16,cc="data-fa-processed",lc="data-fa-pseudo-element",hc="fontawesome-i2svg",vc=function(){try{return!0}catch(c){return!1}}(),zc=[1,2,3,4,5,6,7,8,9,10],ec=zc.concat([11,12,13,14,15,16,17,18,19,20]),ac=["class","data-prefix","data-icon","data-fa-transform","data-fa-mask"],mc=["xs","sm","lg","fw","ul","li","border","pull-left","pull-right","spin","pulse","rotate-90","rotate-180","rotate-270","flip-horizontal","flip-vertical","stack","stack-1x","stack-2x","inverse","layers","layers-text","layers-counter"].concat(zc.map(function(c){return c+"x"})).concat(ec.map(function(c){return"w-"+c})),tc=function(c,l){if(!(c instanceof l))throw new TypeError("Cannot call a class as a function")},sc=function(){function c(c,l){for(var h=0;h<l.length;h++){var v=l[h];v.enumerable=v.enumerable||!1,v.configurable=!0,"value"in v&&(v.writable=!0),Object.defineProperty(c,v.key,v)}}return function(l,h,v){return h&&c(l.prototype,h),v&&c(l,v),l}}(),rc=function(c,l,h){return l in c?Object.defineProperty(c,l,{value:h,enumerable:!0,configurable:!0,writable:!0}):c[l]=h,c},fc=Object.assign||function(c){for(var l=1;l<arguments.length;l++){var h=arguments[l];for(var v in h)Object.prototype.hasOwnProperty.call(h,v)&&(c[v]=h[v])}return c},Mc=function(c,l){var h={};for(var v in c)l.indexOf(v)>=0||Object.prototype.hasOwnProperty.call(c,v)&&(h[v]=c[v]);return h},ic=function(c){if(Array.isArray(c)){for(var l=0,h=Array(c.length);l<c.length;l++)h[l]=c[l];return h}return Array.from(c)},nc=fc({familyPrefix:"fa",replacementClass:"svg-inline--fa",autoReplaceSvg:!0,autoAddCss:!0,autoA11y:!0,searchPseudoElements:!1,observeMutations:!0,keepOriginalSource:!0,measurePerformance:!1,showMissingIcons:!0},U.FontAwesomeConfig||{});nc.autoReplaceSvg||(nc.observeMutations=!1);var Hc=fc({},nc);U.FontAwesomeConfig=Hc;var oc=$,Vc={size:16,x:0,y:0,rotate:0,flipX:!1,flipY:!1},Cc=0,Lc={x:0,y:0,width:"100%",height:"100%"},uc=function(c){var l=c.children,h=c.attributes,z=c.main,e=c.mask,a=c.transform,m=z.width,t=z.icon,s=e.width,r=e.icon,M=f({transform:a,containerWidth:s,iconWidth:m}),i={tag:"rect",attributes:fc({},Lc,{fill:"white"})},n={tag:"g",attributes:fc({},M.inner),children:[{tag:"path",attributes:fc({},t.attributes,M.path,{fill:"black"})}]},H={tag:"g",attributes:fc({},M.outer),children:[n]},o="mask-"+v(),V="clip-"+v(),C={tag:"defs",children:[{tag:"clipPath",attributes:{id:V},children:[r]},{tag:"mask",attributes:fc({},Lc,{id:o,maskUnits:"userSpaceOnUse",maskContentUnits:"userSpaceOnUse"}),children:[i,H]}]};return l.push(C,{tag:"rect",attributes:fc({fill:"currentColor","clip-path":"url(#"+V+")",mask:"url(#"+o+")"},Lc)}),{children:l,attributes:h}},dc=function(c){var l=c.children,h=c.attributes,v=c.main,z=c.transform,e=s(c.styles);if(e.length>0&&(h.style=e),r(z)){var a=f({transform:z,containerWidth:v.width,iconWidth:v.width});l.push({tag:"g",attributes:fc({},a.outer),children:[{tag:"g",attributes:fc({},a.inner),children:[{tag:v.icon.tag,children:v.icon.children,attributes:fc({},v.icon.attributes,a.path)}]}]})}else l.push(v.icon);return{children:l,attributes:h}},pc=function(c){var l=c.children,h=c.main,v=c.mask,z=c.attributes,e=c.styles,a=c.transform;if(r(a)&&h.found&&!v.found){var m={x:h.width/h.height/2,y:.5};z.style=s(fc({},e,{"transform-origin":m.x+a.x/16+"em "+(m.y+a.y/16)+"em"}))}return[{tag:"svg",attributes:z,children:l}]},gc=function(c){var l=c.prefix,h=c.iconName,v=c.children,z=c.attributes,e=c.symbol,a=!0===e?l+"-"+Hc.familyPrefix+"-"+h:e;return[{tag:"svg",attributes:{style:"display: none;"},children:[{tag:"symbol",attributes:fc({},z,{id:a}),children:v}]}]},bc=U||{};bc.___FONT_AWESOME___||(bc.___FONT_AWESOME___={}),bc.___FONT_AWESOME___.styles||(bc.___FONT_AWESOME___.styles={}),bc.___FONT_AWESOME___.hooks||(bc.___FONT_AWESOME___.hooks={}),bc.___FONT_AWESOME___.shims||(bc.___FONT_AWESOME___.shims=[]);var wc=bc.___FONT_AWESOME___,yc=function(){},Sc=Hc.measurePerformance&&J&&J.mark&&J.measure?J:{mark:yc,measure:yc},_c=function(c){Sc.mark('FA "5.0.1" '+c+" ends"),Sc.measure('FA "5.0.1" '+c,'FA "5.0.1" '+c+" begins",'FA "5.0.1" '+c+" ends")},kc={begin:function(c){return Sc.mark('FA "5.0.1" '+c+" begins"),function(){return _c(c)}},end:_c},Ac=function(c,l){return function(h,v,z,e){return c.call(l,h,v,z,e)}},xc=function(c,l,h,v){var z,e,a,m=Object.keys(c),t=m.length,s=void 0!==v?Ac(l,v):l;for(void 0===h?(z=1,a=c[m[0]]):(z=0,a=h);z<t;z++)a=s(a,c[e=m[z]],e,c);return a},Oc=wc.styles,Ec=wc.shims,Nc={},qc={},Tc={},jc=function(){var c=function(c){return xc(Oc,function(l,h,v){return l[v]=xc(h,c,{}),l},{})};Nc=c(function(c,l,h){return c[l[3]]=h,c}),qc=c(function(c,l,h){var v=l[2];return c[h]=h,v.forEach(function(l){c[l]=h}),c});var l="far"in Oc;Tc=xc(Ec,function(c,h){var v=h[0],z=h[1],e=h[2];return"far"!==z||l||(z="fas"),c[v]={prefix:z,iconName:e},c},{})};jc();var Fc=wc.styles,Wc=function(){return{prefix:null,iconName:null,rest:[]}},Pc=function(){},Ic={replace:function(c){var l=c[0],h=c[1].map(function(c){return u(c)}).join("\n");if(l.parentNode&&l.outerHTML)l.outerHTML=h+(Hc.keepOriginalSource&&"svg"!==l.tagName.toLowerCase()?"\x3c!-- "+l.outerHTML+" --\x3e":"");else if(l.parentNode){var v=document.createElement("span");l.parentNode.replaceChild(v,l),v.outerHTML=h}},nest:function(c){var l=c[0],h=c[1];if(~e(l).indexOf(Hc.replacementClass))return Ic.replace(c);var v=new RegExp(Hc.familyPrefix+"-.*");delete h[0].attributes.style;var z=h[0].attributes.class.split(" ").reduce(function(c,l){return l===Hc.replacementClass||l.match(v)?c.toSvg.push(l):c.toNode.push(l),c},{toNode:[],toSvg:[]});h[0].attributes.class=z.toSvg.join(" ");var a=h.map(function(c){return u(c)}).join("\n");l.setAttribute("class",z.toNode.join(" ")),l.setAttribute(cc,""),l.innerHTML=a}},Rc=!1,Bc=function(c){var l=c.getAttribute("style"),h=[];return l&&(h=l.split(";").reduce(function(c,l){var h=l.split(":"),v=h[0],z=h.slice(1);return v&&z.length>0&&(c[v]=z.join(":").trim()),c},{})),h},Xc=function(c){var l=c.getAttribute("data-prefix"),h=c.getAttribute("data-icon"),v=void 0!==c.innerText?c.innerText.trim():"",z=C(e(c));return l&&h&&(z.prefix=l,z.iconName=h),z.prefix&&v.length>1?z.iconName=o(z.prefix,c.innerText):z.prefix&&1===v.length&&(z.iconName=H(z.prefix,y(c.innerText))),z},Yc=function(c){var l={size:16,x:0,y:0,flipX:!1,flipY:!1,rotate:0};return c?c.toLowerCase().split(" ").reduce(function(c,l){var h=l.toLowerCase().split("-"),v=h[0],z=h.slice(1).join("-");if(v&&"h"===z)return c.flipX=!0,c;if(v&&"v"===z)return c.flipY=!0,c;if(z=parseFloat(z),isNaN(z))return c;switch(v){case"grow":c.size=c.size+z;break;case"shrink":c.size=c.size-z;break;case"left":c.x=c.x-z;break;case"right":c.x=c.x+z;break;case"up":c.y=c.y-z;break;case"down":c.y=c.y+z;break;case"rotate":c.rotate=c.rotate+z}return c},l):l},Dc=function(c){return Yc(c.getAttribute("data-fa-transform"))},Uc=function(c){var l=c.getAttribute("data-fa-symbol");return null!==l&&(""===l||l)},Kc=function(c){var l=z(c.attributes).reduce(function(c,l){return"class"!==c.name&&"style"!==c.name&&(c[l.name]=l.value),c},{}),h=c.getAttribute("title");return Hc.autoA11y&&(h?l["aria-labelledby"]=Hc.replacementClass+"-title-"+v():l["aria-hidden"]="true"),l},Gc=function(c){var l=c.getAttribute("data-fa-mask");return l?C(l.split(" ").map(function(c){return c.trim()})):Wc()};_.prototype=Object.create(Error.prototype),_.prototype.constructor=_;var Jc={fill:"currentColor"},Qc={attributeType:"XML",repeatCount:"indefinite",dur:"2s"},Zc={tag:"path",attributes:fc({},Jc,{d:"M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z"})},$c=fc({},Qc,{attributeName:"opacity"}),cl={tag:"g",children:[Zc,{tag:"circle",attributes:fc({},Jc,{cx:"256",cy:"364",r:"28"}),children:[{tag:"animate",attributes:fc({},Qc,{attributeName:"r",values:"28;14;28;28;14;28;"})},{tag:"animate",attributes:fc({},$c,{values:"1;0;1;1;0;1;"})}]},{tag:"path",attributes:fc({},Jc,{opacity:"1",d:"M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z"}),children:[{tag:"animate",attributes:fc({},$c,{values:"1;0;0;0;0;1;"})}]},{tag:"path",attributes:fc({},Jc,{opacity:"0",d:"M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z"}),children:[{tag:"animate",attributes:fc({},$c,{values:"0;0;1;1;0;0;"})}]}]},ll=wc.styles,hl="fa-layers-text",vl=/Font Awesome 5 (Solid|Regular|Light|Brands)/,zl={Solid:"fas",Regular:"far",Light:"fal",Brands:"fab"},el=[],al=(K.documentElement.doScroll?/^loaded|^c/:/^loaded|^i|^c/).test(K.readyState);al||K.addEventListener("DOMContentLoaded",function c(){K.removeEventListener("DOMContentLoaded",c),al=1,el.map(function(c){return c()})});var ml=function(c){K&&(al?setTimeout(c,0):el.push(c))},tl=function(){var c="svg-inline--fa",l=Hc.familyPrefix,h=Hc.replacementClass,v="svg:not(:root).svg-inline--fa{overflow:visible}.svg-inline--fa{display:inline-block;font-size:inherit;height:1em;overflow:visible;vertical-align:-.125em}.svg-inline--fa.fa-lg{vertical-align:-.225em}.svg-inline--fa.fa-w-1{width:.0625em}.svg-inline--fa.fa-w-2{width:.125em}.svg-inline--fa.fa-w-3{width:.1875em}.svg-inline--fa.fa-w-4{width:.25em}.svg-inline--fa.fa-w-5{width:.3125em}.svg-inline--fa.fa-w-6{width:.375em}.svg-inline--fa.fa-w-7{width:.4375em}.svg-inline--fa.fa-w-8{width:.5em}.svg-inline--fa.fa-w-9{width:.5625em}.svg-inline--fa.fa-w-10{width:.625em}.svg-inline--fa.fa-w-11{width:.6875em}.svg-inline--fa.fa-w-12{width:.75em}.svg-inline--fa.fa-w-13{width:.8125em}.svg-inline--fa.fa-w-14{width:.875em}.svg-inline--fa.fa-w-15{width:.9375em}.svg-inline--fa.fa-w-16{width:1em}.svg-inline--fa.fa-w-17{width:1.0625em}.svg-inline--fa.fa-w-18{width:1.125em}.svg-inline--fa.fa-w-19{width:1.1875em}.svg-inline--fa.fa-w-20{width:1.25em}.svg-inline--fa.fa-pull-left{margin-right:.3em;width:auto}.svg-inline--fa.fa-pull-right{margin-left:.3em;width:auto}.svg-inline--fa.fa-border{height:1.5em}.svg-inline--fa.fa-li{width:2em}.svg-inline--fa.fa-fw{width:1.25em}.fa-layers svg.svg-inline--fa{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.fa-layers{display:inline-block;height:1em;position:relative;text-align:center;vertical-align:-12.5%;width:1em}.fa-layers svg.svg-inline--fa{-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter,.fa-layers-text{display:inline-block;position:absolute;text-align:center}.fa-layers-text{left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);-webkit-transform-origin:center center;transform-origin:center center}.fa-layers-counter{background-color:#ff253a;border-radius:1em;color:#fff;height:1.5em;line-height:1;max-width:5em;min-width:1.5em;overflow:hidden;padding:.25em;right:0;text-overflow:ellipsis;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-bottom-right{bottom:0;right:0;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom right;transform-origin:bottom right}.fa-layers-bottom-left{bottom:0;left:0;right:auto;top:auto;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:bottom left;transform-origin:bottom left}.fa-layers-top-right{right:0;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top right;transform-origin:top right}.fa-layers-top-left{left:0;right:auto;top:0;-webkit-transform:scale(.25);transform:scale(.25);-webkit-transform-origin:top left;transform-origin:top left}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-.0667em}.fa-xs{font-size:.75em}.fa-sm{font-size:.875em}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:2.5em;padding-left:0}.fa-ul>li{position:relative}.fa-li{left:-2em;position:absolute;text-align:center;width:2em;line-height:inherit}.fa-border{border:solid .08em #eee;border-radius:.1em;padding:.2em .25em .15em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left,.fab.fa-pull-left,.fal.fa-pull-left,.far.fa-pull-left,.fas.fa-pull-left{margin-right:.3em}.fa.fa-pull-right,.fab.fa-pull-right,.fal.fa-pull-right,.far.fa-pull-right,.fas.fa-pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0);transform:rotate(0)}100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.fa-rotate-90{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-webkit-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{-webkit-transform:scale(1,-1);transform:scale(1,-1)}.fa-flip-horizontal.fa-flip-vertical{-webkit-transform:scale(-1,-1);transform:scale(-1,-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-rotate-90{-webkit-filter:none;filter:none}.fa-stack{display:inline-block;height:2em;position:relative;width:2em}.fa-stack-1x,.fa-stack-2x{bottom:0;left:0;margin:auto;position:absolute;right:0;top:0}.svg-inline--fa.fa-stack-1x{height:1em;width:1em}.svg-inline--fa.fa-stack-2x{height:2em;width:2em}.fa-inverse{color:#fff}.sr-only{border:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.sr-only-focusable:active,.sr-only-focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}";if("fa"!==l||h!==c){var z=new RegExp("\\.fa\\-","g"),e=new RegExp("\\."+c,"g");v=v.replace(z,"."+l+"-").replace(e,"."+h)}return v},sl=!1,rl=new(function(){function c(){tc(this,c),this.definitions={}}return sc(c,[{key:"add",value:function(){for(var c=this,l=arguments.length,h=Array(l),v=0;v<l;v++)h[v]=arguments[v];var z=h.reduce(this._pullDefinitions,{});Object.keys(z).forEach(function(l){c.definitions[l]=fc({},c.definitions[l]||{},z[l])})}},{key:"reset",value:function(){this.definitions={}}},{key:"_pullDefinitions",value:function(c,l){var h=l.prefix&&l.iconName&&l.icon?{0:l}:l;return Object.keys(h).map(function(l){var v=h[l],z=v.prefix,e=v.iconName,a=v.icon;c[z]||(c[z]={}),c[z][e]=a}),c}}]),c}()),fl={dom:{i2svg:function(){var c=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};j();var l=c.node,h=void 0===l?K:l,v=c.callback,z=void 0===v?function(){}:v;Hc.searchPseudoElements&&E(h),N(h,z)},css:tl,insertCss:function(){h(tl())}},library:rl,parse:{transform:function(c){return Yc(c)}},findIconDefinition:W,icon:function(c){return function(l){var h=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},v=(l||{}).icon?l:W(l||{}),z=h.mask;return z&&(z=(z||{}).icon?z:W(z||{})),c(v,fc({},h,{mask:z}))}}(function(c){var l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},h=l.transform,z=void 0===h?Vc:h,e=l.symbol,a=void 0!==e&&e,m=l.mask,t=void 0===m?null:m,s=l.title,r=void 0===s?null:s,f=l.classes,M=void 0===f?[]:f,n=l.attributes,H=void 0===n?{}:n,o=l.styles,V=void 0===o?{}:o;if(c){var C=c.prefix,L=c.iconName,u=c.icon;return F(fc({type:"icon"},c),function(){return j(),Hc.autoA11y&&(r?H["aria-labelledby"]=Hc.replacementClass+"-title-"+v():H["aria-hidden"]="true"),i({icons:{main:T(u),mask:t?T(t.icon):{found:!1,width:null,height:null,icon:{}}},prefix:C,iconName:L,transform:fc({},Vc,z),symbol:a,title:r,extra:{attributes:H,styles:V,classes:M}})})}}),text:function(c){var l=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},h=l.transform,v=void 0===h?Vc:h,z=l.title,e=void 0===z?null:z,a=l.classes,m=void 0===a?[]:a,t=l.attributes,s=void 0===t?{}:t,r=l.styles,f=void 0===r?{}:r;return F({type:"text",content:c},function(){return j(),n({content:c,transform:fc({},Vc,v),title:e,extra:{attributes:s,styles:f,classes:[Hc.familyPrefix+"-layers-text"].concat(ic(m))}})})},layer:function(c){return F({type:"layer"},function(){j();var l=[];return c(function(c){l=Array.isArray(c)?c.map(function(c){l=l.concat(c.abstract)}):l.concat(c.abstract)}),[{tag:"span",attributes:{class:Hc.familyPrefix+"-layers"},children:l}]})}};Object.defineProperty(fl,"config",{get:function(){Hc.autoReplaceSvg,Hc.observeMutations,Hc.showMissingIcons;return Mc(Hc,["autoReplaceSvg","observeMutations","showMissingIcons"])},set:function(l){c(l)}}),function(c){try{c()}catch(c){}}(function(){var c=function(){Hc.autoReplaceSvg&&fl.dom.i2svg({node:K})};Q&&(U.FontAwesome||(U.FontAwesome=fl),ml(function(){Object.keys(wc.styles).length>0&&c(),Hc.observeMutations&&"function"==typeof MutationObserver&&w({treeCallback:N,nodeCallback:q,pseudoElementsCallback:E})})),wc.hooks=fc({},wc.hooks,{addPack:function(l,h){wc.styles[l]=fc({},wc.styles[l]||{},h),jc(),c()},addShims:function(l){var h;(h=wc.shims).push.apply(h,ic(l)),jc(),c()}})})}(); diff --git a/web/gui/lib/gauge-1.3.2.min.js b/web/gui/lib/gauge-1.3.2.min.js new file mode 100644 index 0000000..7d9e163 --- /dev/null +++ b/web/gui/lib/gauge-1.3.2.min.js @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +(function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p=[].slice,q={}.hasOwnProperty,r=function(a,b){function d(){this.constructor=a}for(var c in b)q.call(b,c)&&(a[c]=b[c]);return d.prototype=b.prototype,a.prototype=new d,a.__super__=b.prototype,a};!function(){var a,b,c,d,e,f,g;for(g=["ms","moz","webkit","o"],c=0,e=g.length;c<e&&(f=g[c],!window.requestAnimationFrame);c++)window.requestAnimationFrame=window[f+"RequestAnimationFrame"],window.cancelAnimationFrame=window[f+"CancelAnimationFrame"]||window[f+"CancelRequestAnimationFrame"];return a=null,d=0,b={},requestAnimationFrame?window.cancelAnimationFrame?void 0:(a=window.requestAnimationFrame,window.requestAnimationFrame=function(c,e){var f;return f=++d,a(function(){if(!b[f])return c()},e),f},window.cancelAnimationFrame=function(a){return b[a]=!0}):(window.requestAnimationFrame=function(a,b){var c,d,e,f;return c=(new Date).getTime(),f=Math.max(0,16-(c-e)),d=window.setTimeout(function(){return a(c+f)},f),e=c+f,d},window.cancelAnimationFrame=function(a){return clearTimeout(a)})}(),String.prototype.hashCode=function(){var a,b,c,d,e;if(b=0,0===this.length)return b;for(c=d=0,e=this.length;0<=e?d<e:d>e;c=0<=e?++d:--d)a=this.charCodeAt(c),b=(b<<5)-b+a,b&=b;return b},o=function(a){var b,c;for(b=Math.floor(a/3600),c=Math.floor((a-3600*b)/60),a-=3600*b+60*c,a+="",c+="";c.length<2;)c="0"+c;for(;a.length<2;)a="0"+a;return b=b?b+":":"",b+c+":"+a},m=function(){var a,b,c;return b=1<=arguments.length?p.call(arguments,0):[],c=b[0],a=b[1],k(c.toFixed(a))},n=function(a,b){var c,d,e;d={};for(c in a)q.call(a,c)&&(e=a[c],d[c]=e);for(c in b)q.call(b,c)&&(e=b[c],d[c]=e);return d},k=function(a){var b,c,d,e;for(a+="",c=a.split("."),d=c[0],e="",c.length>1&&(e="."+c[1]),b=/(\d+)(\d{3})/;b.test(d);)d=d.replace(b,"$1,$2");return d+e},l=function(a){return"#"===a.charAt(0)?a.substring(1,7):a},j=function(){function a(a,b){null==a&&(a=!0),this.clear=null==b||b,a&&AnimationUpdater.add(this)}return a.prototype.animationSpeed=32,a.prototype.update=function(a){var b;return null==a&&(a=!1),!(!a&&this.displayedValue===this.value)&&(this.ctx&&this.clear&&this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),b=this.value-this.displayedValue,Math.abs(b/this.animationSpeed)<=.001?this.displayedValue=this.value:this.displayedValue=this.displayedValue+b/this.animationSpeed,this.render(),!0)},a}(),e=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return r(b,a),b.prototype.displayScale=1,b.prototype.setTextField=function(a,b){return this.textField=a instanceof i?a:new i(a,b)},b.prototype.setMinValue=function(a,b){var c,d,e,f,g;if(this.minValue=a,null==b&&(b=!0),b){for(this.displayedValue=this.minValue,f=this.gp||[],g=[],d=0,e=f.length;d<e;d++)c=f[d],g.push(c.displayedValue=this.minValue);return g}},b.prototype.setOptions=function(a){return null==a&&(a=null),this.options=n(this.options,a),this.textField&&(this.textField.el.style.fontSize=a.fontSize+"px"),this.options.angle>.5&&(this.options.angle=.5),this.configDisplayScale(),this},b.prototype.configDisplayScale=function(){var a,b,c,d,e;return d=this.displayScale,this.options.highDpiSupport===!1?delete this.displayScale:(b=window.devicePixelRatio||1,a=this.ctx.webkitBackingStorePixelRatio||this.ctx.mozBackingStorePixelRatio||this.ctx.msBackingStorePixelRatio||this.ctx.oBackingStorePixelRatio||this.ctx.backingStorePixelRatio||1,this.displayScale=b/a),this.displayScale!==d&&(e=this.canvas.G__width||this.canvas.width,c=this.canvas.G__height||this.canvas.height,this.canvas.width=e*this.displayScale,this.canvas.height=c*this.displayScale,this.canvas.style.width=e+"px",this.canvas.style.height=c+"px",this.canvas.G__width=e,this.canvas.G__height=c),this},b}(j),i=function(){function a(a,b){this.el=a,this.fractionDigits=b}return a.prototype.render=function(a){return this.el.innerHTML=m(a.displayedValue,this.fractionDigits)},a}(),a=function(a){function b(a,b){this.elem=a,this.text=null!=b&&b,this.value=1*this.elem.innerHTML,this.text&&(this.value=0)}return r(b,a),b.prototype.displayedValue=0,b.prototype.value=0,b.prototype.setVal=function(a){return this.value=1*a},b.prototype.render=function(){var a;return a=this.text?o(this.displayedValue.toFixed(0)):k(m(this.displayedValue)),this.elem.innerHTML=a},b}(j),b={create:function(b){var c,d,e,f;for(f=[],d=0,e=b.length;d<e;d++)c=b[d],f.push(new a(c));return f}},h=function(a){function b(a){this.gauge=a,this.ctx=this.gauge.ctx,this.canvas=this.gauge.canvas,b.__super__.constructor.call(this,!1,!1),this.setOptions()}return r(b,a),b.prototype.displayedValue=0,b.prototype.value=0,b.prototype.options={strokeWidth:.035,length:.1,color:"#000000"},b.prototype.setOptions=function(a){return null==a&&(a=null),this.options=n(this.options,a),this.length=2*this.gauge.radius*this.gauge.options.radiusScale*this.options.length,this.strokeWidth=this.canvas.height*this.options.strokeWidth,this.maxValue=this.gauge.maxValue,this.minValue=this.gauge.minValue,this.animationSpeed=this.gauge.animationSpeed,this.options.angle=this.gauge.options.angle},b.prototype.render=function(){var a,b,c,d,e,f,g;return a=this.gauge.getAngle.call(this,this.displayedValue),f=Math.round(this.length*Math.cos(a)),g=Math.round(this.length*Math.sin(a)),d=Math.round(this.strokeWidth*Math.cos(a-Math.PI/2)),e=Math.round(this.strokeWidth*Math.sin(a-Math.PI/2)),b=Math.round(this.strokeWidth*Math.cos(a+Math.PI/2)),c=Math.round(this.strokeWidth*Math.sin(a+Math.PI/2)),this.ctx.fillStyle=this.options.color,this.ctx.beginPath(),this.ctx.arc(0,0,this.strokeWidth,0,2*Math.PI,!0),this.ctx.fill(),this.ctx.beginPath(),this.ctx.moveTo(d,e),this.ctx.lineTo(f,g),this.ctx.lineTo(b,c),this.ctx.fill()},b}(j),c=function(){function a(a){this.elem=a}return a.prototype.updateValues=function(a){return this.value=a[0],this.maxValue=a[1],this.avgValue=a[2],this.render()},a.prototype.render=function(){var a,b;return this.textField&&this.textField.text(m(this.value)),0===this.maxValue&&(this.maxValue=2*this.avgValue),b=this.value/this.maxValue*100,a=this.avgValue/this.maxValue*100,$(".bar-value",this.elem).css({width:b+"%"}),$(".typical-value",this.elem).css({width:a+"%"})},a}(),g=function(a){function b(a){var c,d;this.canvas=a,b.__super__.constructor.call(this),this.percentColors=null,this.forceUpdate=!0,"undefined"!=typeof G_vmlCanvasManager&&(this.canvas=window.G_vmlCanvasManager.initElement(this.canvas)),this.ctx=this.canvas.getContext("2d"),c=this.canvas.clientHeight,d=this.canvas.clientWidth,this.canvas.height=c,this.canvas.width=d,this.gp=[new h(this)],this.setOptions(),this.render()}return r(b,a),b.prototype.elem=null,b.prototype.value=[20],b.prototype.maxValue=80,b.prototype.minValue=0,b.prototype.displayedAngle=0,b.prototype.displayedValue=0,b.prototype.lineWidth=40,b.prototype.paddingTop=.1,b.prototype.paddingBottom=.1,b.prototype.percentColors=null,b.prototype.options={colorStart:"#6fadcf",colorStop:void 0,gradientType:0,strokeColor:"#e0e0e0",pointer:{length:.8,strokeWidth:.035},angle:.15,lineWidth:.44,radiusScale:1,fontSize:40,limitMax:!1,limitMin:!1},b.prototype.setOptions=function(a){var c,d,e,f,g;for(null==a&&(a=null),b.__super__.setOptions.call(this,a),this.configPercentColors(),this.extraPadding=0,this.options.angle<0&&(f=Math.PI*(1+this.options.angle),this.extraPadding=Math.sin(f)),this.availableHeight=this.canvas.height*(1-this.paddingTop-this.paddingBottom),this.lineWidth=this.availableHeight*this.options.lineWidth,this.radius=(this.availableHeight-this.lineWidth/2)/(1+this.extraPadding),this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),g=this.gp,d=0,e=g.length;d<e;d++)c=g[d],c.setOptions(this.options.pointer),c.render();return this},b.prototype.configPercentColors=function(){var a,b,c,d,e,f,g;if(this.percentColors=null,void 0!==this.options.percentColors){for(this.percentColors=new Array,f=[],c=d=0,e=this.options.percentColors.length-1;0<=e?d<=e:d>=e;c=0<=e?++d:--d)g=parseInt(l(this.options.percentColors[c][1]).substring(0,2),16),b=parseInt(l(this.options.percentColors[c][1]).substring(2,4),16),a=parseInt(l(this.options.percentColors[c][1]).substring(4,6),16),f.push(this.percentColors[c]={pct:this.options.percentColors[c][0],color:{r:g,g:b,b:a}});return f}},b.prototype.set=function(a){var b,c,d,e,f,g,i;if(a instanceof Array||(a=[a]),a.length>this.gp.length)for(c=d=0,g=a.length-this.gp.length;0<=g?d<g:d>g;c=0<=g?++d:--d)b=new h(this),b.setOptions(this.options.pointer),this.gp.push(b);else a.length<this.gp.length&&(this.gp=this.gp.slice(this.gp.length-a.length));for(c=0,e=0,f=a.length;e<f;e++)i=a[e],i>this.maxValue?this.options.limitMax?i=this.maxValue:this.maxValue=i+1:i<this.minValue&&(this.options.limitMin?i=this.minValue:this.minValue=i-1),this.gp[c].value=i,this.gp[c++].setOptions({minValue:this.minValue,maxValue:this.maxValue,angle:this.options.angle});return this.value=Math.max(Math.min(a[a.length-1],this.maxValue),this.minValue),AnimationUpdater.run(this.forceUpdate),this.forceUpdate=!1},b.prototype.getAngle=function(a){return(1+this.options.angle)*Math.PI+(a-this.minValue)/(this.maxValue-this.minValue)*(1-2*this.options.angle)*Math.PI},b.prototype.getColorForPercentage=function(a,b){var c,d,e,f,g,h,i;if(0===a)c=this.percentColors[0].color;else for(c=this.percentColors[this.percentColors.length-1].color,e=f=0,h=this.percentColors.length-1;0<=h?f<=h:f>=h;e=0<=h?++f:--f)if(a<=this.percentColors[e].pct){b===!0?(i=this.percentColors[e-1]||this.percentColors[0],d=this.percentColors[e],g=(a-i.pct)/(d.pct-i.pct),c={r:Math.floor(i.color.r*(1-g)+d.color.r*g),g:Math.floor(i.color.g*(1-g)+d.color.g*g),b:Math.floor(i.color.b*(1-g)+d.color.b*g)}):c=this.percentColors[e].color;break}return"rgb("+[c.r,c.g,c.b].join(",")+")"},b.prototype.getColorForValue=function(a,b){var c;return c=(a-this.minValue)/(this.maxValue-this.minValue),this.getColorForPercentage(c,b)},b.prototype.renderStaticLabels=function(a,b,c,d){var e,f,g,h,i,j,k,l,n,o;for(this.ctx.save(),this.ctx.translate(b,c),e=a.font||"10px Times",j=/\d+\.?\d?/,i=e.match(j)[0],l=e.slice(i.length),f=parseFloat(i)*this.displayScale,this.ctx.font=f+l,this.ctx.fillStyle=a.color||"#000000",this.ctx.textBaseline="bottom",this.ctx.textAlign="center",k=a.labels,g=0,h=k.length;g<h;g++)o=k[g],(!this.options.limitMin||o>=this.minValue)&&(!this.options.limitMax||o<=this.maxValue)&&(n=this.getAngle(o)-3*Math.PI/2,this.ctx.rotate(n),this.ctx.fillText(m(o,a.fractionDigits),0,-d-this.lineWidth/2),this.ctx.rotate(-n));return this.ctx.restore()},b.prototype.render=function(){var a,b,c,d,e,f,g,h,i,j,k,l,m,n,o;if(n=this.canvas.width/2,d=this.canvas.height*this.paddingTop+this.availableHeight-(this.radius+this.lineWidth/2)*this.extraPadding,a=this.getAngle(this.displayedValue),this.textField&&this.textField.render(this),this.ctx.lineCap="butt",k=this.radius*this.options.radiusScale,this.options.staticLabels&&this.renderStaticLabels(this.options.staticLabels,n,d,k),this.options.staticZones){for(this.ctx.save(),this.ctx.translate(n,d),this.ctx.lineWidth=this.lineWidth,l=this.options.staticZones,e=0,g=l.length;e<g;e++)o=l[e],j=o.min,this.options.limitMin&&j<this.minValue&&(j=this.minValue),i=o.max,this.options.limitMax&&i>this.maxValue&&(i=this.maxValue),this.ctx.strokeStyle=o.strokeStyle,this.ctx.beginPath(),this.ctx.arc(0,0,k,this.getAngle(j),this.getAngle(i),!1),this.ctx.stroke();this.ctx.restore()}else void 0!==this.options.customFillStyle?b=this.options.customFillStyle(this):null!==this.percentColors?b=this.getColorForValue(this.displayedValue,!0):void 0!==this.options.colorStop?(b=0===this.options.gradientType?this.ctx.createRadialGradient(n,d,9,n,d,70):this.ctx.createLinearGradient(0,0,n,0),b.addColorStop(0,this.options.colorStart),b.addColorStop(1,this.options.colorStop)):b=this.options.colorStart,this.ctx.strokeStyle=b,this.ctx.beginPath(),this.ctx.arc(n,d,k,(1+this.options.angle)*Math.PI,a,!1),this.ctx.lineWidth=this.lineWidth,this.ctx.stroke(),this.ctx.strokeStyle=this.options.strokeColor,this.ctx.beginPath(),this.ctx.arc(n,d,k,a,(2-this.options.angle)*Math.PI,!1),this.ctx.stroke();for(this.ctx.translate(n,d),m=this.gp,f=0,h=m.length;f<h;f++)c=m[f],c.update(!0);return this.ctx.translate(-n,-d)},b}(e),d=function(a){function b(a){this.canvas=a,b.__super__.constructor.call(this),"undefined"!=typeof G_vmlCanvasManager&&(this.canvas=window.G_vmlCanvasManager.initElement(this.canvas)),this.ctx=this.canvas.getContext("2d"),this.setOptions(),this.render()}return r(b,a),b.prototype.lineWidth=15,b.prototype.displayedValue=0,b.prototype.value=33,b.prototype.maxValue=80,b.prototype.minValue=0,b.prototype.options={lineWidth:.1,colorStart:"#6f6ea0",colorStop:"#c0c0db",strokeColor:"#eeeeee",shadowColor:"#d5d5d5",angle:.35,radiusScale:1},b.prototype.getAngle=function(a){return(1-this.options.angle)*Math.PI+(a-this.minValue)/(this.maxValue-this.minValue)*(2+this.options.angle-(1-this.options.angle))*Math.PI},b.prototype.setOptions=function(a){return null==a&&(a=null),b.__super__.setOptions.call(this,a),this.lineWidth=this.canvas.height*this.options.lineWidth,this.radius=this.options.radiusScale*(this.canvas.height/2-this.lineWidth/2),this},b.prototype.set=function(a){return this.value=a,this.value>this.maxValue&&(this.maxValue=1.1*this.value),AnimationUpdater.run()},b.prototype.render=function(){var a,b,c,d,e,f;return a=this.getAngle(this.displayedValue),f=this.canvas.width/2,c=this.canvas.height/2,this.textField&&this.textField.render(this),b=this.ctx.createRadialGradient(f,c,39,f,c,70),b.addColorStop(0,this.options.colorStart),b.addColorStop(1,this.options.colorStop),d=this.radius-this.lineWidth/2,e=this.radius+this.lineWidth/2,this.ctx.strokeStyle=this.options.strokeColor,this.ctx.beginPath(),this.ctx.arc(f,c,this.radius,(1-this.options.angle)*Math.PI,(2+this.options.angle)*Math.PI,!1),this.ctx.lineWidth=this.lineWidth,this.ctx.lineCap="round",this.ctx.stroke(),this.ctx.strokeStyle=b,this.ctx.beginPath(),this.ctx.arc(f,c,this.radius,(1-this.options.angle)*Math.PI,a,!1),this.ctx.stroke()},b}(e),f=function(a){function b(){return b.__super__.constructor.apply(this,arguments)}return r(b,a),b.prototype.strokeGradient=function(a,b,c,d){var e;return e=this.ctx.createRadialGradient(a,b,c,a,b,d),e.addColorStop(0,this.options.shadowColor),e.addColorStop(.12,this.options._orgStrokeColor),e.addColorStop(.88,this.options._orgStrokeColor),e.addColorStop(1,this.options.shadowColor),e},b.prototype.setOptions=function(a){var c,d,e,f;return null==a&&(a=null),b.__super__.setOptions.call(this,a),f=this.canvas.width/2,c=this.canvas.height/2,d=this.radius-this.lineWidth/2,e=this.radius+this.lineWidth/2,this.options._orgStrokeColor=this.options.strokeColor,this.options.strokeColor=this.strokeGradient(f,c,d,e),this},b}(d),window.AnimationUpdater={elements:[],animId:null,addAll:function(a){var b,c,d,e;for(e=[],c=0,d=a.length;c<d;c++)b=a[c],e.push(AnimationUpdater.elements.push(b));return e},add:function(a){return AnimationUpdater.elements.push(a)},run:function(a){var b,c,d,e,f;for(null==a&&(a=!1),b=!0,f=AnimationUpdater.elements,d=0,e=f.length;d<e;d++)c=f[d],c.update(a===!0)&&(b=!1);return b?cancelAnimationFrame(AnimationUpdater.animId):AnimationUpdater.animId=requestAnimationFrame(AnimationUpdater.run)}},"function"==typeof window.define&&null!=window.define.amd?define(function(){return{Gauge:g,Donut:f,BaseDonut:d,TextRenderer:i}}):"undefined"!=typeof module&&null!=module.exports?module.exports={Gauge:g,Donut:f,BaseDonut:d,TextRenderer:i}:(window.Gauge=g,window.Donut=f,window.BaseDonut=d,window.TextRenderer=i)}).call(this); diff --git a/web/gui/lib/jquery-2.2.4.min.js b/web/gui/lib/jquery-2.2.4.min.js new file mode 100644 index 0000000..c641fda --- /dev/null +++ b/web/gui/lib/jquery-2.2.4.min.js @@ -0,0 +1,5 @@ +/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */ +// SPDX-License-Identifier: MIT +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};n.fn=n.prototype={jquery:m,constructor:n,selector:"",length:0,toArray:function(){return e.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:e.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a){return n.each(this,a)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(e.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor()},push:g,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(n.isPlainObject(d)||(e=n.isArray(d)))?(e?(e=!1,f=c&&n.isArray(c)?c:[]):f=c&&n.isPlainObject(c)?c:{},g[b]=n.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){var b=a&&a.toString();return!n.isArray(a)&&b-parseFloat(b)+1>=0},isPlainObject:function(a){var b;if("object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;if(a.constructor&&!k.call(a,"constructor")&&!k.call(a.constructor.prototype||{},"isPrototypeOf"))return!1;for(b in a);return void 0===b||k.call(a,b)},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?i[j.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=n.trim(a),a&&(1===a.indexOf("use strict")?(b=d.createElement("script"),b.text=a,d.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b){var c,d=0;if(s(a)){for(c=a.length;c>d;d++)if(b.call(a[d],d,a[d])===!1)break}else for(d in a)if(b.call(a[d],d,a[d])===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):g.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:h.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,e,g=0,h=[];if(s(a))for(d=a.length;d>g;g++)e=b(a[g],g,c),null!=e&&h.push(e);else for(g in a)e=b(a[g],g,c),null!=e&&h.push(e);return f.apply([],h)},guid:1,proxy:function(a,b){var c,d,f;return"string"==typeof b&&(c=a[b],b=a,a=c),n.isFunction(a)?(d=e.call(arguments,2),f=function(){return a.apply(b||this,d.concat(e.call(arguments)))},f.guid=a.guid=a.guid||n.guid++,f):void 0},now:Date.now,support:l}),"function"==typeof Symbol&&(n.fn[Symbol.iterator]=c[Symbol.iterator]),n.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(a,b){i["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=!!a&&"length"in a&&a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ga(),z=ga(),A=ga(),B=function(a,b){return a===b&&(l=!0),0},C=1<<31,D={}.hasOwnProperty,E=[],F=E.pop,G=E.push,H=E.push,I=E.slice,J=function(a,b){for(var c=0,d=a.length;d>c;c++)if(a[c]===b)return c;return-1},K="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",L="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",N="\\["+L+"*("+M+")(?:"+L+"*([*^$|!~]?=)"+L+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+M+"))|)"+L+"*\\]",O=":("+M+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+N+")*)|.*)\\)|)",P=new RegExp(L+"+","g"),Q=new RegExp("^"+L+"+|((?:^|[^\\\\])(?:\\\\.)*)"+L+"+$","g"),R=new RegExp("^"+L+"*,"+L+"*"),S=new RegExp("^"+L+"*([>+~]|"+L+")"+L+"*"),T=new RegExp("="+L+"*([^\\]'\"]*?)"+L+"*\\]","g"),U=new RegExp(O),V=new RegExp("^"+M+"$"),W={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),TAG:new RegExp("^("+M+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+L+"*(even|odd|(([+-]|)(\\d*)n|)"+L+"*(?:([+-]|)"+L+"*(\\d+)|))"+L+"*\\)|)","i"),bool:new RegExp("^(?:"+K+")$","i"),needsContext:new RegExp("^"+L+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+L+"*((?:-\\d)?\\d*)"+L+"*\\)|)(?=[^-]|$)","i")},X=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,$=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,_=/[+~]/,aa=/'|\\/g,ba=new RegExp("\\\\([\\da-f]{1,6}"+L+"?|("+L+")|.)","ig"),ca=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},da=function(){m()};try{H.apply(E=I.call(v.childNodes),v.childNodes),E[v.childNodes.length].nodeType}catch(ea){H={apply:E.length?function(a,b){G.apply(a,I.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fa(a,b,d,e){var f,h,j,k,l,o,r,s,w=b&&b.ownerDocument,x=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==x&&9!==x&&11!==x)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==x&&(o=$.exec(a)))if(f=o[1]){if(9===x){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(w&&(j=w.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(o[2])return H.apply(d,b.getElementsByTagName(a)),d;if((f=o[3])&&c.getElementsByClassName&&b.getElementsByClassName)return H.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==x)w=b,s=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(aa,"\\$&"):b.setAttribute("id",k=u),r=g(a),h=r.length,l=V.test(k)?"#"+k:"[id='"+k+"']";while(h--)r[h]=l+" "+qa(r[h]);s=r.join(","),w=_.test(a)&&oa(b.parentNode)||b}if(s)try{return H.apply(d,w.querySelectorAll(s)),d}catch(y){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(Q,"$1"),b,d,e)}function ga(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ha(a){return a[u]=!0,a}function ia(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ja(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function ka(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||C)-(~a.sourceIndex||C);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function la(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function na(a){return ha(function(b){return b=+b,ha(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function oa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=fa.support={},f=fa.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fa.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ia(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ia(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Z.test(n.getElementsByClassName),c.getById=ia(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ba,ca);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return"undefined"!=typeof b.getElementsByClassName&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=Z.test(n.querySelectorAll))&&(ia(function(a){o.appendChild(a).innerHTML="<a id='"+u+"'></a><select id='"+u+"-\r\\' msallowcapture=''><option selected=''></option></select>",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+L+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+L+"*(?:value|"+K+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ia(function(a){var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+L+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Z.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ia(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",O)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Z.test(o.compareDocumentPosition),t=b||Z.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?J(k,a)-J(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?J(k,a)-J(k,b):0;if(e===f)return ka(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?ka(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},fa.matches=function(a,b){return fa(a,null,null,b)},fa.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(T,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fa(b,n,null,[a]).length>0},fa.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fa.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&D.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fa.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fa.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fa.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fa.selectors={cacheLength:50,createPseudo:ha,match:W,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ba,ca),a[3]=(a[3]||a[4]||a[5]||"").replace(ba,ca),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fa.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fa.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return W.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&U.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ba,ca).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+L+")"+a+"("+L+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fa.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(P," ")+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fa.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ha(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=J(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ha(function(a){var b=[],c=[],d=h(a.replace(Q,"$1"));return d[u]?ha(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ha(function(a){return function(b){return fa(a,b).length>0}}),contains:ha(function(a){return a=a.replace(ba,ca),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ha(function(a){return V.test(a||"")||fa.error("unsupported lang: "+a),a=a.replace(ba,ca).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Y.test(a.nodeName)},input:function(a){return X.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:na(function(){return[0]}),last:na(function(a,b){return[b-1]}),eq:na(function(a,b,c){return[0>c?c+b:c]}),even:na(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:na(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:na(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:na(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=la(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=ma(b);function pa(){}pa.prototype=d.filters=d.pseudos,d.setFilters=new pa,g=fa.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){c&&!(e=R.exec(h))||(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=S.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(Q," ")}),h=h.slice(c.length));for(g in d.filter)!(e=W[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fa.error(a):z(a,i).slice(0)};function qa(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function ra(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j,k=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(j=b[u]||(b[u]={}),i=j[b.uniqueID]||(j[b.uniqueID]={}),(h=i[d])&&h[0]===w&&h[1]===f)return k[2]=h[2];if(i[d]=k,k[2]=a(b,c,g))return!0}}}function sa(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function ta(a,b,c){for(var d=0,e=b.length;e>d;d++)fa(a,b[d],c);return c}function ua(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(c&&!c(f,d,e)||(g.push(f),j&&b.push(h)));return g}function va(a,b,c,d,e,f){return d&&!d[u]&&(d=va(d)),e&&!e[u]&&(e=va(e,f)),ha(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||ta(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ua(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ua(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?J(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ua(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):H.apply(g,r)})}function wa(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ra(function(a){return a===b},h,!0),l=ra(function(a){return J(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];f>i;i++)if(c=d.relative[a[i].type])m=[ra(sa(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return va(i>1&&sa(m),i>1&&qa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(Q,"$1"),c,e>i&&wa(a.slice(i,e)),f>e&&wa(a=a.slice(e)),f>e&&qa(a))}m.push(c)}return sa(m)}function xa(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=F.call(i));u=ua(u)}H.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&fa.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ha(f):f}return h=fa.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wa(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xa(e,d)),f.selector=a}return f},i=fa.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(ba,ca),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=W.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(ba,ca),_.test(j[0].type)&&oa(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qa(j),!a)return H.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,!b||_.test(a)&&oa(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ia(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ia(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||ja("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ia(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ja("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ia(function(a){return null==a.getAttribute("disabled")})||ja(K,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fa}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.uniqueSort=n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&n(a).is(c))break;d.push(a)}return d},v=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},w=n.expr.match.needsContext,x=/^<([\w-]+)\s*\/?>(?:<\/\1>|)$/,y=/^.[^:#\[\.,]*$/;function z(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(y.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return h.call(b,a)>-1!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;c>b;b++)if(n.contains(e[b],this))return!0}));for(b=0;c>b;b++)n.find(a,e[b],d);return d=this.pushStack(c>1?n.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(z(this,a||[],!1))},not:function(a){return this.pushStack(z(this,a||[],!0))},is:function(a){return!!z(this,"string"==typeof a&&w.test(a)?n(a):a||[],!1).length}});var A,B=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=n.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||A,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:B.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),x.test(e[1])&&n.isPlainObject(b))for(e in b)n.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&f.parentNode&&(this.length=1,this[0]=f),this.context=d,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?void 0!==c.ready?c.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};C.prototype=n.fn,A=n(d);var D=/^(?:parents|prev(?:Until|All))/,E={children:!0,contents:!0,next:!0,prev:!0};n.fn.extend({has:function(a){var b=n(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(n.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=w.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?h.call(n(a),this[0]):h.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.uniqueSort(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function F(a,b){while((a=a[b])&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return u(a,"parentNode")},parentsUntil:function(a,b,c){return u(a,"parentNode",c)},next:function(a){return F(a,"nextSibling")},prev:function(a){return F(a,"previousSibling")},nextAll:function(a){return u(a,"nextSibling")},prevAll:function(a){return u(a,"previousSibling")},nextUntil:function(a,b,c){return u(a,"nextSibling",c)},prevUntil:function(a,b,c){return u(a,"previousSibling",c)},siblings:function(a){return v((a.parentNode||{}).firstChild,a)},children:function(a){return v(a.firstChild)},contents:function(a){return a.contentDocument||n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(E[a]||n.uniqueSort(e),D.test(a)&&e.reverse()),this.pushStack(e)}});var G=/\S+/g;function H(a){var b={};return n.each(a.match(G)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?H(a):n.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h<f.length)f[h].apply(c[0],c[1])===!1&&a.stopOnFalse&&(h=f.length,c=!1)}a.memory||(c=!1),b=!1,e&&(f=c?[]:"")},j={add:function(){return f&&(c&&!b&&(h=f.length-1,g.push(c)),function d(b){n.each(b,function(b,c){n.isFunction(c)?a.unique&&j.has(c)||f.push(c):c&&c.length&&"string"!==n.type(c)&&d(c)})}(arguments),c&&!b&&i()),this},remove:function(){return n.each(arguments,function(a,b){var c;while((c=n.inArray(b,f,c))>-1)f.splice(c,1),h>=c&&h--}),this},has:function(a){return a?n.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().progress(c.notify).done(c.resolve).fail(c.reject):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=e.call(arguments),d=c.length,f=1!==d||a&&n.isFunction(a.promise)?d:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(d){b[a]=this,c[a]=arguments.length>1?e.call(arguments):d,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(d>1)for(i=new Array(d),j=new Array(d),k=new Array(d);d>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().progress(h(b,j,i)).done(h(b,k,c)).fail(g.reject):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){(a===!0?--n.readyWait:n.isReady)||(n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(d,[n]),n.fn.triggerHandler&&(n(d).triggerHandler("ready"),n(d).off("ready"))))}});function J(){d.removeEventListener("DOMContentLoaded",J),a.removeEventListener("load",J),n.ready()}n.ready.promise=function(b){return I||(I=n.Deferred(),"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(n.ready):(d.addEventListener("DOMContentLoaded",J),a.addEventListener("load",J))),I.promise(b)},n.ready.promise();var K=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===n.type(c)){e=!0;for(h in c)K(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,n.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(n(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},L=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function M(){this.expando=n.expando+M.uid++}M.uid=1,M.prototype={register:function(a,b){var c=b||{};return a.nodeType?a[this.expando]=c:Object.defineProperty(a,this.expando,{value:c,writable:!0,configurable:!0}),a[this.expando]},cache:function(a){if(!L(a))return{};var b=a[this.expando];return b||(b={},L(a)&&(a.nodeType?a[this.expando]=b:Object.defineProperty(a,this.expando,{value:b,configurable:!0}))),b},set:function(a,b,c){var d,e=this.cache(a);if("string"==typeof b)e[b]=c;else for(d in b)e[d]=b[d];return e},get:function(a,b){return void 0===b?this.cache(a):a[this.expando]&&a[this.expando][b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,n.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=a[this.expando];if(void 0!==f){if(void 0===b)this.register(a);else{n.isArray(b)?d=b.concat(b.map(n.camelCase)):(e=n.camelCase(b),b in f?d=[b,e]:(d=e,d=d in f?[d]:d.match(G)||[])),c=d.length;while(c--)delete f[d[c]]}(void 0===b||n.isEmptyObject(f))&&(a.nodeType?a[this.expando]=void 0:delete a[this.expando])}},hasData:function(a){var b=a[this.expando];return void 0!==b&&!n.isEmptyObject(b)}};var N=new M,O=new M,P=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,Q=/[A-Z]/g;function R(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(Q,"-$&").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:P.test(c)?n.parseJSON(c):c; +}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),R(f,d,e[d])));N.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){O.set(this,a)}):K(this,function(b){var c,d;if(f&&void 0===b){if(c=O.get(f,a)||O.get(f,a.replace(Q,"-$&").toLowerCase()),void 0!==c)return c;if(d=n.camelCase(a),c=O.get(f,d),void 0!==c)return c;if(c=R(f,d,void 0),void 0!==c)return c}else d=n.camelCase(a),this.each(function(){var c=O.get(this,d);O.set(this,d,b),a.indexOf("-")>-1&&void 0!==c&&O.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){O.remove(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=N.get(a,b),c&&(!d||n.isArray(c)?d=N.access(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return N.get(a,c)||N.access(a,c,{empty:n.Callbacks("once memory").add(function(){N.remove(a,[b+"queue",c])})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?n.queue(this[0],a):void 0===b?this:this.each(function(){var c=n.queue(this,a,b);n._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&n.dequeue(this,a)})},dequeue:function(a){return this.each(function(){n.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=n.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=N.get(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),U=["Top","Right","Bottom","Left"],V=function(a,b){return a=b||a,"none"===n.css(a,"display")||!n.contains(a.ownerDocument,a)};function W(a,b,c,d){var e,f=1,g=20,h=d?function(){return d.cur()}:function(){return n.css(a,b,"")},i=h(),j=c&&c[3]||(n.cssNumber[b]?"":"px"),k=(n.cssNumber[b]||"px"!==j&&+i)&&T.exec(n.css(a,b));if(k&&k[3]!==j){j=j||k[3],c=c||[],k=+i||1;do f=f||".5",k/=f,n.style(a,b,k+j);while(f!==(f=h()/i)&&1!==f&&--g)}return c&&(k=+k||+i||0,e=c[1]?k+(c[1]+1)*c[2]:+c[2],d&&(d.unit=j,d.start=k,d.end=e)),e}var X=/^(?:checkbox|radio)$/i,Y=/<([\w:-]+)/,Z=/^$|\/(?:java|ecma)script/i,$={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|&#?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="<textarea>x</textarea>",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return a;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())a.rnamespace&&!a.rnamespace.test(g.namespace)||(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},props:"altKey bubbles cancelable ctrlKey currentTarget detail eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,e,f,g=b.button;return null==a.pageX&&null!=b.clientX&&(c=a.target.ownerDocument||d,e=c.documentElement,f=c.body,a.pageX=b.clientX+(e&&e.scrollLeft||f&&f.scrollLeft||0)-(e&&e.clientLeft||f&&f.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||f&&f.scrollTop||0)-(e&&e.clientTop||f&&f.clientTop||0)),a.which||void 0===g||(a.which=1&g?1:2&g?3:4&g?2:0),a}},fix:function(a){if(a[n.expando])return a;var b,c,e,f=a.type,g=a,h=this.fixHooks[f];h||(this.fixHooks[f]=h=ea.test(f)?this.mouseHooks:da.test(f)?this.keyHooks:{}),e=h.props?this.props.concat(h.props):this.props,a=new n.Event(g),b=e.length;while(b--)c=e[b],a[c]=g[c];return a.target||(a.target=d),3===a.target.nodeType&&(a.target=a.target.parentNode),h.filter?h.filter(a,g):a},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==ia()&&this.focus?(this.focus(),!1):void 0},delegateType:"focusin"},blur:{trigger:function(){return this===ia()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&n.nodeName(this,"input")?(this.click(),!1):void 0},_default:function(a){return n.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}}},n.removeEvent=function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c)},n.Event=function(a,b){return this instanceof n.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ga:ha):this.type=a,b&&n.extend(this,b),this.timeStamp=a&&a.timeStamp||n.now(),void(this[n.expando]=!0)):new n.Event(a,b)},n.Event.prototype={constructor:n.Event,isDefaultPrevented:ha,isPropagationStopped:ha,isImmediatePropagationStopped:ha,isSimulated:!1,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ga,a&&!this.isSimulated&&a.preventDefault()},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ga,a&&!this.isSimulated&&a.stopPropagation()},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ga,a&&!this.isSimulated&&a.stopImmediatePropagation(),this.stopPropagation()}},n.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){n.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return e&&(e===d||n.contains(d,e))||(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),n.fn.extend({on:function(a,b,c,d){return ja(this,a,b,c,d)},one:function(a,b,c,d){return ja(this,a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,n(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return b!==!1&&"function"!=typeof b||(c=b,b=void 0),c===!1&&(c=ha),this.each(function(){n.event.remove(this,a,c,b)})}});var ka=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,la=/<script|<style|<link/i,ma=/checked\s*(?:[^=]|=\s*.checked.)/i,na=/^true\/(.*)/,oa=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function pa(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function qa(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function ra(a){var b=na.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function sa(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(N.hasData(a)&&(f=N.access(a),g=N.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)n.event.add(b,e,j[e][c])}O.hasData(a)&&(h=O.access(a),i=n.extend({},h),O.set(b,i))}}function ta(a,b){var c=b.nodeName.toLowerCase();"input"===c&&X.test(a.type)?b.checked=a.checked:"input"!==c&&"textarea"!==c||(b.defaultValue=a.defaultValue)}function ua(a,b,c,d){b=f.apply([],b);var e,g,h,i,j,k,m=0,o=a.length,p=o-1,q=b[0],r=n.isFunction(q);if(r||o>1&&"string"==typeof q&&!l.checkClone&&ma.test(q))return a.each(function(e){var f=a.eq(e);r&&(b[0]=q.call(this,e,f.html())),ua(f,b,c,d)});if(o&&(e=ca(b,a[0].ownerDocument,!1,a,d),g=e.firstChild,1===e.childNodes.length&&(e=g),g||d)){for(h=n.map(_(e,"script"),qa),i=h.length;o>m;m++)j=e,m!==p&&(j=n.clone(j,!0,!0),i&&n.merge(h,_(j,"script"))),c.call(a[m],j,m);if(i)for(k=h[h.length-1].ownerDocument,n.map(h,ra),m=0;i>m;m++)j=h[m],Z.test(j.type||"")&&!N.access(j,"globalEval")&&n.contains(k,j)&&(j.src?n._evalUrl&&n._evalUrl(j.src):n.globalEval(j.textContent.replace(oa,"")))}return a}function va(a,b,c){for(var d,e=b?n.filter(b,a):a,f=0;null!=(d=e[f]);f++)c||1!==d.nodeType||n.cleanData(_(d)),d.parentNode&&(c&&n.contains(d.ownerDocument,d)&&aa(_(d,"script")),d.parentNode.removeChild(d));return a}n.extend({htmlPrefilter:function(a){return a.replace(ka,"<$1></$2>")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=n.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(g=_(h),f=_(a),d=0,e=f.length;e>d;d++)ta(f[d],g[d]);if(b)if(c)for(f=f||_(a),g=g||_(h),d=0,e=f.length;e>d;d++)sa(f[d],g[d]);else sa(a,h);return g=_(h,"script"),g.length>0&&aa(g,!i&&_(a,"script")),h},cleanData:function(a){for(var b,c,d,e=n.event.special,f=0;void 0!==(c=a[f]);f++)if(L(c)){if(b=c[N.expando]){if(b.events)for(d in b.events)e[d]?n.event.remove(c,d):n.removeEvent(c,d,b.handle);c[N.expando]=void 0}c[O.expando]&&(c[O.expando]=void 0)}}}),n.fn.extend({domManip:ua,detach:function(a){return va(this,a,!0)},remove:function(a){return va(this,a)},text:function(a){return K(this,function(a){return void 0===a?n.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.appendChild(a)}})},prepend:function(){return ua(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=pa(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return ua(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(n.cleanData(_(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return K(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!la.test(a)&&!$[(Y.exec(a)||["",""])[1].toLowerCase()]){a=n.htmlPrefilter(a);try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(_(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=[];return ua(this,arguments,function(b){var c=this.parentNode;n.inArray(this,a)<0&&(n.cleanData(_(this)),c&&c.replaceChild(b,this))},a)}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=[],e=n(a),f=e.length-1,h=0;f>=h;h++)c=h===f?this:this.clone(!0),n(e[h])[b](c),g.apply(d,c.get());return this.pushStack(d)}});var wa,xa={HTML:"block",BODY:"block"};function ya(a,b){var c=n(b.createElement(a)).appendTo(b.body),d=n.css(c[0],"display");return c.detach(),d}function za(a){var b=d,c=xa[a];return c||(c=ya(a,b),"none"!==c&&c||(wa=(wa||n("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=wa[0].contentDocument,b.write(),b.close(),c=ya(a,b),wa.detach()),xa[a]=c),c}var Aa=/^margin/,Ba=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ca=function(b){var c=b.ownerDocument.defaultView;return c&&c.opener||(c=a),c.getComputedStyle(b)},Da=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e},Ea=d.documentElement;!function(){var b,c,e,f,g=d.createElement("div"),h=d.createElement("div");if(h.style){h.style.backgroundClip="content-box",h.cloneNode(!0).style.backgroundClip="",l.clearCloneStyle="content-box"===h.style.backgroundClip,g.style.cssText="border:0;width:8px;height:0;top:0;left:-9999px;padding:0;margin-top:1px;position:absolute",g.appendChild(h);function i(){h.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:relative;display:block;margin:auto;border:1px;padding:1px;top:1%;width:50%",h.innerHTML="",Ea.appendChild(g);var d=a.getComputedStyle(h);b="1%"!==d.top,f="2px"===d.marginLeft,c="4px"===d.width,h.style.marginRight="50%",e="4px"===d.marginRight,Ea.removeChild(g)}n.extend(l,{pixelPosition:function(){return i(),b},boxSizingReliable:function(){return null==c&&i(),c},pixelMarginRight:function(){return null==c&&i(),e},reliableMarginLeft:function(){return null==c&&i(),f},reliableMarginRight:function(){var b,c=h.appendChild(d.createElement("div"));return c.style.cssText=h.style.cssText="-webkit-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",c.style.marginRight=c.style.width="0",h.style.width="1px",Ea.appendChild(g),b=!parseFloat(a.getComputedStyle(c).marginRight),Ea.removeChild(g),h.removeChild(c),b}})}}();function Fa(a,b,c){var d,e,f,g,h=a.style;return c=c||Ca(a),g=c?c.getPropertyValue(b)||c[b]:void 0,""!==g&&void 0!==g||n.contains(a.ownerDocument,a)||(g=n.style(a,b)),c&&!l.pixelMarginRight()&&Ba.test(g)&&Aa.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f),void 0!==g?g+"":g}function Ga(a,b){return{get:function(){return a()?void delete this.get:(this.get=b).apply(this,arguments)}}}var Ha=/^(none|table(?!-c[ea]).+)/,Ia={position:"absolute",visibility:"hidden",display:"block"},Ja={letterSpacing:"0",fontWeight:"400"},Ka=["Webkit","O","Moz","ms"],La=d.createElement("div").style;function Ma(a){if(a in La)return a;var b=a[0].toUpperCase()+a.slice(1),c=Ka.length;while(c--)if(a=Ka[c]+b,a in La)return a}function Na(a,b,c){var d=T.exec(b);return d?Math.max(0,d[2]-(c||0))+(d[3]||"px"):b}function Oa(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=n.css(a,c+U[f],!0,e)),d?("content"===c&&(g-=n.css(a,"padding"+U[f],!0,e)),"margin"!==c&&(g-=n.css(a,"border"+U[f]+"Width",!0,e))):(g+=n.css(a,"padding"+U[f],!0,e),"padding"!==c&&(g+=n.css(a,"border"+U[f]+"Width",!0,e)));return g}function Pa(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ca(a),g="border-box"===n.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Fa(a,b,f),(0>e||null==e)&&(e=a.style[b]),Ba.test(e))return e;d=g&&(l.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Oa(a,b,c||(g?"border":"content"),d,f)+"px"}function Qa(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=N.get(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&V(d)&&(f[g]=N.access(d,"olddisplay",za(d.nodeName)))):(e=V(d),"none"===c&&e||N.set(d,"olddisplay",e?c:n.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}n.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Fa(a,"opacity");return""===c?"1":c}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=n.camelCase(b),i=a.style;return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],void 0===c?g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b]:(f=typeof c,"string"===f&&(e=T.exec(c))&&e[1]&&(c=W(a,b,e),f="number"),null!=c&&c===c&&("number"===f&&(c+=e&&e[3]||(n.cssNumber[h]?"":"px")),l.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),g&&"set"in g&&void 0===(c=g.set(a,c,d))||(i[b]=c)),void 0)}},css:function(a,b,c,d){var e,f,g,h=n.camelCase(b);return b=n.cssProps[h]||(n.cssProps[h]=Ma(h)||h),g=n.cssHooks[b]||n.cssHooks[h],g&&"get"in g&&(e=g.get(a,!0,c)),void 0===e&&(e=Fa(a,b,d)),"normal"===e&&b in Ja&&(e=Ja[b]),""===c||c?(f=parseFloat(e),c===!0||isFinite(f)?f||0:e):e}}),n.each(["height","width"],function(a,b){n.cssHooks[b]={get:function(a,c,d){return c?Ha.test(n.css(a,"display"))&&0===a.offsetWidth?Da(a,Ia,function(){return Pa(a,b,d)}):Pa(a,b,d):void 0},set:function(a,c,d){var e,f=d&&Ca(a),g=d&&Oa(a,b,d,"border-box"===n.css(a,"boxSizing",!1,f),f);return g&&(e=T.exec(c))&&"px"!==(e[3]||"px")&&(a.style[b]=c,c=n.css(a,b)),Na(a,c,g)}}}),n.cssHooks.marginLeft=Ga(l.reliableMarginLeft,function(a,b){return b?(parseFloat(Fa(a,"marginLeft"))||a.getBoundingClientRect().left-Da(a,{marginLeft:0},function(){return a.getBoundingClientRect().left}))+"px":void 0}),n.cssHooks.marginRight=Ga(l.reliableMarginRight,function(a,b){return b?Da(a,{display:"inline-block"},Fa,[a,"marginRight"]):void 0}),n.each({margin:"",padding:"",border:"Width"},function(a,b){n.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+U[d]+b]=f[d]||f[d-2]||f[0];return e}},Aa.test(a)||(n.cssHooks[a+b].set=Na)}),n.fn.extend({css:function(a,b){return K(this,function(a,b,c){var d,e,f={},g=0;if(n.isArray(b)){for(d=Ca(a),e=b.length;e>g;g++)f[b[g]]=n.css(a,b[g],!1,d);return f}return void 0!==c?n.style(a,b,c):n.css(a,b)},a,b,arguments.length>1)},show:function(){return Qa(this,!0)},hide:function(){return Qa(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){V(this)?n(this).show():n(this).hide()})}});function Ra(a,b,c,d,e){return new Ra.prototype.init(a,b,c,d,e)}n.Tween=Ra,Ra.prototype={constructor:Ra,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||n.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(n.cssNumber[c]?"":"px")},cur:function(){var a=Ra.propHooks[this.prop];return a&&a.get?a.get(this):Ra.propHooks._default.get(this)},run:function(a){var b,c=Ra.propHooks[this.prop];return this.options.duration?this.pos=b=n.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ra.propHooks._default.set(this),this}},Ra.prototype.init.prototype=Ra.prototype,Ra.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=n.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){n.fx.step[a.prop]?n.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[n.cssProps[a.prop]]&&!n.cssHooks[a.prop]?a.elem[a.prop]=a.now:n.style(a.elem,a.prop,a.now+a.unit)}}},Ra.propHooks.scrollTop=Ra.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},n.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},n.fx=Ra.prototype.init,n.fx.step={};var Sa,Ta,Ua=/^(?:toggle|show|hide)$/,Va=/queueHooks$/;function Wa(){return a.setTimeout(function(){Sa=void 0}),Sa=n.now()}function Xa(a,b){var c,d=0,e={height:a};for(b=b?1:0;4>d;d+=2-b)c=U[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function Ya(a,b,c){for(var d,e=(_a.tweeners[b]||[]).concat(_a.tweeners["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function Za(a,b,c){var d,e,f,g,h,i,j,k,l=this,m={},o=a.style,p=a.nodeType&&V(a),q=N.get(a,"fxshow");c.queue||(h=n._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,l.always(function(){l.always(function(){h.unqueued--,n.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[o.overflow,o.overflowX,o.overflowY],j=n.css(a,"display"),k="none"===j?N.get(a,"olddisplay")||za(a.nodeName):j,"inline"===k&&"none"===n.css(a,"float")&&(o.display="inline-block")),c.overflow&&(o.overflow="hidden",l.always(function(){o.overflow=c.overflow[0],o.overflowX=c.overflow[1],o.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],Ua.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(p?"hide":"show")){if("show"!==e||!q||void 0===q[d])continue;p=!0}m[d]=q&&q[d]||n.style(a,d)}else j=void 0;if(n.isEmptyObject(m))"inline"===("none"===j?za(a.nodeName):j)&&(o.display=j);else{q?"hidden"in q&&(p=q.hidden):q=N.access(a,"fxshow",{}),f&&(q.hidden=!p),p?n(a).show():l.done(function(){n(a).hide()}),l.done(function(){var b;N.remove(a,"fxshow");for(b in m)n.style(a,b,m[b])});for(d in m)g=Ya(p?q[d]:0,d,l),d in q||(q[d]=g.start,p&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function $a(a,b){var c,d,e,f,g;for(c in a)if(d=n.camelCase(c),e=b[d],f=a[c],n.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=n.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function _a(a,b,c){var d,e,f=0,g=_a.prefilters.length,h=n.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=Sa||Wa(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:n.extend({},b),opts:n.extend(!0,{specialEasing:{},easing:n.easing._default},c),originalProperties:b,originalOptions:c,startTime:Sa||Wa(),duration:c.duration,tweens:[],createTween:function(b,c){var d=n.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?(h.notifyWith(a,[j,1,0]),h.resolveWith(a,[j,b])):h.rejectWith(a,[j,b]),this}}),k=j.props;for($a(k,j.opts.specialEasing);g>f;f++)if(d=_a.prefilters[f].call(j,a,k,j.opts))return n.isFunction(d.stop)&&(n._queueHooks(j.elem,j.opts.queue).stop=n.proxy(d.stop,d)),d;return n.map(k,Ya,j),n.isFunction(j.opts.start)&&j.opts.start.call(a,j),n.fx.timer(n.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}n.Animation=n.extend(_a,{tweeners:{"*":[function(a,b){var c=this.createTween(a,b);return W(c.elem,a,T.exec(b),c),c}]},tweener:function(a,b){n.isFunction(a)?(b=a,a=["*"]):a=a.match(G);for(var c,d=0,e=a.length;e>d;d++)c=a[d],_a.tweeners[c]=_a.tweeners[c]||[],_a.tweeners[c].unshift(b)},prefilters:[Za],prefilter:function(a,b){b?_a.prefilters.unshift(a):_a.prefilters.push(a)}}),n.speed=function(a,b,c){var d=a&&"object"==typeof a?n.extend({},a):{complete:c||!c&&b||n.isFunction(a)&&a,duration:a,easing:c&&b||b&&!n.isFunction(b)&&b};return d.duration=n.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in n.fx.speeds?n.fx.speeds[d.duration]:n.fx.speeds._default,null!=d.queue&&d.queue!==!0||(d.queue="fx"),d.old=d.complete,d.complete=function(){n.isFunction(d.old)&&d.old.call(this),d.queue&&n.dequeue(this,d.queue)},d},n.fn.extend({fadeTo:function(a,b,c,d){return this.filter(V).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=n.isEmptyObject(a),f=n.speed(b,c,d),g=function(){var b=_a(this,n.extend({},a),f);(e||N.get(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=n.timers,g=N.get(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&Va.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));!b&&c||n.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=N.get(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=n.timers,g=d?d.length:0;for(c.finish=!0,n.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),n.each(["toggle","show","hide"],function(a,b){var c=n.fn[b];n.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(Xa(b,!0),a,d,e)}}),n.each({slideDown:Xa("show"),slideUp:Xa("hide"),slideToggle:Xa("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){n.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),n.timers=[],n.fx.tick=function(){var a,b=0,c=n.timers;for(Sa=n.now();b<c.length;b++)a=c[b],a()||c[b]!==a||c.splice(b--,1);c.length||n.fx.stop(),Sa=void 0},n.fx.timer=function(a){n.timers.push(a),a()?n.fx.start():n.timers.pop()},n.fx.interval=13,n.fx.start=function(){Ta||(Ta=a.setInterval(n.fx.tick,n.fx.interval))},n.fx.stop=function(){a.clearInterval(Ta),Ta=null},n.fx.speeds={slow:600,fast:200,_default:400},n.fn.delay=function(b,c){return b=n.fx?n.fx.speeds[b]||b:b,c=c||"fx",this.queue(c,function(c,d){var e=a.setTimeout(c,b);d.stop=function(){a.clearTimeout(e)}})},function(){var a=d.createElement("input"),b=d.createElement("select"),c=b.appendChild(d.createElement("option"));a.type="checkbox",l.checkOn=""!==a.value,l.optSelected=c.selected,b.disabled=!0,l.optDisabled=!c.disabled,a=d.createElement("input"),a.value="t",a.type="radio",l.radioValue="t"===a.value}();var ab,bb=n.expr.attrHandle;n.fn.extend({attr:function(a,b){return K(this,n.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){n.removeAttr(this,a)})}}),n.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?n.prop(a,b,c):(1===f&&n.isXMLDoc(a)||(b=b.toLowerCase(),e=n.attrHooks[b]||(n.expr.match.bool.test(b)?ab:void 0)),void 0!==c?null===c?void n.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=n.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!l.radioValue&&"radio"===b&&n.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(G);if(f&&1===a.nodeType)while(c=f[e++])d=n.propFix[c]||c,n.expr.match.bool.test(c)&&(a[d]=!1),a.removeAttribute(c)}}),ab={set:function(a,b,c){return b===!1?n.removeAttr(a,c):a.setAttribute(c,c),c}},n.each(n.expr.match.bool.source.match(/\w+/g),function(a,b){var c=bb[b]||n.find.attr;bb[b]=function(a,b,d){var e,f;return d||(f=bb[b],bb[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,bb[b]=f),e}});var cb=/^(?:input|select|textarea|button)$/i,db=/^(?:a|area)$/i;n.fn.extend({prop:function(a,b){return K(this,n.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[n.propFix[a]||a]})}}),n.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&n.isXMLDoc(a)||(b=n.propFix[b]||b,e=n.propHooks[b]), +void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),n.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){n.propFix[this.toLowerCase()]=this});var eb=/[\t\r\n\f]/g;function fb(a){return a.getAttribute&&a.getAttribute("class")||""}n.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).addClass(a.call(this,b,fb(this)))});if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(n.isFunction(a))return this.each(function(b){n(this).removeClass(a.call(this,b,fb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(G)||[];while(c=this[i++])if(e=fb(c),d=1===c.nodeType&&(" "+e+" ").replace(eb," ")){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=n.trim(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):n.isFunction(a)?this.each(function(c){n(this).toggleClass(a.call(this,c,fb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=n(this),f=a.match(G)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=fb(this),b&&N.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":N.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+fb(c)+" ").replace(eb," ").indexOf(b)>-1)return!0;return!1}});var gb=/\r/g,hb=/[\x20\t\r\n\f]+/g;n.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=n.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,n(this).val()):a,null==e?e="":"number"==typeof e?e+="":n.isArray(e)&&(e=n.map(e,function(a){return null==a?"":a+""})),b=n.valHooks[this.type]||n.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=n.valHooks[e.type]||n.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(gb,""):null==c?"":c)}}}),n.extend({valHooks:{option:{get:function(a){var b=n.find.attr(a,"value");return null!=b?b:n.trim(n.text(a)).replace(hb," ")}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],(c.selected||i===e)&&(l.optDisabled?!c.disabled:null===c.getAttribute("disabled"))&&(!c.parentNode.disabled||!n.nodeName(c.parentNode,"optgroup"))){if(b=n(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=n.makeArray(b),g=e.length;while(g--)d=e[g],(d.selected=n.inArray(n.valHooks.option.get(d),f)>-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),n.each(["radio","checkbox"],function(){n.valHooks[this]={set:function(a,b){return n.isArray(b)?a.checked=n.inArray(n(a).val(),b)>-1:void 0}},l.checkOn||(n.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var ib=/^(?:focusinfocus|focusoutblur)$/;n.extend(n.event,{trigger:function(b,c,e,f){var g,h,i,j,l,m,o,p=[e||d],q=k.call(b,"type")?b.type:b,r=k.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!ib.test(q+n.event.triggered)&&(q.indexOf(".")>-1&&(r=q.split("."),q=r.shift(),r.sort()),l=q.indexOf(":")<0&&"on"+q,b=b[n.expando]?b:new n.Event(q,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=r.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:n.makeArray(c,[b]),o=n.event.special[q]||{},f||!o.trigger||o.trigger.apply(e,c)!==!1)){if(!f&&!o.noBubble&&!n.isWindow(e)){for(j=o.delegateType||q,ib.test(j+q)||(h=h.parentNode);h;h=h.parentNode)p.push(h),i=h;i===(e.ownerDocument||d)&&p.push(i.defaultView||i.parentWindow||a)}g=0;while((h=p[g++])&&!b.isPropagationStopped())b.type=g>1?j:o.bindType||q,m=(N.get(h,"events")||{})[b.type]&&N.get(h,"handle"),m&&m.apply(h,c),m=l&&h[l],m&&m.apply&&L(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=q,f||b.isDefaultPrevented()||o._default&&o._default.apply(p.pop(),c)!==!1||!L(e)||l&&n.isFunction(e[q])&&!n.isWindow(e)&&(i=e[l],i&&(e[l]=null),n.event.triggered=q,e[q](),n.event.triggered=void 0,i&&(e[l]=i)),b.result}},simulate:function(a,b,c){var d=n.extend(new n.Event,c,{type:a,isSimulated:!0});n.event.trigger(d,null,b)}}),n.fn.extend({trigger:function(a,b){return this.each(function(){n.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?n.event.trigger(a,b,c,!0):void 0}}),n.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){n.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),n.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),l.focusin="onfocusin"in a,l.focusin||n.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){n.event.simulate(b,a.target,n.event.fix(a))};n.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=N.access(d,b);e||d.addEventListener(a,c,!0),N.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=N.access(d,b)-1;e?N.access(d,b,e):(d.removeEventListener(a,c,!0),N.remove(d,b))}}});var jb=a.location,kb=n.now(),lb=/\?/;n.parseJSON=function(a){return JSON.parse(a+"")},n.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||n.error("Invalid XML: "+b),c};var mb=/#.*$/,nb=/([?&])_=[^&]*/,ob=/^(.*?):[ \t]*([^\r\n]*)$/gm,pb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,qb=/^(?:GET|HEAD)$/,rb=/^\/\//,sb={},tb={},ub="*/".concat("*"),vb=d.createElement("a");vb.href=jb.href;function wb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(G)||[];if(n.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function xb(a,b,c,d){var e={},f=a===tb;function g(h){var i;return e[h]=!0,n.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function yb(a,b){var c,d,e=n.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&n.extend(!0,a,d),a}function zb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Ab(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}n.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:jb.href,type:"GET",isLocal:pb.test(jb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":ub,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":n.parseJSON,"text xml":n.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?yb(yb(a,n.ajaxSettings),b):yb(n.ajaxSettings,a)},ajaxPrefilter:wb(sb),ajaxTransport:wb(tb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m=n.ajaxSetup({},c),o=m.context||m,p=m.context&&(o.nodeType||o.jquery)?n(o):n.event,q=n.Deferred(),r=n.Callbacks("once memory"),s=m.statusCode||{},t={},u={},v=0,w="canceled",x={readyState:0,getResponseHeader:function(a){var b;if(2===v){if(!h){h={};while(b=ob.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===v?g:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return v||(a=u[c]=u[c]||a,t[a]=b),this},overrideMimeType:function(a){return v||(m.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>v)for(b in a)s[b]=[s[b],a[b]];else x.always(a[x.status]);return this},abort:function(a){var b=a||w;return e&&e.abort(b),z(0,b),this}};if(q.promise(x).complete=r.add,x.success=x.done,x.error=x.fail,m.url=((b||m.url||jb.href)+"").replace(mb,"").replace(rb,jb.protocol+"//"),m.type=c.method||c.type||m.method||m.type,m.dataTypes=n.trim(m.dataType||"*").toLowerCase().match(G)||[""],null==m.crossDomain){j=d.createElement("a");try{j.href=m.url,j.href=j.href,m.crossDomain=vb.protocol+"//"+vb.host!=j.protocol+"//"+j.host}catch(y){m.crossDomain=!0}}if(m.data&&m.processData&&"string"!=typeof m.data&&(m.data=n.param(m.data,m.traditional)),xb(sb,m,c,x),2===v)return x;k=n.event&&m.global,k&&0===n.active++&&n.event.trigger("ajaxStart"),m.type=m.type.toUpperCase(),m.hasContent=!qb.test(m.type),f=m.url,m.hasContent||(m.data&&(f=m.url+=(lb.test(f)?"&":"?")+m.data,delete m.data),m.cache===!1&&(m.url=nb.test(f)?f.replace(nb,"$1_="+kb++):f+(lb.test(f)?"&":"?")+"_="+kb++)),m.ifModified&&(n.lastModified[f]&&x.setRequestHeader("If-Modified-Since",n.lastModified[f]),n.etag[f]&&x.setRequestHeader("If-None-Match",n.etag[f])),(m.data&&m.hasContent&&m.contentType!==!1||c.contentType)&&x.setRequestHeader("Content-Type",m.contentType),x.setRequestHeader("Accept",m.dataTypes[0]&&m.accepts[m.dataTypes[0]]?m.accepts[m.dataTypes[0]]+("*"!==m.dataTypes[0]?", "+ub+"; q=0.01":""):m.accepts["*"]);for(l in m.headers)x.setRequestHeader(l,m.headers[l]);if(m.beforeSend&&(m.beforeSend.call(o,x,m)===!1||2===v))return x.abort();w="abort";for(l in{success:1,error:1,complete:1})x[l](m[l]);if(e=xb(tb,m,c,x)){if(x.readyState=1,k&&p.trigger("ajaxSend",[x,m]),2===v)return x;m.async&&m.timeout>0&&(i=a.setTimeout(function(){x.abort("timeout")},m.timeout));try{v=1,e.send(t,z)}catch(y){if(!(2>v))throw y;z(-1,y)}}else z(-1,"No Transport");function z(b,c,d,h){var j,l,t,u,w,y=c;2!==v&&(v=2,i&&a.clearTimeout(i),e=void 0,g=h||"",x.readyState=b>0?4:0,j=b>=200&&300>b||304===b,d&&(u=zb(m,x,d)),u=Ab(m,u,x,j),j?(m.ifModified&&(w=x.getResponseHeader("Last-Modified"),w&&(n.lastModified[f]=w),w=x.getResponseHeader("etag"),w&&(n.etag[f]=w)),204===b||"HEAD"===m.type?y="nocontent":304===b?y="notmodified":(y=u.state,l=u.data,t=u.error,j=!t)):(t=y,!b&&y||(y="error",0>b&&(b=0))),x.status=b,x.statusText=(c||y)+"",j?q.resolveWith(o,[l,y,x]):q.rejectWith(o,[x,y,t]),x.statusCode(s),s=void 0,k&&p.trigger(j?"ajaxSuccess":"ajaxError",[x,m,j?l:t]),r.fireWith(o,[x,y]),k&&(p.trigger("ajaxComplete",[x,m]),--n.active||n.event.trigger("ajaxStop")))}return x},getJSON:function(a,b,c){return n.get(a,b,c,"json")},getScript:function(a,b){return n.get(a,void 0,b,"script")}}),n.each(["get","post"],function(a,b){n[b]=function(a,c,d,e){return n.isFunction(c)&&(e=e||d,d=c,c=void 0),n.ajax(n.extend({url:a,type:b,dataType:e,data:c,success:d},n.isPlainObject(a)&&a))}}),n._evalUrl=function(a){return n.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},n.fn.extend({wrapAll:function(a){var b;return n.isFunction(a)?this.each(function(b){n(this).wrapAll(a.call(this,b))}):(this[0]&&(b=n(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this)},wrapInner:function(a){return n.isFunction(a)?this.each(function(b){n(this).wrapInner(a.call(this,b))}):this.each(function(){var b=n(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=n.isFunction(a);return this.each(function(c){n(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){n.nodeName(this,"body")||n(this).replaceWith(this.childNodes)}).end()}}),n.expr.filters.hidden=function(a){return!n.expr.filters.visible(a)},n.expr.filters.visible=function(a){return a.offsetWidth>0||a.offsetHeight>0||a.getClientRects().length>0};var Bb=/%20/g,Cb=/\[\]$/,Db=/\r?\n/g,Eb=/^(?:submit|button|image|reset|file)$/i,Fb=/^(?:input|select|textarea|keygen)/i;function Gb(a,b,c,d){var e;if(n.isArray(b))n.each(b,function(b,e){c||Cb.test(a)?d(a,e):Gb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==n.type(b))d(a,b);else for(e in b)Gb(a+"["+e+"]",b[e],c,d)}n.param=function(a,b){var c,d=[],e=function(a,b){b=n.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=n.ajaxSettings&&n.ajaxSettings.traditional),n.isArray(a)||a.jquery&&!n.isPlainObject(a))n.each(a,function(){e(this.name,this.value)});else for(c in a)Gb(c,a[c],b,e);return d.join("&").replace(Bb,"+")},n.fn.extend({serialize:function(){return n.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=n.prop(this,"elements");return a?n.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!n(this).is(":disabled")&&Fb.test(this.nodeName)&&!Eb.test(a)&&(this.checked||!X.test(a))}).map(function(a,b){var c=n(this).val();return null==c?null:n.isArray(c)?n.map(c,function(a){return{name:b.name,value:a.replace(Db,"\r\n")}}):{name:b.name,value:c.replace(Db,"\r\n")}}).get()}}),n.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Hb={0:200,1223:204},Ib=n.ajaxSettings.xhr();l.cors=!!Ib&&"withCredentials"in Ib,l.ajax=Ib=!!Ib,n.ajaxTransport(function(b){var c,d;return l.cors||Ib&&!b.crossDomain?{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Hb[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}:void 0}),n.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return n.globalEval(a),a}}}),n.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),n.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=n("<script>").prop({charset:a.scriptCharset,src:a.url}).on("load error",c=function(a){b.remove(),c=null,a&&f("error"===a.type?404:200,a.type)}),d.head.appendChild(b[0])},abort:function(){c&&c()}}}});var Jb=[],Kb=/(=)\?(?=&|$)|\?\?/;n.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=Jb.pop()||n.expando+"_"+kb++;return this[a]=!0,a}}),n.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(Kb.test(b.url)?"url":"string"==typeof b.data&&0===(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&Kb.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=n.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(Kb,"$1"+e):b.jsonp!==!1&&(b.url+=(lb.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||n.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){void 0===f?n(a).removeProp(e):a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,Jb.push(e)),g&&n.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),n.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||d;var e=x.exec(a),f=!c&&[];return e?[b.createElement(e[1])]:(e=ca([a],b,f),f&&f.length&&n(f).remove(),n.merge([],e.childNodes))};var Lb=n.fn.load;n.fn.load=function(a,b,c){if("string"!=typeof a&&Lb)return Lb.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>-1&&(d=n.trim(a.slice(h)),a=a.slice(0,h)),n.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(e="POST"),g.length>0&&n.ajax({url:a,type:e||"GET",dataType:"html",data:b}).done(function(a){f=arguments,g.html(d?n("<div>").append(n.parseHTML(a)).find(d):a)}).always(c&&function(a,b){g.each(function(){c.apply(this,f||[a.responseText,b,a])})}),this},n.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){n.fn[b]=function(a){return this.on(b,a)}}),n.expr.filters.animated=function(a){return n.grep(n.timers,function(b){return a===b.elem}).length};function Mb(a){return n.isWindow(a)?a:9===a.nodeType&&a.defaultView}n.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=n.css(a,"position"),l=n(a),m={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=n.css(a,"top"),i=n.css(a,"left"),j=("absolute"===k||"fixed"===k)&&(f+i).indexOf("auto")>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),n.isFunction(b)&&(b=b.call(a,c,n.extend({},h))),null!=b.top&&(m.top=b.top-h.top+g),null!=b.left&&(m.left=b.left-h.left+e),"using"in b?b.using.call(a,m):l.css(m)}},n.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){n.offset.setOffset(this,a,b)});var b,c,d=this[0],e={top:0,left:0},f=d&&d.ownerDocument;if(f)return b=f.documentElement,n.contains(b,d)?(e=d.getBoundingClientRect(),c=Mb(f),{top:e.top+c.pageYOffset-b.clientTop,left:e.left+c.pageXOffset-b.clientLeft}):e},position:function(){if(this[0]){var a,b,c=this[0],d={top:0,left:0};return"fixed"===n.css(c,"position")?b=c.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),n.nodeName(a[0],"html")||(d=a.offset()),d.top+=n.css(a[0],"borderTopWidth",!0),d.left+=n.css(a[0],"borderLeftWidth",!0)),{top:b.top-d.top-n.css(c,"marginTop",!0),left:b.left-d.left-n.css(c,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent;while(a&&"static"===n.css(a,"position"))a=a.offsetParent;return a||Ea})}}),n.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c="pageYOffset"===b;n.fn[a]=function(d){return K(this,function(a,d,e){var f=Mb(a);return void 0===e?f?f[b]:a[d]:void(f?f.scrollTo(c?f.pageXOffset:e,c?e:f.pageYOffset):a[d]=e)},a,d,arguments.length)}}),n.each(["top","left"],function(a,b){n.cssHooks[b]=Ga(l.pixelPosition,function(a,c){return c?(c=Fa(a,b),Ba.test(c)?n(a).position()[b]+"px":c):void 0})}),n.each({Height:"height",Width:"width"},function(a,b){n.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){n.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return K(this,function(b,c,d){var e;return n.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?n.css(b,c,g):n.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),n.fn.extend({bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)},size:function(){return this.length}}),n.fn.andSelf=n.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return n});var Nb=a.jQuery,Ob=a.$;return n.noConflict=function(b){return a.$===n&&(a.$=Ob),b&&a.jQuery===n&&(a.jQuery=Nb),n},b||(a.jQuery=a.$=n),n}); diff --git a/web/gui/lib/jquery.easypiechart-97b5824.min.js b/web/gui/lib/jquery.easypiechart-97b5824.min.js new file mode 100644 index 0000000..b6f6811 --- /dev/null +++ b/web/gui/lib/jquery.easypiechart-97b5824.min.js @@ -0,0 +1,10 @@ +/**! + * easy-pie-chart + * Lightweight plugin to render simple, animated and retina optimized pie charts + * + * @license + * @author Robert Fleischmann <rendro87@gmail.com> (http://robert-fleischmann.de) + * @version 2.1.7 + * SPDX-License-Identifier: MIT + **/ +!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=function(a,b){var c,d=document.createElement("canvas");a.appendChild(d),"object"==typeof G_vmlCanvasManager&&G_vmlCanvasManager.initElement(d);var e=d.getContext("2d");d.width=d.height=b.size;var f=1;window.devicePixelRatio>1&&(f=window.devicePixelRatio,d.style.width=d.style.height=[b.size,"px"].join(""),d.width=d.height=b.size*f,e.scale(f,f)),e.translate(b.size/2,b.size/2),e.rotate((-0.5+b.rotate/180)*Math.PI);var g=(b.size-b.lineWidth)/2;b.scaleColor&&b.scaleLength&&(g-=b.scaleLength+2),Date.now=Date.now||function(){return+new Date};var h=function(a,b,c){c=Math.min(Math.max(-1,c||0),1);var d=0>=c?!0:!1;e.beginPath(),e.arc(0,0,g,0,2*Math.PI*c,d),e.strokeStyle=a,e.lineWidth=b,e.stroke()},i=function(){var a,c;e.lineWidth=1,e.fillStyle=b.scaleColor,e.save();for(var d=24;d>0;--d)d%6===0?(c=b.scaleLength,a=0):(c=.6*b.scaleLength,a=b.scaleLength-c),e.fillRect(-b.size/2+a,0,c,1),e.rotate(Math.PI/12);e.restore()},j=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(a){window.setTimeout(a,1e3/60)}}(),k=function(){b.scaleColor&&i(),b.trackColor&&h(b.trackColor,b.trackWidth||b.lineWidth,1)};this.getCanvas=function(){return d},this.getCtx=function(){return e},this.clear=function(){e.clearRect(b.size/-2,b.size/-2,b.size,b.size)},this.draw=function(a){b.scaleColor||b.trackColor?e.getImageData&&e.putImageData?c?e.putImageData(c,0,0):(k(),c=e.getImageData(0,0,b.size*f,b.size*f)):(this.clear(),k()):this.clear(),e.lineCap=b.lineCap;var d;d="function"==typeof b.barColor?b.barColor(a):b.barColor,h(d,b.lineWidth,a/100)}.bind(this),this.animate=function(a,c){var d=Date.now();b.onStart(a,c);var e=function(){var f=Math.min(Date.now()-d,b.animate.duration),g=b.easing(this,f,a,c-a,b.animate.duration);this.draw(g),b.onStep(a,c,g),f>=b.animate.duration?b.onStop(a,c):j(e)}.bind(this);j(e)}.bind(this)},c=function(a,c){var d={barColor:"#ef1e25",trackColor:"#f9f9f9",scaleColor:"#dfe0e0",scaleLength:5,lineCap:"round",lineWidth:3,trackWidth:void 0,size:110,rotate:0,animate:{duration:1e3,enabled:!0},easing:function(a,b,c,d,e){return b/=e/2,1>b?d/2*b*b+c:-d/2*(--b*(b-2)-1)+c},onStart:function(a,b){},onStep:function(a,b,c){},onStop:function(a,b){}};if("undefined"!=typeof b)d.renderer=b;else{if("undefined"==typeof SVGRenderer)throw new Error("Please load either the SVG- or the CanvasRenderer");d.renderer=SVGRenderer}var e={},f=0,g=function(){this.el=a,this.options=e;for(var b in d)d.hasOwnProperty(b)&&(e[b]=c&&"undefined"!=typeof c[b]?c[b]:d[b],"function"==typeof e[b]&&(e[b]=e[b].bind(this)));"string"==typeof e.easing&&"undefined"!=typeof jQuery&&jQuery.isFunction(jQuery.easing[e.easing])?e.easing=jQuery.easing[e.easing]:e.easing=d.easing,"number"==typeof e.animate&&(e.animate={duration:e.animate,enabled:!0}),"boolean"!=typeof e.animate||e.animate||(e.animate={duration:1e3,enabled:e.animate}),this.renderer=new e.renderer(a,e),this.renderer.draw(f),a.dataset&&a.dataset.percent?this.update(parseFloat(a.dataset.percent)):a.getAttribute&&a.getAttribute("data-percent")&&this.update(parseFloat(a.getAttribute("data-percent")))}.bind(this);this.update=function(a){return a=parseFloat(a),e.animate.enabled?this.renderer.animate(f,a):this.renderer.draw(a),f=a,this}.bind(this),this.disableAnimation=function(){return e.animate.enabled=!1,this},this.enableAnimation=function(){return e.animate.enabled=!0,this},g()};a.fn.easyPieChart=function(b){return this.each(function(){var d;a.data(this,"easyPieChart")||(d=a.extend({},b,a(this).data()),a.data(this,"easyPieChart",new c(this,d)))})}}); diff --git a/web/gui/lib/jquery.peity-3.2.0.min.js b/web/gui/lib/jquery.peity-3.2.0.min.js new file mode 100644 index 0000000..a0a9169 --- /dev/null +++ b/web/gui/lib/jquery.peity-3.2.0.min.js @@ -0,0 +1,14 @@ +// Peity jQuery plugin version 3.2.0 +// (c) 2015 Ben Pickles +// +// http://benpickles.github.io/peity +// +// Released under MIT license. +// SPDX-License-Identifier: MIT +(function(k,w,h,v){var d=k.fn.peity=function(a,b){y&&this.each(function(){var e=k(this),c=e.data("_peity");c?(a&&(c.type=a),k.extend(c.opts,b)):(c=new x(e,a,k.extend({},d.defaults[a],e.data("peity"),b)),e.change(function(){c.draw()}).data("_peity",c));c.draw()});return this},x=function(a,b,e){this.$el=a;this.type=b;this.opts=e},o=x.prototype,q=o.svgElement=function(a,b){return k(w.createElementNS("http://www.w3.org/2000/svg",a)).attr(b)},y="createElementNS"in w&&q("svg",{})[0].createSVGRect;o.draw= +function(){var a=this.opts;d.graphers[this.type].call(this,a);a.after&&a.after.call(this,a)};o.fill=function(){var a=this.opts.fill;return k.isFunction(a)?a:function(b,e){return a[e%a.length]}};o.prepare=function(a,b){this.$svg||this.$el.hide().after(this.$svg=q("svg",{"class":"peity"}));return this.$svg.empty().data("peity",this).attr({height:b,width:a})};o.values=function(){return k.map(this.$el.text().split(this.opts.delimiter),function(a){return parseFloat(a)})};d.defaults={};d.graphers={};d.register= +function(a,b,e){this.defaults[a]=b;this.graphers[a]=e};d.register("pie",{fill:["#ff9900","#fff4dd","#ffc66e"],radius:8},function(a){if(!a.delimiter){var b=this.$el.text().match(/[^0-9\.]/);a.delimiter=b?b[0]:","}b=k.map(this.values(),function(a){return 0<a?a:0});if("/"==a.delimiter)var e=b[0],b=[e,h.max(0,b[1]-e)];for(var c=0,e=b.length,t=0;c<e;c++)t+=b[c];t||(e=2,t=1,b=[0,1]);var l=2*a.radius,l=this.prepare(a.width||l,a.height||l),c=l.width(),f=l.height(),j=c/2,d=f/2,f=h.min(j,d),a=a.innerRadius; +"donut"==this.type&&!a&&(a=0.5*f);for(var r=h.PI,s=this.fill(),g=this.scale=function(a,b){var c=a/t*r*2-r/2;return[b*h.cos(c)+j,b*h.sin(c)+d]},m=0,c=0;c<e;c++){var u=b[c],i=u/t;if(0!=i){if(1==i)if(a)var i=j-0.01,p=d-f,n=d-a,i=q("path",{d:["M",j,p,"A",f,f,0,1,1,i,p,"L",i,n,"A",a,a,0,1,0,j,n].join(" ")});else i=q("circle",{cx:j,cy:d,r:f});else p=m+u,n=["M"].concat(g(m,f),"A",f,f,0,0.5<i?1:0,1,g(p,f),"L"),a?n=n.concat(g(p,a),"A",a,a,0,0.5<i?1:0,0,g(m,a)):n.push(j,d),m+=u,i=q("path",{d:n.join(" ")}); +i.attr("fill",s.call(this,u,c,b));l.append(i)}}});d.register("donut",k.extend(!0,{},d.defaults.pie),function(a){d.graphers.pie.call(this,a)});d.register("line",{delimiter:",",fill:"#c6d9fd",height:16,min:0,stroke:"#4d89f9",strokeWidth:1,width:32},function(a){var b=this.values();1==b.length&&b.push(b[0]);for(var e=h.max.apply(h,a.max==v?b:b.concat(a.max)),c=h.min.apply(h,a.min==v?b:b.concat(a.min)),d=this.prepare(a.width,a.height),l=a.strokeWidth,f=d.width(),j=d.height()-l,k=e-c,e=this.x=function(a){return a* +(f/(b.length-1))},r=this.y=function(a){var b=j;k&&(b-=(a-c)/k*j);return b+l/2},s=r(h.max(c,0)),g=[0,s],m=0;m<b.length;m++)g.push(e(m),r(b[m]));g.push(f,s);a.fill&&d.append(q("polygon",{fill:a.fill,points:g.join(" ")}));l&&d.append(q("polyline",{fill:"none",points:g.slice(2,g.length-2).join(" "),stroke:a.stroke,"stroke-width":l,"stroke-linecap":"square"}))});d.register("bar",{delimiter:",",fill:["#4D89F9"],height:16,min:0,padding:0.1,width:32},function(a){for(var b=this.values(),e=h.max.apply(h,a.max== +v?b:b.concat(a.max)),c=h.min.apply(h,a.min==v?b:b.concat(a.min)),d=this.prepare(a.width,a.height),l=d.width(),f=d.height(),j=e-c,a=a.padding,k=this.fill(),r=this.x=function(a){return a*l/b.length},s=this.y=function(a){return f-(j?(a-c)/j*f:1)},g=0;g<b.length;g++){var m=r(g+a),u=r(g+1-a)-m,i=b[g],p=s(i),n=p,o;j?0>i?n=s(h.min(e,0)):p=s(h.max(c,0)):o=1;o=p-n;0==o&&(o=1,0<e&&j&&n--);d.append(q("rect",{fill:k.call(this,i,g,b),x:m,y:n,width:u,height:o}))}})})(jQuery,document,Math); diff --git a/web/gui/lib/jquery.sparkline-2.1.2.min.js b/web/gui/lib/jquery.sparkline-2.1.2.min.js new file mode 100644 index 0000000..f1973df --- /dev/null +++ b/web/gui/lib/jquery.sparkline-2.1.2.min.js @@ -0,0 +1,6 @@ +/* jquery.sparkline 2.1.2 - http://omnipotent.net/jquery.sparkline/ +** SPDX-License-Identifier: BSD-3-Clause +** Licensed under the New BSD License - see above site for details */ + +(function(a,b,c){(function(a){typeof define=="function"&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.sparkline&&a(jQuery)})(function(d){"use strict";var e={},f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L=0;f=function(){return{common:{type:"line",lineColor:"#00f",fillColor:"#cdf",defaultPixelsPerValue:3,width:"auto",height:"auto",composite:!1,tagValuesAttribute:"values",tagOptionsPrefix:"spark",enableTagOptions:!1,enableHighlight:!0,highlightLighten:1.4,tooltipSkipNull:!0,tooltipPrefix:"",tooltipSuffix:"",disableHiddenCheck:!1,numberFormatter:!1,numberDigitGroupCount:3,numberDigitGroupSep:",",numberDecimalMark:".",disableTooltips:!1,disableInteraction:!1},line:{spotColor:"#f80",highlightSpotColor:"#5f5",highlightLineColor:"#f22",spotRadius:1.5,minSpotColor:"#f80",maxSpotColor:"#f80",lineWidth:1,normalRangeMin:c,normalRangeMax:c,normalRangeColor:"#ccc",drawNormalOnTop:!1,chartRangeMin:c,chartRangeMax:c,chartRangeMinX:c,chartRangeMaxX:c,tooltipFormat:new h('<span style="color: {{color}}">●</span> {{prefix}}{{y}}{{suffix}}')},bar:{barColor:"#3366cc",negBarColor:"#f44",stackedBarColor:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],zeroColor:c,nullColor:c,zeroAxis:!0,barWidth:4,barSpacing:1,chartRangeMax:c,chartRangeMin:c,chartRangeClip:!1,colorMap:c,tooltipFormat:new h('<span style="color: {{color}}">●</span> {{prefix}}{{value}}{{suffix}}')},tristate:{barWidth:4,barSpacing:1,posBarColor:"#6f6",negBarColor:"#f44",zeroBarColor:"#999",colorMap:{},tooltipFormat:new h('<span style="color: {{color}}">●</span> {{value:map}}'),tooltipValueLookups:{map:{"-1":"Loss",0:"Draw",1:"Win"}}},discrete:{lineHeight:"auto",thresholdColor:c,thresholdValue:0,chartRangeMax:c,chartRangeMin:c,chartRangeClip:!1,tooltipFormat:new h("{{prefix}}{{value}}{{suffix}}")},bullet:{targetColor:"#f33",targetWidth:3,performanceColor:"#33f",rangeColors:["#d3dafe","#a8b6ff","#7f94ff"],base:c,tooltipFormat:new h("{{fieldkey:fields}} - {{value}}"),tooltipValueLookups:{fields:{r:"Range",p:"Performance",t:"Target"}}},pie:{offset:0,sliceColors:["#3366cc","#dc3912","#ff9900","#109618","#66aa00","#dd4477","#0099c6","#990099"],borderWidth:0,borderColor:"#000",tooltipFormat:new h('<span style="color: {{color}}">●</span> {{value}} ({{percent.1}}%)')},box:{raw:!1,boxLineColor:"#000",boxFillColor:"#cdf",whiskerColor:"#000",outlierLineColor:"#333",outlierFillColor:"#fff",medianColor:"#f00",showOutliers:!0,outlierIQR:1.5,spotRadius:1.5,target:c,targetColor:"#4a2",chartRangeMax:c,chartRangeMin:c,tooltipFormat:new h("{{field:fields}}: {{value}}"),tooltipFormatFieldlistKey:"field",tooltipValueLookups:{fields:{lq:"Lower Quartile",med:"Median",uq:"Upper Quartile",lo:"Left Outlier",ro:"Right Outlier",lw:"Left Whisker",rw:"Right Whisker"}}}}},E='.jqstooltip { position: absolute;left: 0px;top: 0px;visibility: hidden;background: rgb(0, 0, 0) transparent;background-color: rgba(0,0,0,0.6);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";color: white;font: 10px arial, san serif;text-align: left;white-space: nowrap;padding: 5px;border: 1px solid white;z-index: 10000;}.jqsfield { color: white;font: 10px arial, san serif;text-align: left;}',g=function(){var a,b;return a=function(){this.init.apply(this,arguments)},arguments.length>1?(arguments[0]?(a.prototype=d.extend(new arguments[0],arguments[arguments.length-1]),a._super=arguments[0].prototype):a.prototype=arguments[arguments.length-1],arguments.length>2&&(b=Array.prototype.slice.call(arguments,1,-1),b.unshift(a.prototype),d.extend.apply(d,b))):a.prototype=arguments[0],a.prototype.cls=a,a},d.SPFormatClass=h=g({fre:/\{\{([\w.]+?)(:(.+?))?\}\}/g,precre:/(\w+)\.(\d+)/,init:function(a,b){this.format=a,this.fclass=b},render:function(a,b,d){var e=this,f=a,g,h,i,j,k;return this.format.replace(this.fre,function(){var a;return h=arguments[1],i=arguments[3],g=e.precre.exec(h),g?(k=g[2],h=g[1]):k=!1,j=f[h],j===c?"":i&&b&&b[i]?(a=b[i],a.get?b[i].get(j)||j:b[i][j]||j):(n(j)&&(d.get("numberFormatter")?j=d.get("numberFormatter")(j):j=s(j,k,d.get("numberDigitGroupCount"),d.get("numberDigitGroupSep"),d.get("numberDecimalMark"))),j)})}}),d.spformat=function(a,b){return new h(a,b)},i=function(a,b,c){return a<b?b:a>c?c:a},j=function(a,c){var d;return c===2?(d=b.floor(a.length/2),a.length%2?a[d]:(a[d-1]+a[d])/2):a.length%2?(d=(a.length*c+c)/4,d%1?(a[b.floor(d)]+a[b.floor(d)-1])/2:a[d-1]):(d=(a.length*c+2)/4,d%1?(a[b.floor(d)]+a[b.floor(d)-1])/2:a[d-1])},k=function(a){var b;switch(a){case"undefined":a=c;break;case"null":a=null;break;case"true":a=!0;break;case"false":a=!1;break;default:b=parseFloat(a),a==b&&(a=b)}return a},l=function(a){var b,c=[];for(b=a.length;b--;)c[b]=k(a[b]);return c},m=function(a,b){var c,d,e=[];for(c=0,d=a.length;c<d;c++)a[c]!==b&&e.push(a[c]);return e},n=function(a){return!isNaN(parseFloat(a))&&isFinite(a)},s=function(a,b,c,e,f){var g,h;a=(b===!1?parseFloat(a).toString():a.toFixed(b)).split(""),g=(g=d.inArray(".",a))<0?a.length:g,g<a.length&&(a[g]=f);for(h=g-c;h>0;h-=c)a.splice(h,0,e);return a.join("")},o=function(a,b,c){var d;for(d=b.length;d--;){if(c&&b[d]===null)continue;if(b[d]!==a)return!1}return!0},p=function(a){var b=0,c;for(c=a.length;c--;)b+=typeof a[c]=="number"?a[c]:0;return b},r=function(a){return d.isArray(a)?a:[a]},q=function(b){var c;a.createStyleSheet?a.createStyleSheet().cssText=b:(c=a.createElement("style"),c.type="text/css",a.getElementsByTagName("head")[0].appendChild(c),c[typeof a.body.style.WebkitAppearance=="string"?"innerText":"innerHTML"]=b)},d.fn.simpledraw=function(b,e,f,g){var h,i;if(f&&(h=this.data("_jqs_vcanvas")))return h;if(d.fn.sparkline.canvas===!1)return!1;if(d.fn.sparkline.canvas===c){var j=a.createElement("canvas");if(!j.getContext||!j.getContext("2d")){if(!a.namespaces||!!a.namespaces.v)return d.fn.sparkline.canvas=!1,!1;a.namespaces.add("v","urn:schemas-microsoft-com:vml","#default#VML"),d.fn.sparkline.canvas=function(a,b,c,d){return new J(a,b,c)}}else d.fn.sparkline.canvas=function(a,b,c,d){return new I(a,b,c,d)}}return b===c&&(b=d(this).innerWidth()),e===c&&(e=d(this).innerHeight()),h=d.fn.sparkline.canvas(b,e,this,g),i=d(this).data("_jqs_mhandler"),i&&i.registerCanvas(h),h},d.fn.cleardraw=function(){var a=this.data("_jqs_vcanvas");a&&a.reset()},d.RangeMapClass=t=g({init:function(a){var b,c,d=[];for(b in a)a.hasOwnProperty(b)&&typeof b=="string"&&b.indexOf(":")>-1&&(c=b.split(":"),c[0]=c[0].length===0?-Infinity:parseFloat(c[0]),c[1]=c[1].length===0?Infinity:parseFloat(c[1]),c[2]=a[b],d.push(c));this.map=a,this.rangelist=d||!1},get:function(a){var b=this.rangelist,d,e,f;if((f=this.map[a])!==c)return f;if(b)for(d=b.length;d--;){e=b[d];if(e[0]<=a&&e[1]>=a)return e[2]}return c}}),d.range_map=function(a){return new t(a)},u=g({init:function(a,b){var c=d(a);this.$el=c,this.options=b,this.currentPageX=0,this.currentPageY=0,this.el=a,this.splist=[],this.tooltip=null,this.over=!1,this.displayTooltips=!b.get("disableTooltips"),this.highlightEnabled=!b.get("disableHighlight")},registerSparkline:function(a){this.splist.push(a),this.over&&this.updateDisplay()},registerCanvas:function(a){var b=d(a.canvas);this.canvas=a,this.$canvas=b,b.mouseenter(d.proxy(this.mouseenter,this)),b.mouseleave(d.proxy(this.mouseleave,this)),b.click(d.proxy(this.mouseclick,this))},reset:function(a){this.splist=[],this.tooltip&&a&&(this.tooltip.remove(),this.tooltip=c)},mouseclick:function(a){var b=d.Event("sparklineClick");b.originalEvent=a,b.sparklines=this.splist,this.$el.trigger(b)},mouseenter:function(b){d(a.body).unbind("mousemove.jqs"),d(a.body).bind("mousemove.jqs",d.proxy(this.mousemove,this)),this.over=!0,this.currentPageX=b.pageX,this.currentPageY=b.pageY,this.currentEl=b.target,!this.tooltip&&this.displayTooltips&&(this.tooltip=new v(this.options),this.tooltip.updatePosition(b.pageX,b.pageY)),this.updateDisplay()},mouseleave:function(){d(a.body).unbind("mousemove.jqs");var b=this.splist,c=b.length,e=!1,f,g;this.over=!1,this.currentEl=null,this.tooltip&&(this.tooltip.remove(),this.tooltip=null);for(g=0;g<c;g++)f=b[g],f.clearRegionHighlight()&&(e=!0);e&&this.canvas.render()},mousemove:function(a){this.currentPageX=a.pageX,this.currentPageY=a.pageY,this.currentEl=a.target,this.tooltip&&this.tooltip.updatePosition(a.pageX,a.pageY),this.updateDisplay()},updateDisplay:function(){var a=this.splist,b=a.length,c=!1,e=this.$canvas.offset(),f=this.currentPageX-e.left,g=this.currentPageY-e.top,h,i,j,k,l;if(!this.over)return;for(j=0;j<b;j++)i=a[j],k=i.setRegionHighlight(this.currentEl,f,g),k&&(c=!0);if(c){l=d.Event("sparklineRegionChange"),l.sparklines=this.splist,this.$el.trigger(l);if(this.tooltip){h="";for(j=0;j<b;j++)i=a[j],h+=i.getCurrentRegionTooltip();this.tooltip.setContent(h)}this.disableHighlight||this.canvas.render()}k===null&&this.mouseleave()}}),v=g({sizeStyle:"position: static !important;display: block !important;visibility: hidden !important;float: left !important;",init:function(b){var c=b.get("tooltipClassname","jqstooltip"),e=this.sizeStyle,f;this.container=b.get("tooltipContainer")||a.body,this.tooltipOffsetX=b.get("tooltipOffsetX",10),this.tooltipOffsetY=b.get("tooltipOffsetY",12),d("#jqssizetip").remove(),d("#jqstooltip").remove(),this.sizetip=d("<div/>",{id:"jqssizetip",style:e,"class":c}),this.tooltip=d("<div/>",{id:"jqstooltip","class":c}).appendTo(this.container),f=this.tooltip.offset(),this.offsetLeft=f.left,this.offsetTop=f.top,this.hidden=!0,d(window).unbind("resize.jqs scroll.jqs"),d(window).bind("resize.jqs scroll.jqs",d.proxy(this.updateWindowDims,this)),this.updateWindowDims()},updateWindowDims:function(){this.scrollTop=d(window).scrollTop(),this.scrollLeft=d(window).scrollLeft(),this.scrollRight=this.scrollLeft+d(window).width(),this.updatePosition()},getSize:function(a){this.sizetip.html(a).appendTo(this.container),this.width=this.sizetip.width()+1,this.height=this.sizetip.height(),this.sizetip.remove()},setContent:function(a){if(!a){this.tooltip.css("visibility","hidden"),this.hidden=!0;return}this.getSize(a),this.tooltip.html(a).css({width:this.width,height:this.height,visibility:"visible"}),this.hidden&&(this.hidden=!1,this.updatePosition())},updatePosition:function(a,b){if(a===c){if(this.mousex===c)return;a=this.mousex-this.offsetLeft,b=this.mousey-this.offsetTop}else this.mousex=a-=this.offsetLeft,this.mousey=b-=this.offsetTop;if(!this.height||!this.width||this.hidden)return;b-=this.height+this.tooltipOffsetY,a+=this.tooltipOffsetX,b<this.scrollTop&&(b=this.scrollTop),a<this.scrollLeft?a=this.scrollLeft:a+this.width>this.scrollRight&&(a=this.scrollRight-this.width),this.tooltip.css({left:a,top:b})},remove:function(){this.tooltip.remove(),this.sizetip.remove(),this.sizetip=this.tooltip=c,d(window).unbind("resize.jqs scroll.jqs")}}),F=function(){q(E)},d(F),K=[],d.fn.sparkline=function(b,e){return this.each(function(){var f=new d.fn.sparkline.options(this,e),g=d(this),h,i;h=function(){var e,h,i,j,k,l,m;if(b==="html"||b===c){m=this.getAttribute(f.get("tagValuesAttribute"));if(m===c||m===null)m=g.html();e=m.replace(/(^\s*<!--)|(-->\s*$)|\s+/g,"").split(",")}else e=b;h=f.get("width")==="auto"?e.length*f.get("defaultPixelsPerValue"):f.get("width");if(f.get("height")==="auto"){if(!f.get("composite")||!d.data(this,"_jqs_vcanvas"))j=a.createElement("span"),j.innerHTML="a",g.html(j),i=d(j).innerHeight()||d(j).height(),d(j).remove(),j=null}else i=f.get("height");f.get("disableInteraction")?k=!1:(k=d.data(this,"_jqs_mhandler"),k?f.get("composite")||k.reset():(k=new u(this,f),d.data(this,"_jqs_mhandler",k)));if(f.get("composite")&&!d.data(this,"_jqs_vcanvas")){d.data(this,"_jqs_errnotify")||(alert("Attempted to attach a composite sparkline to an element with no existing sparkline"),d.data(this,"_jqs_errnotify",!0));return}l=new(d.fn.sparkline[f.get("type")])(this,e,f,h,i),l.render(),k&&k.registerSparkline(l)};if(d(this).html()&&!f.get("disableHiddenCheck")&&d(this).is(":hidden")||!d(this).parents("body").length){if(!f.get("composite")&&d.data(this,"_jqs_pending"))for(i=K.length;i;i--)K[i-1][0]==this&&K.splice(i-1,1);K.push([this,h]),d.data(this,"_jqs_pending",!0)}else h.call(this)})},d.fn.sparkline.defaults=f(),d.sparkline_display_visible=function(){var a,b,c,e=[];for(b=0,c=K.length;b<c;b++)a=K[b][0],d(a).is(":visible")&&!d(a).parents().is(":hidden")?(K[b][1].call(a),d.data(K[b][0],"_jqs_pending",!1),e.push(b)):!d(a).closest("html").length&&!d.data(a,"_jqs_pending")&&(d.data(K[b][0],"_jqs_pending",!1),e.push(b));for(b=e.length;b;b--)K.splice(e[b-1],1)},d.fn.sparkline.options=g({init:function(a,b){var c,f,g,h;this.userOptions=b=b||{},this.tag=a,this.tagValCache={},f=d.fn.sparkline.defaults,g=f.common,this.tagOptionsPrefix=b.enableTagOptions&&(b.tagOptionsPrefix||g.tagOptionsPrefix),h=this.getTagSetting("type"),h===e?c=f[b.type||g.type]:c=f[h],this.mergedOptions=d.extend({},g,c,b)},getTagSetting:function(a){var b=this.tagOptionsPrefix,d,f,g,h;if(b===!1||b===c)return e;if(this.tagValCache.hasOwnProperty(a))d=this.tagValCache.key;else{d=this.tag.getAttribute(b+a);if(d===c||d===null)d=e;else if(d.substr(0,1)==="["){d=d.substr(1,d.length-2).split(",");for(f=d.length;f--;)d[f]=k(d[f].replace(/(^\s*)|(\s*$)/g,""))}else if(d.substr(0,1)==="{"){g=d.substr(1,d.length-2).split(","),d={};for(f=g.length;f--;)h=g[f].split(":",2),d[h[0].replace(/(^\s*)|(\s*$)/g,"")]=k(h[1].replace(/(^\s*)|(\s*$)/g,""))}else d=k(d);this.tagValCache.key=d}return d},get:function(a,b){var d=this.getTagSetting(a),f;return d!==e?d:(f=this.mergedOptions[a])===c?b:f}}),d.fn.sparkline._base=g({disabled:!1,init:function(a,b,e,f,g){this.el=a,this.$el=d(a),this.values=b,this.options=e,this.width=f,this.height=g,this.currentRegion=c},initTarget:function(){var a=!this.options.get("disableInteraction");(this.target=this.$el.simpledraw(this.width,this.height,this.options.get("composite"),a))?(this.canvasWidth=this.target.pixelWidth,this.canvasHeight=this.target.pixelHeight):this.disabled=!0},render:function(){return this.disabled?(this.el.innerHTML="",!1):!0},getRegion:function(a,b){},setRegionHighlight:function(a,b,d){var e=this.currentRegion,f=!this.options.get("disableHighlight"),g;return b>this.canvasWidth||d>this.canvasHeight||b<0||d<0?null:(g=this.getRegion(a,b,d),e!==g?(e!==c&&f&&this.removeHighlight(),this.currentRegion=g,g!==c&&f&&this.renderHighlight(),!0):!1)},clearRegionHighlight:function(){return this.currentRegion!==c?(this.removeHighlight(),this.currentRegion=c,!0):!1},renderHighlight:function(){this.changeHighlight(!0)},removeHighlight:function(){this.changeHighlight(!1)},changeHighlight:function(a){},getCurrentRegionTooltip:function(){var a=this.options,b="",e=[],f,g,i,j,k,l,m,n,o,p,q,r,s,t;if(this.currentRegion===c)return"";f=this.getCurrentRegionFields(),q=a.get("tooltipFormatter");if(q)return q(this,a,f);a.get("tooltipChartTitle")&&(b+='<div class="jqs jqstitle">'+a.get("tooltipChartTitle")+"</div>\n"),g=this.options.get("tooltipFormat");if(!g)return"";d.isArray(g)||(g=[g]),d.isArray(f)||(f=[f]),m=this.options.get("tooltipFormatFieldlist"),n=this.options.get("tooltipFormatFieldlistKey");if(m&&n){o=[];for(l=f.length;l--;)p=f[l][n],(t=d.inArray(p,m))!=-1&&(o[t]=f[l]);f=o}i=g.length,s=f.length;for(l=0;l<i;l++){r=g[l],typeof r=="string"&&(r=new h(r)),j=r.fclass||"jqsfield";for(t=0;t<s;t++)if(!f[t].isNull||!a.get("tooltipSkipNull"))d.extend(f[t],{prefix:a.get("tooltipPrefix"),suffix:a.get("tooltipSuffix")}),k=r.render(f[t],a.get("tooltipValueLookups"),a),e.push('<div class="'+j+'">'+k+"</div>")}return e.length?b+e.join("\n"):""},getCurrentRegionFields:function(){},calcHighlightColor:function(a,c){var d=c.get("highlightColor"),e=c.get("highlightLighten"),f,g,h,j;if(d)return d;if(e){f=/^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(a)||/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(a);if(f){h=[],g=a.length===4?16:1;for(j=0;j<3;j++)h[j]=i(b.round(parseInt(f[j+1],16)*g*e),0,255);return"rgb("+h.join(",")+")"}}return a}}),w={changeHighlight:function(a){var b=this.currentRegion,c=this.target,e=this.regionShapes[b],f;e&&(f=this.renderRegion(b,a),d.isArray(f)||d.isArray(e)?(c.replaceWithShapes(e,f),this.regionShapes[b]=d.map(f,function(a){return a.id})):(c.replaceWithShape(e,f),this.regionShapes[b]=f.id))},render:function(){var a=this.values,b=this.target,c=this.regionShapes,e,f,g,h;if(!this.cls._super.render.call(this))return;for(g=a.length;g--;){e=this.renderRegion(g);if(e)if(d.isArray(e)){f=[];for(h=e.length;h--;)e[h].append(),f.push(e[h].id);c[g]=f}else e.append(),c[g]=e.id;else c[g]=null}b.render()}},d.fn.sparkline.line=x=g(d.fn.sparkline._base,{type:"line",init:function(a,b,c,d,e){x._super.init.call(this,a,b,c,d,e),this.vertices=[],this.regionMap=[],this.xvalues=[],this.yvalues=[],this.yminmax=[],this.hightlightSpotId=null,this.lastShapeId=null,this.initTarget()},getRegion:function(a,b,d){var e,f=this.regionMap;for(e=f.length;e--;)if(f[e]!==null&&b>=f[e][0]&&b<=f[e][1])return f[e][2];return c},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.yvalues[a]===null,x:this.xvalues[a],y:this.yvalues[a],color:this.options.get("lineColor"),fillColor:this.options.get("fillColor"),offset:a}},renderHighlight:function(){var a=this.currentRegion,b=this.target,d=this.vertices[a],e=this.options,f=e.get("spotRadius"),g=e.get("highlightSpotColor"),h=e.get("highlightLineColor"),i,j;if(!d)return;f&&g&&(i=b.drawCircle(d[0],d[1],f,c,g),this.highlightSpotId=i.id,b.insertAfterShape(this.lastShapeId,i)),h&&(j=b.drawLine(d[0],this.canvasTop,d[0],this.canvasTop+this.canvasHeight,h),this.highlightLineId=j.id,b.insertAfterShape(this.lastShapeId,j))},removeHighlight:function(){var a=this.target;this.highlightSpotId&&(a.removeShapeId(this.highlightSpotId),this.highlightSpotId=null),this.highlightLineId&&(a.removeShapeId(this.highlightLineId),this.highlightLineId=null)},scanValues:function(){var a=this.values,c=a.length,d=this.xvalues,e=this.yvalues,f=this.yminmax,g,h,i,j,k;for(g=0;g<c;g++)h=a[g],i=typeof a[g]=="string",j=typeof a[g]=="object"&&a[g]instanceof Array,k=i&&a[g].split(":"),i&&k.length===2?(d.push(Number(k[0])),e.push(Number(k[1])),f.push(Number(k[1]))):j?(d.push(h[0]),e.push(h[1]),f.push(h[1])):(d.push(g),a[g]===null||a[g]==="null"?e.push(null):(e.push(Number(h)),f.push(Number(h))));this.options.get("xvalues")&&(d=this.options.get("xvalues")),this.maxy=this.maxyorg=b.max.apply(b,f),this.miny=this.minyorg=b.min.apply(b,f),this.maxx=b.max.apply(b,d),this.minx=b.min.apply(b,d),this.xvalues=d,this.yvalues=e,this.yminmax=f},processRangeOptions:function(){var a=this.options,b=a.get("normalRangeMin"),d=a.get("normalRangeMax");b!==c&&(b<this.miny&&(this.miny=b),d>this.maxy&&(this.maxy=d)),a.get("chartRangeMin")!==c&&(a.get("chartRangeClip")||a.get("chartRangeMin")<this.miny)&&(this.miny=a.get("chartRangeMin")),a.get("chartRangeMax")!==c&&(a.get("chartRangeClip")||a.get("chartRangeMax")>this.maxy)&&(this.maxy=a.get("chartRangeMax")),a.get("chartRangeMinX")!==c&&(a.get("chartRangeClipX")||a.get("chartRangeMinX")<this.minx)&&(this.minx=a.get("chartRangeMinX")),a.get("chartRangeMaxX")!==c&&(a.get("chartRangeClipX")||a.get("chartRangeMaxX")>this.maxx)&&(this.maxx=a.get("chartRangeMaxX"))},drawNormalRange:function(a,d,e,f,g){var h=this.options.get("normalRangeMin"),i=this.options.get("normalRangeMax"),j=d+b.round(e-e*((i-this.miny)/g)),k=b.round(e*(i-h)/g);this.target.drawRect(a,j,f,k,c,this.options.get("normalRangeColor")).append()},render:function(){var a=this.options,e=this.target,f=this.canvasWidth,g=this.canvasHeight,h=this.vertices,i=a.get("spotRadius"),j=this.regionMap,k,l,m,n,o,p,q,r,s,u,v,w,y,z,A,B,C,D,E,F,G,H,I,J,K;if(!x._super.render.call(this))return;this.scanValues(),this.processRangeOptions(),I=this.xvalues,J=this.yvalues;if(!this.yminmax.length||this.yvalues.length<2)return;n=o=0,k=this.maxx-this.minx===0?1:this.maxx-this.minx,l=this.maxy-this.miny===0?1:this.maxy-this.miny,m=this.yvalues.length-1,i&&(f<i*4||g<i*4)&&(i=0);if(i){G=a.get("highlightSpotColor")&&!a.get("disableInteraction");if(G||a.get("minSpotColor")||a.get("spotColor")&&J[m]===this.miny)g-=b.ceil(i);if(G||a.get("maxSpotColor")||a.get("spotColor")&&J[m]===this.maxy)g-=b.ceil(i),n+=b.ceil(i);if(G||(a.get("minSpotColor")||a.get("maxSpotColor"))&&(J[0]===this.miny||J[0]===this.maxy))o+=b.ceil(i),f-=b.ceil(i);if(G||a.get("spotColor")||a.get("minSpotColor")||a.get("maxSpotColor")&&(J[m]===this.miny||J[m]===this.maxy))f-=b.ceil(i)}g--,a.get("normalRangeMin")!==c&&!a.get("drawNormalOnTop")&&this.drawNormalRange(o,n,g,f,l),q=[],r=[q],z=A=null,B=J.length;for(K=0;K<B;K++)s=I[K],v=I[K+1],u=J[K],w=o+b.round((s-this.minx)*(f/k)),y=K<B-1?o+b.round((v-this.minx)*(f/k)):f,A=w+(y-w)/2,j[K]=[z||0,A,K],z=A,u===null?K&&(J[K-1]!==null&&(q=[],r.push(q)),h.push(null)):(u<this.miny&&(u=this.miny),u>this.maxy&&(u=this.maxy),q.length||q.push([w,n+g]),p=[w,n+b.round(g-g*((u-this.miny)/l))],q.push(p),h.push(p));C=[],D=[],E=r.length;for(K=0;K<E;K++)q=r[K],q.length&&(a.get("fillColor")&&(q.push([q[q.length-1][0],n+g]),D.push(q.slice(0)),q.pop()),q.length>2&&(q[0]=[q[0][0],q[1][1]]),C.push(q));E=D.length;for(K=0;K<E;K++)e.drawShape(D[K],a.get("fillColor"),a.get("fillColor")).append();a.get("normalRangeMin")!==c&&a.get("drawNormalOnTop")&&this.drawNormalRange(o,n,g,f,l),E=C.length;for(K=0;K<E;K++)e.drawShape(C[K],a.get("lineColor"),c,a.get("lineWidth")).append();if(i&&a.get("valueSpots")){F=a.get("valueSpots"),F.get===c&&(F=new t(F));for(K=0;K<B;K++)H=F.get(J[K]),H&&e.drawCircle(o+b.round((I[K]-this.minx)*(f/k)),n+b.round(g-g*((J[K]-this.miny)/l)),i,c,H).append()}i&&a.get("spotColor")&&J[m]!==null&&e.drawCircle(o+b.round((I[I.length-1]-this.minx)*(f/k)),n+b.round(g-g*((J[m]-this.miny)/l)),i,c,a.get("spotColor")).append(),this.maxy!==this.minyorg&&(i&&a.get("minSpotColor")&&(s=I[d.inArray(this.minyorg,J)],e.drawCircle(o+b.round((s-this.minx)*(f/k)),n+b.round(g-g*((this.minyorg-this.miny)/l)),i,c,a.get("minSpotColor")).append()),i&&a.get("maxSpotColor")&&(s=I[d.inArray(this.maxyorg,J)],e.drawCircle(o+b.round((s-this.minx)*(f/k)),n+b.round(g-g*((this.maxyorg-this.miny)/l)),i,c,a.get("maxSpotColor")).append())),this.lastShapeId=e.getLastShapeId(),this.canvasTop=n,e.render()}}),d.fn.sparkline.bar=y=g(d.fn.sparkline._base,w,{type:"bar",init:function(a,e,f,g,h){var j=parseInt(f.get("barWidth"),10),n=parseInt(f.get("barSpacing"),10),o=f.get("chartRangeMin"),p=f.get("chartRangeMax"),q=f.get("chartRangeClip"),r=Infinity,s=-Infinity,u,v,w,x,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R;y._super.init.call(this,a,e,f,g,h);for(A=0,B=e.length;A<B;A++){O=e[A],u=typeof O=="string"&&O.indexOf(":")>-1;if(u||d.isArray(O))J=!0,u&&(O=e[A]=l(O.split(":"))),O=m(O,null),v=b.min.apply(b,O),w=b.max.apply(b,O),v<r&&(r=v),w>s&&(s=w)}this.stacked=J,this.regionShapes={},this.barWidth=j,this.barSpacing=n,this.totalBarWidth=j+n,this.width=g=e.length*j+(e.length-1)*n,this.initTarget(),q&&(H=o===c?-Infinity:o,I=p===c?Infinity:p),z=[],x=J?[]:z;var S=[],T=[];for(A=0,B=e.length;A<B;A++)if(J){K=e[A],e[A]=N=[],S[A]=0,x[A]=T[A]=0;for(L=0,M=K.length;L<M;L++)O=N[L]=q?i(K[L],H,I):K[L],O!==null&&(O>0&&(S[A]+=O),r<0&&s>0?O<0?T[A]+=b.abs(O):x[A]+=O:x[A]+=b.abs(O-(O<0?s:r)),z.push(O))}else O=q?i(e[A],H,I):e[A],O=e[A]=k(O),O!==null&&z.push(O);this.max=G=b.max.apply(b,z),this.min=F=b.min.apply(b,z),this.stackMax=s=J?b.max.apply(b,S):G,this.stackMin=r=J?b.min.apply(b,z):F,f.get("chartRangeMin")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMin")<F)&&(F=f.get("chartRangeMin")),f.get("chartRangeMax")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMax")>G)&&(G=f.get("chartRangeMax")),this.zeroAxis=D=f.get("zeroAxis",!0),F<=0&&G>=0&&D?E=0:D==0?E=F:F>0?E=F:E=G,this.xaxisOffset=E,C=J?b.max.apply(b,x)+b.max.apply(b,T):G-F,this.canvasHeightEf=D&&F<0?this.canvasHeight-2:this.canvasHeight-1,F<E?(Q=J&&G>=0?s:G,P=(Q-E)/C*this.canvasHeight,P!==b.ceil(P)&&(this.canvasHeightEf-=2,P=b.ceil(P))):P=this.canvasHeight,this.yoffset=P,d.isArray(f.get("colorMap"))?(this.colorMapByIndex=f.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=f.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===c&&(this.colorMapByValue=new t(this.colorMapByValue))),this.range=C},getRegion:function(a,d,e){var f=b.floor(d/this.totalBarWidth);return f<0||f>=this.values.length?c:f},getCurrentRegionFields:function(){var a=this.currentRegion,b=r(this.values[a]),c=[],d,e;for(e=b.length;e--;)d=b[e],c.push({isNull:d===null,value:d,color:this.calcColor(e,d,a),offset:a});return c},calcColor:function(a,b,e){var f=this.colorMapByIndex,g=this.colorMapByValue,h=this.options,i,j;return this.stacked?i=h.get("stackedBarColor"):i=b<0?h.get("negBarColor"):h.get("barColor"),b===0&&h.get("zeroColor")!==c&&(i=h.get("zeroColor")),g&&(j=g.get(b))?i=j:f&&f.length>e&&(i=f[e]),d.isArray(i)?i[a%i.length]:i},renderRegion:function(a,e){var f=this.values[a],g=this.options,h=this.xaxisOffset,i=[],j=this.range,k=this.stacked,l=this.target,m=a*this.totalBarWidth,n=this.canvasHeightEf,p=this.yoffset,q,r,s,t,u,v,w,x,y,z;f=d.isArray(f)?f:[f],w=f.length,x=f[0],t=o(null,f),z=o(h,f,!0);if(t)return g.get("nullColor")?(s=e?g.get("nullColor"):this.calcHighlightColor(g.get("nullColor"),g),q=p>0?p-1:p,l.drawRect(m,q,this.barWidth-1,0,s,s)):c;u=p;for(v=0;v<w;v++){x=f[v];if(k&&x===h){if(!z||y)continue;y=!0}j>0?r=b.floor(n*(b.abs(x-h)/j))+1:r=1,x<h||x===h&&p===0?(q=u,u+=r):(q=p-r,p-=r),s=this.calcColor(v,x,a),e&&(s=this.calcHighlightColor(s,g)),i.push(l.drawRect(m,q,this.barWidth-1,r-1,s,s))}return i.length===1?i[0]:i}}),d.fn.sparkline.tristate=z=g(d.fn.sparkline._base,w,{type:"tristate",init:function(a,b,e,f,g){var h=parseInt(e.get("barWidth"),10),i=parseInt(e.get("barSpacing"),10);z._super.init.call(this,a,b,e,f,g),this.regionShapes={},this.barWidth=h,this.barSpacing=i,this.totalBarWidth=h+i,this.values=d.map(b,Number),this.width=f=b.length*h+(b.length-1)*i,d.isArray(e.get("colorMap"))?(this.colorMapByIndex=e.get("colorMap"),this.colorMapByValue=null):(this.colorMapByIndex=null,this.colorMapByValue=e.get("colorMap"),this.colorMapByValue&&this.colorMapByValue.get===c&&(this.colorMapByValue=new t(this.colorMapByValue))),this.initTarget()},getRegion:function(a,c,d){return b.floor(c/this.totalBarWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],color:this.calcColor(this.values[a],a),offset:a}},calcColor:function(a,b){var c=this.values,d=this.options,e=this.colorMapByIndex,f=this.colorMapByValue,g,h;return f&&(h=f.get(a))?g=h:e&&e.length>b?g=e[b]:c[b]<0?g=d.get("negBarColor"):c[b]>0?g=d.get("posBarColor"):g=d.get("zeroBarColor"),g},renderRegion:function(a,c){var d=this.values,e=this.options,f=this.target,g,h,i,j,k,l;g=f.pixelHeight,i=b.round(g/2),j=a*this.totalBarWidth,d[a]<0?(k=i,h=i-1):d[a]>0?(k=0,h=i-1):(k=i-1,h=2),l=this.calcColor(d[a],a);if(l===null)return;return c&&(l=this.calcHighlightColor(l,e)),f.drawRect(j,k,this.barWidth-1,h-1,l,l)}}),d.fn.sparkline.discrete=A=g(d.fn.sparkline._base,w,{type:"discrete",init:function(a,e,f,g,h){A._super.init.call(this,a,e,f,g,h),this.regionShapes={},this.values=e=d.map(e,Number),this.min=b.min.apply(b,e),this.max=b.max.apply(b,e),this.range=this.max-this.min,this.width=g=f.get("width")==="auto"?e.length*2:this.width,this.interval=b.floor(g/e.length),this.itemWidth=g/e.length,f.get("chartRangeMin")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMin")<this.min)&&(this.min=f.get("chartRangeMin")),f.get("chartRangeMax")!==c&&(f.get("chartRangeClip")||f.get("chartRangeMax")>this.max)&&(this.max=f.get("chartRangeMax")),this.initTarget(),this.target&&(this.lineHeight=f.get("lineHeight")==="auto"?b.round(this.canvasHeight*.3):f.get("lineHeight"))},getRegion:function(a,c,d){return b.floor(c/this.itemWidth)},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],offset:a}},renderRegion:function(a,c){var d=this.values,e=this.options,f=this.min,g=this.max,h=this.range,j=this.interval,k=this.target,l=this.canvasHeight,m=this.lineHeight,n=l-m,o,p,q,r;return p=i(d[a],f,g),r=a*j,o=b.round(n-n*((p-f)/h)),q=e.get("thresholdColor")&&p<e.get("thresholdValue")?e.get("thresholdColor"):e.get("lineColor"),c&&(q=this.calcHighlightColor(q,e)),k.drawLine(r,o,r,o+m,q)}}),d.fn.sparkline.bullet=B=g(d.fn.sparkline._base,{type:"bullet",init:function(a,d,e,f,g){var h,i,j;B._super.init.call(this,a,d,e,f,g),this.values=d=l(d),j=d.slice(),j[0]=j[0]===null?j[2]:j[0],j[1]=d[1]===null?j[2]:j[1],h=b.min.apply(b,d),i=b.max.apply(b,d),e.get("base")===c?h=h<0?h:0:h=e.get("base"),this.min=h,this.max=i,this.range=i-h,this.shapes={},this.valueShapes={},this.regiondata={},this.width=f=e.get("width")==="auto"?"4.0em":f,this.target=this.$el.simpledraw(f,g,e.get("composite")),d.length||(this.disabled=!0),this.initTarget()},getRegion:function(a,b,d){var e=this.target.getShapeAt(a,b,d);return e!==c&&this.shapes[e]!==c?this.shapes[e]:c},getCurrentRegionFields:function(){var a=this.currentRegion;return{fieldkey:a.substr(0,1),value:this.values[a.substr(1)],region:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.valueShapes[b],d;delete this.shapes[c];switch(b.substr(0,1)){case"r":d=this.renderRange(b.substr(1),a);break;case"p":d=this.renderPerformance(a);break;case"t":d=this.renderTarget(a)}this.valueShapes[b]=d.id,this.shapes[d.id]=b,this.target.replaceWithShape(c,d)},renderRange:function(a,c){var d=this.values[a],e=b.round(this.canvasWidth*((d-this.min)/this.range)),f=this.options.get("rangeColors")[a-2];return c&&(f=this.calcHighlightColor(f,this.options)),this.target.drawRect(0,0,e-1,this.canvasHeight-1,f,f)},renderPerformance:function(a){var c=this.values[1],d=b.round(this.canvasWidth*((c-this.min)/this.range)),e=this.options.get("performanceColor");return a&&(e=this.calcHighlightColor(e,this.options)),this.target.drawRect(0,b.round(this.canvasHeight*.3),d-1,b.round(this.canvasHeight*.4)-1,e,e)},renderTarget:function(a){var c=this.values[0],d=b.round(this.canvasWidth*((c-this.min)/this.range)-this.options.get("targetWidth")/2),e=b.round(this.canvasHeight*.1),f=this.canvasHeight-e*2,g=this.options.get("targetColor");return a&&(g=this.calcHighlightColor(g,this.options)),this.target.drawRect(d,e,this.options.get("targetWidth")-1,f-1,g,g)},render:function(){var a=this.values.length,b=this.target,c,d;if(!B._super.render.call(this))return;for(c=2;c<a;c++)d=this.renderRange(c).append(),this.shapes[d.id]="r"+c,this.valueShapes["r"+c]=d.id;this.values[1]!==null&&(d=this.renderPerformance().append(),this.shapes[d.id]="p1",this.valueShapes.p1=d.id),this.values[0]!==null&&(d=this.renderTarget().append(),this.shapes[d.id]="t0",this.valueShapes.t0=d.id),b.render()}}),d.fn.sparkline.pie=C=g(d.fn.sparkline._base,{type:"pie",init:function(a,c,e,f,g){var h=0,i;C._super.init.call(this,a,c,e,f,g),this.shapes={},this.valueShapes={},this.values=c=d.map(c,Number),e.get("width")==="auto"&&(this.width=this.height);if(c.length>0)for(i=c.length;i--;)h+=c[i];this.total=h,this.initTarget(),this.radius=b.floor(b.min(this.canvasWidth,this.canvasHeight)/2)},getRegion:function(a,b,d){var e=this.target.getShapeAt(a,b,d);return e!==c&&this.shapes[e]!==c?this.shapes[e]:c},getCurrentRegionFields:function(){var a=this.currentRegion;return{isNull:this.values[a]===c,value:this.values[a],percent:this.values[a]/this.total*100,color:this.options.get("sliceColors")[a%this.options.get("sliceColors").length],offset:a}},changeHighlight:function(a){var b=this.currentRegion,c=this.renderSlice(b,a),d=this.valueShapes[b];delete this.shapes[d],this.target.replaceWithShape(d,c),this.valueShapes[b]=c.id,this.shapes[c.id]=b},renderSlice:function(a,d){var e=this.target,f=this.options,g=this.radius,h=f.get("borderWidth"),i=f.get("offset"),j=2*b.PI,k=this.values,l=this.total,m=i?2*b.PI*(i/360):0,n,o,p,q,r;q=k.length;for(p=0;p<q;p++){n=m,o=m,l>0&&(o=m+j*(k[p]/l));if(a===p)return r=f.get("sliceColors")[p%f.get("sliceColors").length],d&&(r=this.calcHighlightColor(r,f)),e.drawPieSlice(g,g,g-h,n,o,c,r);m=o}},render:function(){var a=this.target,d=this.values,e=this.options,f=this.radius,g=e.get("borderWidth"),h,i;if(!C._super.render.call(this))return;g&&a.drawCircle(f,f,b.floor(f-g/2),e.get("borderColor"),c,g).append();for(i=d.length;i--;)d[i]&&(h=this.renderSlice(i).append(),this.valueShapes[i]=h.id,this.shapes[h.id]=i);a.render()}}),d.fn.sparkline.box=D=g(d.fn.sparkline._base,{type:"box",init:function(a,b,c,e,f){D._super.init.call(this,a,b,c,e,f),this.values=d.map(b,Number),this.width=c.get("width")==="auto"?"4.0em":e,this.initTarget(),this.values.length||(this.disabled=1)},getRegion:function(){return 1},getCurrentRegionFields:function(){var a=[{field:"lq",value:this.quartiles[0]},{field:"med",value:this.quartiles +[1]},{field:"uq",value:this.quartiles[2]}];return this.loutlier!==c&&a.push({field:"lo",value:this.loutlier}),this.routlier!==c&&a.push({field:"ro",value:this.routlier}),this.lwhisker!==c&&a.push({field:"lw",value:this.lwhisker}),this.rwhisker!==c&&a.push({field:"rw",value:this.rwhisker}),a},render:function(){var a=this.target,d=this.values,e=d.length,f=this.options,g=this.canvasWidth,h=this.canvasHeight,i=f.get("chartRangeMin")===c?b.min.apply(b,d):f.get("chartRangeMin"),k=f.get("chartRangeMax")===c?b.max.apply(b,d):f.get("chartRangeMax"),l=0,m,n,o,p,q,r,s,t,u,v,w;if(!D._super.render.call(this))return;if(f.get("raw"))f.get("showOutliers")&&d.length>5?(n=d[0],m=d[1],p=d[2],q=d[3],r=d[4],s=d[5],t=d[6]):(m=d[0],p=d[1],q=d[2],r=d[3],s=d[4]);else{d.sort(function(a,b){return a-b}),p=j(d,1),q=j(d,2),r=j(d,3),o=r-p;if(f.get("showOutliers")){m=s=c;for(u=0;u<e;u++)m===c&&d[u]>p-o*f.get("outlierIQR")&&(m=d[u]),d[u]<r+o*f.get("outlierIQR")&&(s=d[u]);n=d[0],t=d[e-1]}else m=d[0],s=d[e-1]}this.quartiles=[p,q,r],this.lwhisker=m,this.rwhisker=s,this.loutlier=n,this.routlier=t,w=g/(k-i+1),f.get("showOutliers")&&(l=b.ceil(f.get("spotRadius")),g-=2*b.ceil(f.get("spotRadius")),w=g/(k-i+1),n<m&&a.drawCircle((n-i)*w+l,h/2,f.get("spotRadius"),f.get("outlierLineColor"),f.get("outlierFillColor")).append(),t>s&&a.drawCircle((t-i)*w+l,h/2,f.get("spotRadius"),f.get("outlierLineColor"),f.get("outlierFillColor")).append()),a.drawRect(b.round((p-i)*w+l),b.round(h*.1),b.round((r-p)*w),b.round(h*.8),f.get("boxLineColor"),f.get("boxFillColor")).append(),a.drawLine(b.round((m-i)*w+l),b.round(h/2),b.round((p-i)*w+l),b.round(h/2),f.get("lineColor")).append(),a.drawLine(b.round((m-i)*w+l),b.round(h/4),b.round((m-i)*w+l),b.round(h-h/4),f.get("whiskerColor")).append(),a.drawLine(b.round((s-i)*w+l),b.round(h/2),b.round((r-i)*w+l),b.round(h/2),f.get("lineColor")).append(),a.drawLine(b.round((s-i)*w+l),b.round(h/4),b.round((s-i)*w+l),b.round(h-h/4),f.get("whiskerColor")).append(),a.drawLine(b.round((q-i)*w+l),b.round(h*.1),b.round((q-i)*w+l),b.round(h*.9),f.get("medianColor")).append(),f.get("target")&&(v=b.ceil(f.get("spotRadius")),a.drawLine(b.round((f.get("target")-i)*w+l),b.round(h/2-v),b.round((f.get("target")-i)*w+l),b.round(h/2+v),f.get("targetColor")).append(),a.drawLine(b.round((f.get("target")-i)*w+l-v),b.round(h/2),b.round((f.get("target")-i)*w+l+v),b.round(h/2),f.get("targetColor")).append()),a.render()}}),G=g({init:function(a,b,c,d){this.target=a,this.id=b,this.type=c,this.args=d},append:function(){return this.target.appendShape(this),this}}),H=g({_pxregex:/(\d+)(px)?\s*$/i,init:function(a,b,c){if(!a)return;this.width=a,this.height=b,this.target=c,this.lastShapeId=null,c[0]&&(c=c[0]),d.data(c,"_jqs_vcanvas",this)},drawLine:function(a,b,c,d,e,f){return this.drawShape([[a,b],[c,d]],e,f)},drawShape:function(a,b,c,d){return this._genShape("Shape",[a,b,c,d])},drawCircle:function(a,b,c,d,e,f){return this._genShape("Circle",[a,b,c,d,e,f])},drawPieSlice:function(a,b,c,d,e,f,g){return this._genShape("PieSlice",[a,b,c,d,e,f,g])},drawRect:function(a,b,c,d,e,f){return this._genShape("Rect",[a,b,c,d,e,f])},getElement:function(){return this.canvas},getLastShapeId:function(){return this.lastShapeId},reset:function(){alert("reset not implemented")},_insert:function(a,b){d(b).html(a)},_calculatePixelDims:function(a,b,c){var e;e=this._pxregex.exec(b),e?this.pixelHeight=e[1]:this.pixelHeight=d(c).height(),e=this._pxregex.exec(a),e?this.pixelWidth=e[1]:this.pixelWidth=d(c).width()},_genShape:function(a,b){var c=L++;return b.unshift(c),new G(this,c,a,b)},appendShape:function(a){alert("appendShape not implemented")},replaceWithShape:function(a,b){alert("replaceWithShape not implemented")},insertAfterShape:function(a,b){alert("insertAfterShape not implemented")},removeShapeId:function(a){alert("removeShapeId not implemented")},getShapeAt:function(a,b,c){alert("getShapeAt not implemented")},render:function(){alert("render not implemented")}}),I=g(H,{init:function(b,e,f,g){I._super.init.call(this,b,e,f),this.canvas=a.createElement("canvas"),f[0]&&(f=f[0]),d.data(f,"_jqs_vcanvas",this),d(this.canvas).css({display:"inline-block",width:b,height:e,verticalAlign:"top"}),this._insert(this.canvas,f),this._calculatePixelDims(b,e,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,this.interact=g,this.shapes={},this.shapeseq=[],this.currentTargetShapeId=c,d(this.canvas).css({width:this.pixelWidth,height:this.pixelHeight})},_getContext:function(a,b,d){var e=this.canvas.getContext("2d");return a!==c&&(e.strokeStyle=a),e.lineWidth=d===c?1:d,b!==c&&(e.fillStyle=b),e},reset:function(){var a=this._getContext();a.clearRect(0,0,this.pixelWidth,this.pixelHeight),this.shapes={},this.shapeseq=[],this.currentTargetShapeId=c},_drawShape:function(a,b,d,e,f){var g=this._getContext(d,e,f),h,i;g.beginPath(),g.moveTo(b[0][0]+.5,b[0][1]+.5);for(h=1,i=b.length;h<i;h++)g.lineTo(b[h][0]+.5,b[h][1]+.5);d!==c&&g.stroke(),e!==c&&g.fill(),this.targetX!==c&&this.targetY!==c&&g.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawCircle:function(a,d,e,f,g,h,i){var j=this._getContext(g,h,i);j.beginPath(),j.arc(d,e,f,0,2*b.PI,!1),this.targetX!==c&&this.targetY!==c&&j.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a),g!==c&&j.stroke(),h!==c&&j.fill()},_drawPieSlice:function(a,b,d,e,f,g,h,i){var j=this._getContext(h,i);j.beginPath(),j.moveTo(b,d),j.arc(b,d,e,f,g,!1),j.lineTo(b,d),j.closePath(),h!==c&&j.stroke(),i&&j.fill(),this.targetX!==c&&this.targetY!==c&&j.isPointInPath(this.targetX,this.targetY)&&(this.currentTargetShapeId=a)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b+d,c],[b+d,c+e],[b,c+e],[b,c]],f,g)},appendShape:function(a){return this.shapes[a.id]=a,this.shapeseq.push(a.id),this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=this.shapeseq,d;this.shapes[b.id]=b;for(d=c.length;d--;)c[d]==a&&(c[d]=b.id);delete this.shapes[a]},replaceWithShapes:function(a,b){var c=this.shapeseq,d={},e,f,g;for(f=a.length;f--;)d[a[f]]=!0;for(f=c.length;f--;)e=c[f],d[e]&&(c.splice(f,1),delete this.shapes[e],g=f);for(f=b.length;f--;)c.splice(g,0,b[f].id),this.shapes[b[f].id]=b[f]},insertAfterShape:function(a,b){var c=this.shapeseq,d;for(d=c.length;d--;)if(c[d]===a){c.splice(d+1,0,b.id),this.shapes[b.id]=b;return}},removeShapeId:function(a){var b=this.shapeseq,c;for(c=b.length;c--;)if(b[c]===a){b.splice(c,1);break}delete this.shapes[a]},getShapeAt:function(a,b,c){return this.targetX=b,this.targetY=c,this.render(),this.currentTargetShapeId},render:function(){var a=this.shapeseq,b=this.shapes,c=a.length,d=this._getContext(),e,f,g;d.clearRect(0,0,this.pixelWidth,this.pixelHeight);for(g=0;g<c;g++)e=a[g],f=b[e],this["_draw"+f.type].apply(this,f.args);this.interact||(this.shapes={},this.shapeseq=[])}}),J=g(H,{init:function(b,c,e){var f;J._super.init.call(this,b,c,e),e[0]&&(e=e[0]),d.data(e,"_jqs_vcanvas",this),this.canvas=a.createElement("span"),d(this.canvas).css({display:"inline-block",position:"relative",overflow:"hidden",width:b,height:c,margin:"0px",padding:"0px",verticalAlign:"top"}),this._insert(this.canvas,e),this._calculatePixelDims(b,c,this.canvas),this.canvas.width=this.pixelWidth,this.canvas.height=this.pixelHeight,f='<v:group coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'"'+' style="position:absolute;top:0;left:0;width:'+this.pixelWidth+"px;height="+this.pixelHeight+'px;"></v:group>',this.canvas.insertAdjacentHTML("beforeEnd",f),this.group=d(this.canvas).children()[0],this.rendered=!1,this.prerender=""},_drawShape:function(a,b,d,e,f){var g=[],h,i,j,k,l,m,n;for(n=0,m=b.length;n<m;n++)g[n]=""+b[n][0]+","+b[n][1];return h=g.splice(0,1),f=f===c?1:f,i=d===c?' stroked="false" ':' strokeWeight="'+f+'px" strokeColor="'+d+'" ',j=e===c?' filled="false"':' fillColor="'+e+'" filled="true" ',k=g[0]===g[g.length-1]?"x ":"",l='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+i+j+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+h+" l "+g.join(", ")+" "+k+'e">'+" </v:shape>",l},_drawCircle:function(a,b,d,e,f,g,h){var i,j,k;return b-=e,d-=e,i=f===c?' stroked="false" ':' strokeWeight="'+h+'px" strokeColor="'+f+'" ',j=g===c?' filled="false"':' fillColor="'+g+'" filled="true" ',k='<v:oval id="jqsshape'+a+'" '+i+j+' style="position:absolute;top:'+d+"px; left:"+b+"px; width:"+e*2+"px; height:"+e*2+'px"></v:oval>',k},_drawPieSlice:function(a,d,e,f,g,h,i,j){var k,l,m,n,o,p,q,r;if(g===h)return"";h-g===2*b.PI&&(g=0,h=2*b.PI),l=d+b.round(b.cos(g)*f),m=e+b.round(b.sin(g)*f),n=d+b.round(b.cos(h)*f),o=e+b.round(b.sin(h)*f);if(l===n&&m===o){if(h-g<b.PI)return"";l=n=d+f,m=o=e}return l===n&&m===o&&h-g<b.PI?"":(k=[d-f,e-f,d+f,e+f,l,m,n,o],p=i===c?' stroked="false" ':' strokeWeight="1px" strokeColor="'+i+'" ',q=j===c?' filled="false"':' fillColor="'+j+'" filled="true" ',r='<v:shape coordorigin="0 0" coordsize="'+this.pixelWidth+" "+this.pixelHeight+'" '+' id="jqsshape'+a+'" '+p+q+' style="position:absolute;left:0px;top:0px;height:'+this.pixelHeight+"px;width:"+this.pixelWidth+'px;padding:0px;margin:0px;" '+' path="m '+d+","+e+" wa "+k.join(", ")+' x e">'+" </v:shape>",r)},_drawRect:function(a,b,c,d,e,f,g){return this._drawShape(a,[[b,c],[b,c+e],[b+d,c+e],[b+d,c],[b,c]],f,g)},reset:function(){this.group.innerHTML=""},appendShape:function(a){var b=this["_draw"+a.type].apply(this,a.args);return this.rendered?this.group.insertAdjacentHTML("beforeEnd",b):this.prerender+=b,this.lastShapeId=a.id,a.id},replaceWithShape:function(a,b){var c=d("#jqsshape"+a),e=this["_draw"+b.type].apply(this,b.args);c[0].outerHTML=e},replaceWithShapes:function(a,b){var c=d("#jqsshape"+a[0]),e="",f=b.length,g;for(g=0;g<f;g++)e+=this["_draw"+b[g].type].apply(this,b[g].args);c[0].outerHTML=e;for(g=1;g<a.length;g++)d("#jqsshape"+a[g]).remove()},insertAfterShape:function(a,b){var c=d("#jqsshape"+a),e=this["_draw"+b.type].apply(this,b.args);c[0].insertAdjacentHTML("afterEnd",e)},removeShapeId:function(a){var b=d("#jqsshape"+a);this.group.removeChild(b[0])},getShapeAt:function(a,b,c){var d=a.id.substr(8);return d},render:function(){this.rendered||(this.group.innerHTML=this.prerender,this.rendered=!0)}})})})(document,Math); diff --git a/web/gui/lib/lz-string-1.4.4.min.js b/web/gui/lib/lz-string-1.4.4.min.js new file mode 100644 index 0000000..c7de0d5 --- /dev/null +++ b/web/gui/lib/lz-string-1.4.4.min.js @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: WTFPL +var LZString=function(){function o(o,r){if(!t[o]){t[o]={};for(var n=0;n<o.length;n++)t[o][o.charAt(n)]=n}return t[o][r]}var r=String.fromCharCode,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$",t={},i={compressToBase64:function(o){if(null==o)return"";var r=i._compress(o,6,function(o){return n.charAt(o)});switch(r.length%4){default:case 0:return r;case 1:return r+"===";case 2:return r+"==";case 3:return r+"="}},decompressFromBase64:function(r){return null==r?"":""==r?null:i._decompress(r.length,32,function(e){return o(n,r.charAt(e))})},compressToUTF16:function(o){return null==o?"":i._compress(o,15,function(o){return r(o+32)})+" "},decompressFromUTF16:function(o){return null==o?"":""==o?null:i._decompress(o.length,16384,function(r){return o.charCodeAt(r)-32})},compressToUint8Array:function(o){for(var r=i.compress(o),n=new Uint8Array(2*r.length),e=0,t=r.length;t>e;e++){var s=r.charCodeAt(e);n[2*e]=s>>>8,n[2*e+1]=s%256}return n},decompressFromUint8Array:function(o){if(null===o||void 0===o)return i.decompress(o);for(var n=new Array(o.length/2),e=0,t=n.length;t>e;e++)n[e]=256*o[2*e]+o[2*e+1];var s=[];return n.forEach(function(o){s.push(r(o))}),i.decompress(s.join(""))},compressToEncodedURIComponent:function(o){return null==o?"":i._compress(o,6,function(o){return e.charAt(o)})},decompressFromEncodedURIComponent:function(r){return null==r?"":""==r?null:(r=r.replace(/ /g,"+"),i._decompress(r.length,32,function(n){return o(e,r.charAt(n))}))},compress:function(o){return i._compress(o,16,function(o){return r(o)})},_compress:function(o,r,n){if(null==o)return"";var e,t,i,s={},p={},u="",c="",a="",l=2,f=3,h=2,d=[],m=0,v=0;for(i=0;i<o.length;i+=1)if(u=o.charAt(i),Object.prototype.hasOwnProperty.call(s,u)||(s[u]=f++,p[u]=!0),c=a+u,Object.prototype.hasOwnProperty.call(s,c))a=c;else{if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++),s[c]=f++,a=String(u)}if(""!==a){if(Object.prototype.hasOwnProperty.call(p,a)){if(a.charCodeAt(0)<256){for(e=0;h>e;e++)m<<=1,v==r-1?(v=0,d.push(n(m)),m=0):v++;for(t=a.charCodeAt(0),e=0;8>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}else{for(t=1,e=0;h>e;e++)m=m<<1|t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t=0;for(t=a.charCodeAt(0),e=0;16>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1}l--,0==l&&(l=Math.pow(2,h),h++),delete p[a]}else for(t=s[a],e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;l--,0==l&&(l=Math.pow(2,h),h++)}for(t=2,e=0;h>e;e++)m=m<<1|1&t,v==r-1?(v=0,d.push(n(m)),m=0):v++,t>>=1;for(;;){if(m<<=1,v==r-1){d.push(n(m));break}v++}return d.join("")},decompress:function(o){return null==o?"":""==o?null:i._decompress(o.length,32768,function(r){return o.charCodeAt(r)})},_decompress:function(o,n,e){var t,i,s,p,u,c,a,l,f=[],h=4,d=4,m=3,v="",w=[],A={val:e(0),position:n,index:1};for(i=0;3>i;i+=1)f[i]=i;for(p=0,c=Math.pow(2,2),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(t=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;l=r(p);break;case 2:return""}for(f[3]=l,s=l,w.push(l);;){if(A.index>o)return"";for(p=0,c=Math.pow(2,m),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;switch(l=p){case 0:for(p=0,c=Math.pow(2,8),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 1:for(p=0,c=Math.pow(2,16),a=1;a!=c;)u=A.val&A.position,A.position>>=1,0==A.position&&(A.position=n,A.val=e(A.index++)),p|=(u>0?1:0)*a,a<<=1;f[d++]=r(p),l=d-1,h--;break;case 2:return w.join("")}if(0==h&&(h=Math.pow(2,m),m++),f[l])v=f[l];else{if(l!==d)return null;v=s+s.charAt(0)}w.push(v),f[d++]=s+v.charAt(0),h--,s=v,0==h&&(h=Math.pow(2,m),m++)}}};return i}();"function"==typeof define&&define.amd?define(function(){return LZString}):"undefined"!=typeof module&&null!=module&&(module.exports=LZString); diff --git a/web/gui/lib/pako-1.0.6.min.js b/web/gui/lib/pako-1.0.6.min.js new file mode 100644 index 0000000..165fc26 --- /dev/null +++ b/web/gui/lib/pako-1.0.6.min.js @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).pako=t()}}(function(){return function t(e,a,i){function n(s,o){if(!a[s]){if(!e[s]){var l="function"==typeof require&&require;if(!o&&l)return l(s,!0);if(r)return r(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var d=a[s]={exports:{}};e[s][0].call(d.exports,function(t){var a=e[s][1][t];return n(a||t)},d,d.exports,t,e,a,i)}return a[s].exports}for(var r="function"==typeof require&&require,s=0;s<i.length;s++)n(i[s]);return n}({1:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({level:_,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:u,to:""},t||{});var e=this.options;e.raw&&e.windowBits>0?e.windowBits=-e.windowBits:e.gzip&&e.windowBits>0&&e.windowBits<16&&(e.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new h,this.strm.avail_out=0;var a=r.deflateInit2(this.strm,e.level,e.method,e.windowBits,e.memLevel,e.strategy);if(a!==f)throw new Error(l[a]);if(e.header&&r.deflateSetHeader(this.strm,e.header),e.dictionary){var n;if(n="string"==typeof e.dictionary?o.string2buf(e.dictionary):"[object ArrayBuffer]"===d.call(e.dictionary)?new Uint8Array(e.dictionary):e.dictionary,(a=r.deflateSetDictionary(this.strm,n))!==f)throw new Error(l[a]);this._dict_set=!0}}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||l[a.err];return a.result}var r=t("./zlib/deflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/messages"),h=t("./zlib/zstream"),d=Object.prototype.toString,f=0,_=-1,u=0,c=8;i.prototype.push=function(t,e){var a,i,n=this.strm,l=this.options.chunkSize;if(this.ended)return!1;i=e===~~e?e:!0===e?4:0,"string"==typeof t?n.input=o.string2buf(t):"[object ArrayBuffer]"===d.call(t)?n.input=new Uint8Array(t):n.input=t,n.next_in=0,n.avail_in=n.input.length;do{if(0===n.avail_out&&(n.output=new s.Buf8(l),n.next_out=0,n.avail_out=l),1!==(a=r.deflate(n,i))&&a!==f)return this.onEnd(a),this.ended=!0,!1;0!==n.avail_out&&(0!==n.avail_in||4!==i&&2!==i)||("string"===this.options.to?this.onData(o.buf2binstring(s.shrinkBuf(n.output,n.next_out))):this.onData(s.shrinkBuf(n.output,n.next_out)))}while((n.avail_in>0||0===n.avail_out)&&1!==a);return 4===i?(a=r.deflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===f):2!==i||(this.onEnd(f),n.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===f&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Deflate=i,a.deflate=n,a.deflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.gzip=function(t,e){return e=e||{},e.gzip=!0,n(t,e)}},{"./utils/common":3,"./utils/strings":4,"./zlib/deflate":8,"./zlib/messages":13,"./zlib/zstream":15}],2:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&e.windowBits>=0&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(e.windowBits>=0&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),e.windowBits>15&&e.windowBits<48&&0==(15&e.windowBits)&&(e.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var a=r.inflateInit2(this.strm,e.windowBits);if(a!==l.Z_OK)throw new Error(h[a]);this.header=new f,r.inflateGetHeader(this.strm,this.header)}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||h[a.err];return a.result}var r=t("./zlib/inflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/constants"),h=t("./zlib/messages"),d=t("./zlib/zstream"),f=t("./zlib/gzheader"),_=Object.prototype.toString;i.prototype.push=function(t,e){var a,i,n,h,d,f,u=this.strm,c=this.options.chunkSize,b=this.options.dictionary,g=!1;if(this.ended)return!1;i=e===~~e?e:!0===e?l.Z_FINISH:l.Z_NO_FLUSH,"string"==typeof t?u.input=o.binstring2buf(t):"[object ArrayBuffer]"===_.call(t)?u.input=new Uint8Array(t):u.input=t,u.next_in=0,u.avail_in=u.input.length;do{if(0===u.avail_out&&(u.output=new s.Buf8(c),u.next_out=0,u.avail_out=c),(a=r.inflate(u,l.Z_NO_FLUSH))===l.Z_NEED_DICT&&b&&(f="string"==typeof b?o.string2buf(b):"[object ArrayBuffer]"===_.call(b)?new Uint8Array(b):b,a=r.inflateSetDictionary(this.strm,f)),a===l.Z_BUF_ERROR&&!0===g&&(a=l.Z_OK,g=!1),a!==l.Z_STREAM_END&&a!==l.Z_OK)return this.onEnd(a),this.ended=!0,!1;u.next_out&&(0!==u.avail_out&&a!==l.Z_STREAM_END&&(0!==u.avail_in||i!==l.Z_FINISH&&i!==l.Z_SYNC_FLUSH)||("string"===this.options.to?(n=o.utf8border(u.output,u.next_out),h=u.next_out-n,d=o.buf2string(u.output,n),u.next_out=h,u.avail_out=c-h,h&&s.arraySet(u.output,u.output,n,h,0),this.onData(d)):this.onData(s.shrinkBuf(u.output,u.next_out)))),0===u.avail_in&&0===u.avail_out&&(g=!0)}while((u.avail_in>0||0===u.avail_out)&&a!==l.Z_STREAM_END);return a===l.Z_STREAM_END&&(i=l.Z_FINISH),i===l.Z_FINISH?(a=r.inflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===l.Z_OK):i!==l.Z_SYNC_FLUSH||(this.onEnd(l.Z_OK),u.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===l.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Inflate=i,a.inflate=n,a.inflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.ungzip=n},{"./utils/common":3,"./utils/strings":4,"./zlib/constants":6,"./zlib/gzheader":9,"./zlib/inflate":11,"./zlib/messages":13,"./zlib/zstream":15}],3:[function(t,e,a){"use strict";function i(t,e){return Object.prototype.hasOwnProperty.call(t,e)}var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;a.assign=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var a=e.shift();if(a){if("object"!=typeof a)throw new TypeError(a+"must be non-object");for(var n in a)i(a,n)&&(t[n]=a[n])}}return t},a.shrinkBuf=function(t,e){return t.length===e?t:t.subarray?t.subarray(0,e):(t.length=e,t)};var r={arraySet:function(t,e,a,i,n){if(e.subarray&&t.subarray)t.set(e.subarray(a,a+i),n);else for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){var e,a,i,n,r,s;for(i=0,e=0,a=t.length;e<a;e++)i+=t[e].length;for(s=new Uint8Array(i),n=0,e=0,a=t.length;e<a;e++)r=t[e],s.set(r,n),n+=r.length;return s}},s={arraySet:function(t,e,a,i,n){for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){return[].concat.apply([],t)}};a.setTyped=function(t){t?(a.Buf8=Uint8Array,a.Buf16=Uint16Array,a.Buf32=Int32Array,a.assign(a,r)):(a.Buf8=Array,a.Buf16=Array,a.Buf32=Array,a.assign(a,s))},a.setTyped(n)},{}],4:[function(t,e,a){"use strict";function i(t,e){if(e<65537&&(t.subarray&&s||!t.subarray&&r))return String.fromCharCode.apply(null,n.shrinkBuf(t,e));for(var a="",i=0;i<e;i++)a+=String.fromCharCode(t[i]);return a}var n=t("./common"),r=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(t){r=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(t){s=!1}for(var o=new n.Buf8(256),l=0;l<256;l++)o[l]=l>=252?6:l>=248?5:l>=240?4:l>=224?3:l>=192?2:1;o[254]=o[254]=1,a.string2buf=function(t){var e,a,i,r,s,o=t.length,l=0;for(r=0;r<o;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),l+=a<128?1:a<2048?2:a<65536?3:4;for(e=new n.Buf8(l),s=0,r=0;s<l;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),a<128?e[s++]=a:a<2048?(e[s++]=192|a>>>6,e[s++]=128|63&a):a<65536?(e[s++]=224|a>>>12,e[s++]=128|a>>>6&63,e[s++]=128|63&a):(e[s++]=240|a>>>18,e[s++]=128|a>>>12&63,e[s++]=128|a>>>6&63,e[s++]=128|63&a);return e},a.buf2binstring=function(t){return i(t,t.length)},a.binstring2buf=function(t){for(var e=new n.Buf8(t.length),a=0,i=e.length;a<i;a++)e[a]=t.charCodeAt(a);return e},a.buf2string=function(t,e){var a,n,r,s,l=e||t.length,h=new Array(2*l);for(n=0,a=0;a<l;)if((r=t[a++])<128)h[n++]=r;else if((s=o[r])>4)h[n++]=65533,a+=s-1;else{for(r&=2===s?31:3===s?15:7;s>1&&a<l;)r=r<<6|63&t[a++],s--;s>1?h[n++]=65533:r<65536?h[n++]=r:(r-=65536,h[n++]=55296|r>>10&1023,h[n++]=56320|1023&r)}return i(h,n)},a.utf8border=function(t,e){var a;for((e=e||t.length)>t.length&&(e=t.length),a=e-1;a>=0&&128==(192&t[a]);)a--;return a<0?e:0===a?e:a+o[t[a]]>e?a:e}},{"./common":3}],5:[function(t,e,a){"use strict";e.exports=function(t,e,a,i){for(var n=65535&t|0,r=t>>>16&65535|0,s=0;0!==a;){a-=s=a>2e3?2e3:a;do{r=r+(n=n+e[i++]|0)|0}while(--s);n%=65521,r%=65521}return n|r<<16|0}},{}],6:[function(t,e,a){"use strict";e.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],7:[function(t,e,a){"use strict";var i=function(){for(var t,e=[],a=0;a<256;a++){t=a;for(var i=0;i<8;i++)t=1&t?3988292384^t>>>1:t>>>1;e[a]=t}return e}();e.exports=function(t,e,a,n){var r=i,s=n+a;t^=-1;for(var o=n;o<s;o++)t=t>>>8^r[255&(t^e[o])];return-1^t}},{}],8:[function(t,e,a){"use strict";function i(t,e){return t.msg=A[e],e}function n(t){return(t<<1)-(t>4?9:0)}function r(t){for(var e=t.length;--e>=0;)t[e]=0}function s(t){var e=t.state,a=e.pending;a>t.avail_out&&(a=t.avail_out),0!==a&&(z.arraySet(t.output,e.pending_buf,e.pending_out,a,t.next_out),t.next_out+=a,e.pending_out+=a,t.total_out+=a,t.avail_out-=a,e.pending-=a,0===e.pending&&(e.pending_out=0))}function o(t,e){B._tr_flush_block(t,t.block_start>=0?t.block_start:-1,t.strstart-t.block_start,e),t.block_start=t.strstart,s(t.strm)}function l(t,e){t.pending_buf[t.pending++]=e}function h(t,e){t.pending_buf[t.pending++]=e>>>8&255,t.pending_buf[t.pending++]=255&e}function d(t,e,a,i){var n=t.avail_in;return n>i&&(n=i),0===n?0:(t.avail_in-=n,z.arraySet(e,t.input,t.next_in,n,a),1===t.state.wrap?t.adler=S(t.adler,e,n,a):2===t.state.wrap&&(t.adler=E(t.adler,e,n,a)),t.next_in+=n,t.total_in+=n,n)}function f(t,e){var a,i,n=t.max_chain_length,r=t.strstart,s=t.prev_length,o=t.nice_match,l=t.strstart>t.w_size-it?t.strstart-(t.w_size-it):0,h=t.window,d=t.w_mask,f=t.prev,_=t.strstart+at,u=h[r+s-1],c=h[r+s];t.prev_length>=t.good_match&&(n>>=2),o>t.lookahead&&(o=t.lookahead);do{if(a=e,h[a+s]===c&&h[a+s-1]===u&&h[a]===h[r]&&h[++a]===h[r+1]){r+=2,a++;do{}while(h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&r<_);if(i=at-(_-r),r=_-at,i>s){if(t.match_start=e,s=i,i>=o)break;u=h[r+s-1],c=h[r+s]}}}while((e=f[e&d])>l&&0!=--n);return s<=t.lookahead?s:t.lookahead}function _(t){var e,a,i,n,r,s=t.w_size;do{if(n=t.window_size-t.lookahead-t.strstart,t.strstart>=s+(s-it)){z.arraySet(t.window,t.window,s,s,0),t.match_start-=s,t.strstart-=s,t.block_start-=s,e=a=t.hash_size;do{i=t.head[--e],t.head[e]=i>=s?i-s:0}while(--a);e=a=s;do{i=t.prev[--e],t.prev[e]=i>=s?i-s:0}while(--a);n+=s}if(0===t.strm.avail_in)break;if(a=d(t.strm,t.window,t.strstart+t.lookahead,n),t.lookahead+=a,t.lookahead+t.insert>=et)for(r=t.strstart-t.insert,t.ins_h=t.window[r],t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+1])&t.hash_mask;t.insert&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+et-1])&t.hash_mask,t.prev[r&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=r,r++,t.insert--,!(t.lookahead+t.insert<et)););}while(t.lookahead<it&&0!==t.strm.avail_in)}function u(t,e){for(var a,i;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),0!==a&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a)),t.match_length>=et)if(i=B._tr_tally(t,t.strstart-t.match_start,t.match_length-et),t.lookahead-=t.match_length,t.match_length<=t.max_lazy_match&&t.lookahead>=et){t.match_length--;do{t.strstart++,t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart}while(0!=--t.match_length);t.strstart++}else t.strstart+=t.match_length,t.match_length=0,t.ins_h=t.window[t.strstart],t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+1])&t.hash_mask;else i=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++;if(i&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function c(t,e){for(var a,i,n;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),t.prev_length=t.match_length,t.prev_match=t.match_start,t.match_length=et-1,0!==a&&t.prev_length<t.max_lazy_match&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a),t.match_length<=5&&(t.strategy===H||t.match_length===et&&t.strstart-t.match_start>4096)&&(t.match_length=et-1)),t.prev_length>=et&&t.match_length<=t.prev_length){n=t.strstart+t.lookahead-et,i=B._tr_tally(t,t.strstart-1-t.prev_match,t.prev_length-et),t.lookahead-=t.prev_length-1,t.prev_length-=2;do{++t.strstart<=n&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart)}while(0!=--t.prev_length);if(t.match_available=0,t.match_length=et-1,t.strstart++,i&&(o(t,!1),0===t.strm.avail_out))return _t}else if(t.match_available){if((i=B._tr_tally(t,0,t.window[t.strstart-1]))&&o(t,!1),t.strstart++,t.lookahead--,0===t.strm.avail_out)return _t}else t.match_available=1,t.strstart++,t.lookahead--}return t.match_available&&(i=B._tr_tally(t,0,t.window[t.strstart-1]),t.match_available=0),t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function b(t,e){for(var a,i,n,r,s=t.window;;){if(t.lookahead<=at){if(_(t),t.lookahead<=at&&e===Z)return _t;if(0===t.lookahead)break}if(t.match_length=0,t.lookahead>=et&&t.strstart>0&&(n=t.strstart-1,(i=s[n])===s[++n]&&i===s[++n]&&i===s[++n])){r=t.strstart+at;do{}while(i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&n<r);t.match_length=at-(r-n),t.match_length>t.lookahead&&(t.match_length=t.lookahead)}if(t.match_length>=et?(a=B._tr_tally(t,1,t.match_length-et),t.lookahead-=t.match_length,t.strstart+=t.match_length,t.match_length=0):(a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++),a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function g(t,e){for(var a;;){if(0===t.lookahead&&(_(t),0===t.lookahead)){if(e===Z)return _t;break}if(t.match_length=0,a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++,a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function m(t,e,a,i,n){this.good_length=t,this.max_lazy=e,this.nice_length=a,this.max_chain=i,this.func=n}function w(t){t.window_size=2*t.w_size,r(t.head),t.max_lazy_match=x[t.level].max_lazy,t.good_match=x[t.level].good_length,t.nice_match=x[t.level].nice_length,t.max_chain_length=x[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=et-1,t.match_available=0,t.ins_h=0}function p(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=q,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new z.Buf16(2*$),this.dyn_dtree=new z.Buf16(2*(2*Q+1)),this.bl_tree=new z.Buf16(2*(2*V+1)),r(this.dyn_ltree),r(this.dyn_dtree),r(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new z.Buf16(tt+1),this.heap=new z.Buf16(2*J+1),r(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new z.Buf16(2*J+1),r(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function v(t){var e;return t&&t.state?(t.total_in=t.total_out=0,t.data_type=Y,e=t.state,e.pending=0,e.pending_out=0,e.wrap<0&&(e.wrap=-e.wrap),e.status=e.wrap?rt:dt,t.adler=2===e.wrap?0:1,e.last_flush=Z,B._tr_init(e),D):i(t,U)}function k(t){var e=v(t);return e===D&&w(t.state),e}function y(t,e,a,n,r,s){if(!t)return U;var o=1;if(e===L&&(e=6),n<0?(o=0,n=-n):n>15&&(o=2,n-=16),r<1||r>G||a!==q||n<8||n>15||e<0||e>9||s<0||s>M)return i(t,U);8===n&&(n=9);var l=new p;return t.state=l,l.strm=t,l.wrap=o,l.gzhead=null,l.w_bits=n,l.w_size=1<<l.w_bits,l.w_mask=l.w_size-1,l.hash_bits=r+7,l.hash_size=1<<l.hash_bits,l.hash_mask=l.hash_size-1,l.hash_shift=~~((l.hash_bits+et-1)/et),l.window=new z.Buf8(2*l.w_size),l.head=new z.Buf16(l.hash_size),l.prev=new z.Buf16(l.w_size),l.lit_bufsize=1<<r+6,l.pending_buf_size=4*l.lit_bufsize,l.pending_buf=new z.Buf8(l.pending_buf_size),l.d_buf=1*l.lit_bufsize,l.l_buf=3*l.lit_bufsize,l.level=e,l.strategy=s,l.method=a,k(t)}var x,z=t("../utils/common"),B=t("./trees"),S=t("./adler32"),E=t("./crc32"),A=t("./messages"),Z=0,R=1,C=3,N=4,O=5,D=0,I=1,U=-2,T=-3,F=-5,L=-1,H=1,j=2,K=3,M=4,P=0,Y=2,q=8,G=9,X=15,W=8,J=286,Q=30,V=19,$=2*J+1,tt=15,et=3,at=258,it=at+et+1,nt=32,rt=42,st=69,ot=73,lt=91,ht=103,dt=113,ft=666,_t=1,ut=2,ct=3,bt=4,gt=3;x=[new m(0,0,0,0,function(t,e){var a=65535;for(a>t.pending_buf_size-5&&(a=t.pending_buf_size-5);;){if(t.lookahead<=1){if(_(t),0===t.lookahead&&e===Z)return _t;if(0===t.lookahead)break}t.strstart+=t.lookahead,t.lookahead=0;var i=t.block_start+a;if((0===t.strstart||t.strstart>=i)&&(t.lookahead=t.strstart-i,t.strstart=i,o(t,!1),0===t.strm.avail_out))return _t;if(t.strstart-t.block_start>=t.w_size-it&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):(t.strstart>t.block_start&&(o(t,!1),t.strm.avail_out),_t)}),new m(4,4,8,4,u),new m(4,5,16,8,u),new m(4,6,32,32,u),new m(4,4,16,16,c),new m(8,16,32,32,c),new m(8,16,128,128,c),new m(8,32,128,256,c),new m(32,128,258,1024,c),new m(32,258,258,4096,c)],a.deflateInit=function(t,e){return y(t,e,q,X,W,P)},a.deflateInit2=y,a.deflateReset=k,a.deflateResetKeep=v,a.deflateSetHeader=function(t,e){return t&&t.state?2!==t.state.wrap?U:(t.state.gzhead=e,D):U},a.deflate=function(t,e){var a,o,d,f;if(!t||!t.state||e>O||e<0)return t?i(t,U):U;if(o=t.state,!t.output||!t.input&&0!==t.avail_in||o.status===ft&&e!==N)return i(t,0===t.avail_out?F:U);if(o.strm=t,a=o.last_flush,o.last_flush=e,o.status===rt)if(2===o.wrap)t.adler=0,l(o,31),l(o,139),l(o,8),o.gzhead?(l(o,(o.gzhead.text?1:0)+(o.gzhead.hcrc?2:0)+(o.gzhead.extra?4:0)+(o.gzhead.name?8:0)+(o.gzhead.comment?16:0)),l(o,255&o.gzhead.time),l(o,o.gzhead.time>>8&255),l(o,o.gzhead.time>>16&255),l(o,o.gzhead.time>>24&255),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,255&o.gzhead.os),o.gzhead.extra&&o.gzhead.extra.length&&(l(o,255&o.gzhead.extra.length),l(o,o.gzhead.extra.length>>8&255)),o.gzhead.hcrc&&(t.adler=E(t.adler,o.pending_buf,o.pending,0)),o.gzindex=0,o.status=st):(l(o,0),l(o,0),l(o,0),l(o,0),l(o,0),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,gt),o.status=dt);else{var _=q+(o.w_bits-8<<4)<<8;_|=(o.strategy>=j||o.level<2?0:o.level<6?1:6===o.level?2:3)<<6,0!==o.strstart&&(_|=nt),_+=31-_%31,o.status=dt,h(o,_),0!==o.strstart&&(h(o,t.adler>>>16),h(o,65535&t.adler)),t.adler=1}if(o.status===st)if(o.gzhead.extra){for(d=o.pending;o.gzindex<(65535&o.gzhead.extra.length)&&(o.pending!==o.pending_buf_size||(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending!==o.pending_buf_size));)l(o,255&o.gzhead.extra[o.gzindex]),o.gzindex++;o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),o.gzindex===o.gzhead.extra.length&&(o.gzindex=0,o.status=ot)}else o.status=ot;if(o.status===ot)if(o.gzhead.name){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.name.length?255&o.gzhead.name.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.gzindex=0,o.status=lt)}else o.status=lt;if(o.status===lt)if(o.gzhead.comment){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.comment.length?255&o.gzhead.comment.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.status=ht)}else o.status=ht;if(o.status===ht&&(o.gzhead.hcrc?(o.pending+2>o.pending_buf_size&&s(t),o.pending+2<=o.pending_buf_size&&(l(o,255&t.adler),l(o,t.adler>>8&255),t.adler=0,o.status=dt)):o.status=dt),0!==o.pending){if(s(t),0===t.avail_out)return o.last_flush=-1,D}else if(0===t.avail_in&&n(e)<=n(a)&&e!==N)return i(t,F);if(o.status===ft&&0!==t.avail_in)return i(t,F);if(0!==t.avail_in||0!==o.lookahead||e!==Z&&o.status!==ft){var u=o.strategy===j?g(o,e):o.strategy===K?b(o,e):x[o.level].func(o,e);if(u!==ct&&u!==bt||(o.status=ft),u===_t||u===ct)return 0===t.avail_out&&(o.last_flush=-1),D;if(u===ut&&(e===R?B._tr_align(o):e!==O&&(B._tr_stored_block(o,0,0,!1),e===C&&(r(o.head),0===o.lookahead&&(o.strstart=0,o.block_start=0,o.insert=0))),s(t),0===t.avail_out))return o.last_flush=-1,D}return e!==N?D:o.wrap<=0?I:(2===o.wrap?(l(o,255&t.adler),l(o,t.adler>>8&255),l(o,t.adler>>16&255),l(o,t.adler>>24&255),l(o,255&t.total_in),l(o,t.total_in>>8&255),l(o,t.total_in>>16&255),l(o,t.total_in>>24&255)):(h(o,t.adler>>>16),h(o,65535&t.adler)),s(t),o.wrap>0&&(o.wrap=-o.wrap),0!==o.pending?D:I)},a.deflateEnd=function(t){var e;return t&&t.state?(e=t.state.status)!==rt&&e!==st&&e!==ot&&e!==lt&&e!==ht&&e!==dt&&e!==ft?i(t,U):(t.state=null,e===dt?i(t,T):D):U},a.deflateSetDictionary=function(t,e){var a,i,n,s,o,l,h,d,f=e.length;if(!t||!t.state)return U;if(a=t.state,2===(s=a.wrap)||1===s&&a.status!==rt||a.lookahead)return U;for(1===s&&(t.adler=S(t.adler,e,f,0)),a.wrap=0,f>=a.w_size&&(0===s&&(r(a.head),a.strstart=0,a.block_start=0,a.insert=0),d=new z.Buf8(a.w_size),z.arraySet(d,e,f-a.w_size,a.w_size,0),e=d,f=a.w_size),o=t.avail_in,l=t.next_in,h=t.input,t.avail_in=f,t.next_in=0,t.input=e,_(a);a.lookahead>=et;){i=a.strstart,n=a.lookahead-(et-1);do{a.ins_h=(a.ins_h<<a.hash_shift^a.window[i+et-1])&a.hash_mask,a.prev[i&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=i,i++}while(--n);a.strstart=i,a.lookahead=et-1,_(a)}return a.strstart+=a.lookahead,a.block_start=a.strstart,a.insert=a.lookahead,a.lookahead=0,a.match_length=a.prev_length=et-1,a.match_available=0,t.next_in=l,t.input=h,t.avail_in=o,a.wrap=s,D},a.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./messages":13,"./trees":14}],9:[function(t,e,a){"use strict";e.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],10:[function(t,e,a){"use strict";e.exports=function(t,e){var a,i,n,r,s,o,l,h,d,f,_,u,c,b,g,m,w,p,v,k,y,x,z,B,S;a=t.state,i=t.next_in,B=t.input,n=i+(t.avail_in-5),r=t.next_out,S=t.output,s=r-(e-t.avail_out),o=r+(t.avail_out-257),l=a.dmax,h=a.wsize,d=a.whave,f=a.wnext,_=a.window,u=a.hold,c=a.bits,b=a.lencode,g=a.distcode,m=(1<<a.lenbits)-1,w=(1<<a.distbits)-1;t:do{c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=b[u&m];e:for(;;){if(v=p>>>24,u>>>=v,c-=v,0===(v=p>>>16&255))S[r++]=65535&p;else{if(!(16&v)){if(0==(64&v)){p=b[(65535&p)+(u&(1<<v)-1)];continue e}if(32&v){a.mode=12;break t}t.msg="invalid literal/length code",a.mode=30;break t}k=65535&p,(v&=15)&&(c<v&&(u+=B[i++]<<c,c+=8),k+=u&(1<<v)-1,u>>>=v,c-=v),c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=g[u&w];a:for(;;){if(v=p>>>24,u>>>=v,c-=v,!(16&(v=p>>>16&255))){if(0==(64&v)){p=g[(65535&p)+(u&(1<<v)-1)];continue a}t.msg="invalid distance code",a.mode=30;break t}if(y=65535&p,v&=15,c<v&&(u+=B[i++]<<c,(c+=8)<v&&(u+=B[i++]<<c,c+=8)),(y+=u&(1<<v)-1)>l){t.msg="invalid distance too far back",a.mode=30;break t}if(u>>>=v,c-=v,v=r-s,y>v){if((v=y-v)>d&&a.sane){t.msg="invalid distance too far back",a.mode=30;break t}if(x=0,z=_,0===f){if(x+=h-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}else if(f<v){if(x+=h+f-v,(v-=f)<k){k-=v;do{S[r++]=_[x++]}while(--v);if(x=0,f<k){k-=v=f;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}}else if(x+=f-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}for(;k>2;)S[r++]=z[x++],S[r++]=z[x++],S[r++]=z[x++],k-=3;k&&(S[r++]=z[x++],k>1&&(S[r++]=z[x++]))}else{x=r-y;do{S[r++]=S[x++],S[r++]=S[x++],S[r++]=S[x++],k-=3}while(k>2);k&&(S[r++]=S[x++],k>1&&(S[r++]=S[x++]))}break}}break}}while(i<n&&r<o);i-=k=c>>3,u&=(1<<(c-=k<<3))-1,t.next_in=i,t.next_out=r,t.avail_in=i<n?n-i+5:5-(i-n),t.avail_out=r<o?o-r+257:257-(r-o),a.hold=u,a.bits=c}},{}],11:[function(t,e,a){"use strict";function i(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function n(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new u.Buf16(320),this.work=new u.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function r(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=N,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new u.Buf32(dt),e.distcode=e.distdyn=new u.Buf32(ft),e.sane=1,e.back=-1,z):E}function s(t){var e;return t&&t.state?(e=t.state,e.wsize=0,e.whave=0,e.wnext=0,r(t)):E}function o(t,e){var a,i;return t&&t.state?(i=t.state,e<0?(a=0,e=-e):(a=1+(e>>4),e<48&&(e&=15)),e&&(e<8||e>15)?E:(null!==i.window&&i.wbits!==e&&(i.window=null),i.wrap=a,i.wbits=e,s(t))):E}function l(t,e){var a,i;return t?(i=new n,t.state=i,i.window=null,(a=o(t,e))!==z&&(t.state=null),a):E}function h(t){if(ut){var e;for(f=new u.Buf32(512),_=new u.Buf32(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(m(p,t.lens,0,288,f,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;m(v,t.lens,0,32,_,0,t.work,{bits:5}),ut=!1}t.lencode=f,t.lenbits=9,t.distcode=_,t.distbits=5}function d(t,e,a,i){var n,r=t.state;return null===r.window&&(r.wsize=1<<r.wbits,r.wnext=0,r.whave=0,r.window=new u.Buf8(r.wsize)),i>=r.wsize?(u.arraySet(r.window,e,a-r.wsize,r.wsize,0),r.wnext=0,r.whave=r.wsize):((n=r.wsize-r.wnext)>i&&(n=i),u.arraySet(r.window,e,a-i,n,r.wnext),(i-=n)?(u.arraySet(r.window,e,a-i,i,0),r.wnext=i,r.whave=r.wsize):(r.wnext+=n,r.wnext===r.wsize&&(r.wnext=0),r.whave<r.wsize&&(r.whave+=n))),0}var f,_,u=t("../utils/common"),c=t("./adler32"),b=t("./crc32"),g=t("./inffast"),m=t("./inftrees"),w=0,p=1,v=2,k=4,y=5,x=6,z=0,B=1,S=2,E=-2,A=-3,Z=-4,R=-5,C=8,N=1,O=2,D=3,I=4,U=5,T=6,F=7,L=8,H=9,j=10,K=11,M=12,P=13,Y=14,q=15,G=16,X=17,W=18,J=19,Q=20,V=21,$=22,tt=23,et=24,at=25,it=26,nt=27,rt=28,st=29,ot=30,lt=31,ht=32,dt=852,ft=592,_t=15,ut=!0;a.inflateReset=s,a.inflateReset2=o,a.inflateResetKeep=r,a.inflateInit=function(t){return l(t,_t)},a.inflateInit2=l,a.inflate=function(t,e){var a,n,r,s,o,l,f,_,dt,ft,_t,ut,ct,bt,gt,mt,wt,pt,vt,kt,yt,xt,zt,Bt,St=0,Et=new u.Buf8(4),At=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!t||!t.state||!t.output||!t.input&&0!==t.avail_in)return E;(a=t.state).mode===M&&(a.mode=P),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,ft=l,_t=f,xt=z;t:for(;;)switch(a.mode){case N:if(0===a.wrap){a.mode=P;break}for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(2&a.wrap&&35615===_){a.check=0,Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0),_=0,dt=0,a.mode=O;break}if(a.flags=0,a.head&&(a.head.done=!1),!(1&a.wrap)||(((255&_)<<8)+(_>>8))%31){t.msg="incorrect header check",a.mode=ot;break}if((15&_)!==C){t.msg="unknown compression method",a.mode=ot;break}if(_>>>=4,dt-=4,yt=8+(15&_),0===a.wbits)a.wbits=yt;else if(yt>a.wbits){t.msg="invalid window size",a.mode=ot;break}a.dmax=1<<yt,t.adler=a.check=1,a.mode=512&_?j:M,_=0,dt=0;break;case O:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.flags=_,(255&a.flags)!==C){t.msg="unknown compression method",a.mode=ot;break}if(57344&a.flags){t.msg="unknown header flags set",a.mode=ot;break}a.head&&(a.head.text=_>>8&1),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=D;case D:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.time=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,Et[2]=_>>>16&255,Et[3]=_>>>24&255,a.check=b(a.check,Et,4,0)),_=0,dt=0,a.mode=I;case I:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.xflags=255&_,a.head.os=_>>8),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=U;case U:if(1024&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length=_,a.head&&(a.head.extra_len=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0}else a.head&&(a.head.extra=null);a.mode=T;case T:if(1024&a.flags&&((ut=a.length)>l&&(ut=l),ut&&(a.head&&(yt=a.head.extra_len-a.length,a.head.extra||(a.head.extra=new Array(a.head.extra_len)),u.arraySet(a.head.extra,n,s,ut,yt)),512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,a.length-=ut),a.length))break t;a.length=0,a.mode=F;case F:if(2048&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.name+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.name=null);a.length=0,a.mode=L;case L:if(4096&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.comment+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.comment=null);a.mode=H;case H:if(512&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(65535&a.check)){t.msg="header crc mismatch",a.mode=ot;break}_=0,dt=0}a.head&&(a.head.hcrc=a.flags>>9&1,a.head.done=!0),t.adler=a.check=0,a.mode=M;break;case j:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}t.adler=a.check=i(_),_=0,dt=0,a.mode=K;case K:if(0===a.havedict)return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,S;t.adler=a.check=1,a.mode=M;case M:if(e===y||e===x)break t;case P:if(a.last){_>>>=7&dt,dt-=7&dt,a.mode=nt;break}for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}switch(a.last=1&_,_>>>=1,dt-=1,3&_){case 0:a.mode=Y;break;case 1:if(h(a),a.mode=Q,e===x){_>>>=2,dt-=2;break t}break;case 2:a.mode=X;break;case 3:t.msg="invalid block type",a.mode=ot}_>>>=2,dt-=2;break;case Y:for(_>>>=7&dt,dt-=7&dt;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if((65535&_)!=(_>>>16^65535)){t.msg="invalid stored block lengths",a.mode=ot;break}if(a.length=65535&_,_=0,dt=0,a.mode=q,e===x)break t;case q:a.mode=G;case G:if(ut=a.length){if(ut>l&&(ut=l),ut>f&&(ut=f),0===ut)break t;u.arraySet(r,n,s,ut,o),l-=ut,s+=ut,f-=ut,o+=ut,a.length-=ut;break}a.mode=M;break;case X:for(;dt<14;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.nlen=257+(31&_),_>>>=5,dt-=5,a.ndist=1+(31&_),_>>>=5,dt-=5,a.ncode=4+(15&_),_>>>=4,dt-=4,a.nlen>286||a.ndist>30){t.msg="too many length or distance symbols",a.mode=ot;break}a.have=0,a.mode=W;case W:for(;a.have<a.ncode;){for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.lens[At[a.have++]]=7&_,_>>>=3,dt-=3}for(;a.have<19;)a.lens[At[a.have++]]=0;if(a.lencode=a.lendyn,a.lenbits=7,zt={bits:a.lenbits},xt=m(w,a.lens,0,19,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid code lengths set",a.mode=ot;break}a.have=0,a.mode=J;case J:for(;a.have<a.nlen+a.ndist;){for(;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(wt<16)_>>>=gt,dt-=gt,a.lens[a.have++]=wt;else{if(16===wt){for(Bt=gt+2;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_>>>=gt,dt-=gt,0===a.have){t.msg="invalid bit length repeat",a.mode=ot;break}yt=a.lens[a.have-1],ut=3+(3&_),_>>>=2,dt-=2}else if(17===wt){for(Bt=gt+3;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=3+(7&(_>>>=gt)),_>>>=3,dt-=3}else{for(Bt=gt+7;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=11+(127&(_>>>=gt)),_>>>=7,dt-=7}if(a.have+ut>a.nlen+a.ndist){t.msg="invalid bit length repeat",a.mode=ot;break}for(;ut--;)a.lens[a.have++]=yt}}if(a.mode===ot)break;if(0===a.lens[256]){t.msg="invalid code -- missing end-of-block",a.mode=ot;break}if(a.lenbits=9,zt={bits:a.lenbits},xt=m(p,a.lens,0,a.nlen,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid literal/lengths set",a.mode=ot;break}if(a.distbits=6,a.distcode=a.distdyn,zt={bits:a.distbits},xt=m(v,a.lens,a.nlen,a.ndist,a.distcode,0,a.work,zt),a.distbits=zt.bits,xt){t.msg="invalid distances set",a.mode=ot;break}if(a.mode=Q,e===x)break t;case Q:a.mode=V;case V:if(l>=6&&f>=258){t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,g(t,_t),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,a.mode===M&&(a.back=-1);break}for(a.back=0;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(mt&&0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.lencode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,a.length=wt,0===mt){a.mode=it;break}if(32&mt){a.back=-1,a.mode=M;break}if(64&mt){t.msg="invalid literal/length code",a.mode=ot;break}a.extra=15&mt,a.mode=$;case $:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}a.was=a.length,a.mode=tt;case tt:for(;St=a.distcode[_&(1<<a.distbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.distcode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,64&mt){t.msg="invalid distance code",a.mode=ot;break}a.offset=wt,a.extra=15&mt,a.mode=et;case et:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.offset+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}if(a.offset>a.dmax){t.msg="invalid distance too far back",a.mode=ot;break}a.mode=at;case at:if(0===f)break t;if(ut=_t-f,a.offset>ut){if((ut=a.offset-ut)>a.whave&&a.sane){t.msg="invalid distance too far back",a.mode=ot;break}ut>a.wnext?(ut-=a.wnext,ct=a.wsize-ut):ct=a.wnext-ut,ut>a.length&&(ut=a.length),bt=a.window}else bt=r,ct=o-a.offset,ut=a.length;ut>f&&(ut=f),f-=ut,a.length-=ut;do{r[o++]=bt[ct++]}while(--ut);0===a.length&&(a.mode=V);break;case it:if(0===f)break t;r[o++]=a.length,f--,a.mode=V;break;case nt:if(a.wrap){for(;dt<32;){if(0===l)break t;l--,_|=n[s++]<<dt,dt+=8}if(_t-=f,t.total_out+=_t,a.total+=_t,_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,o-_t):c(a.check,r,_t,o-_t)),_t=f,(a.flags?_:i(_))!==a.check){t.msg="incorrect data check",a.mode=ot;break}_=0,dt=0}a.mode=rt;case rt:if(a.wrap&&a.flags){for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(4294967295&a.total)){t.msg="incorrect length check",a.mode=ot;break}_=0,dt=0}a.mode=st;case st:xt=B;break t;case ot:xt=A;break t;case lt:return Z;case ht:default:return E}return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,(a.wsize||_t!==t.avail_out&&a.mode<ot&&(a.mode<nt||e!==k))&&d(t,t.output,t.next_out,_t-t.avail_out)?(a.mode=lt,Z):(ft-=t.avail_in,_t-=t.avail_out,t.total_in+=ft,t.total_out+=_t,a.total+=_t,a.wrap&&_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,t.next_out-_t):c(a.check,r,_t,t.next_out-_t)),t.data_type=a.bits+(a.last?64:0)+(a.mode===M?128:0)+(a.mode===Q||a.mode===q?256:0),(0===ft&&0===_t||e===k)&&xt===z&&(xt=R),xt)},a.inflateEnd=function(t){if(!t||!t.state)return E;var e=t.state;return e.window&&(e.window=null),t.state=null,z},a.inflateGetHeader=function(t,e){var a;return t&&t.state?0==(2&(a=t.state).wrap)?E:(a.head=e,e.done=!1,z):E},a.inflateSetDictionary=function(t,e){var a,i,n=e.length;return t&&t.state?0!==(a=t.state).wrap&&a.mode!==K?E:a.mode===K&&(i=1,(i=c(i,e,n,0))!==a.check)?A:d(t,e,n,n)?(a.mode=lt,Z):(a.havedict=1,z):E},a.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./inffast":10,"./inftrees":12}],12:[function(t,e,a){"use strict";var i=t("../utils/common"),n=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],r=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],s=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],o=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];e.exports=function(t,e,a,l,h,d,f,_){var u,c,b,g,m,w,p,v,k,y=_.bits,x=0,z=0,B=0,S=0,E=0,A=0,Z=0,R=0,C=0,N=0,O=null,D=0,I=new i.Buf16(16),U=new i.Buf16(16),T=null,F=0;for(x=0;x<=15;x++)I[x]=0;for(z=0;z<l;z++)I[e[a+z]]++;for(E=y,S=15;S>=1&&0===I[S];S--);if(E>S&&(E=S),0===S)return h[d++]=20971520,h[d++]=20971520,_.bits=1,0;for(B=1;B<S&&0===I[B];B++);for(E<B&&(E=B),R=1,x=1;x<=15;x++)if(R<<=1,(R-=I[x])<0)return-1;if(R>0&&(0===t||1!==S))return-1;for(U[1]=0,x=1;x<15;x++)U[x+1]=U[x]+I[x];for(z=0;z<l;z++)0!==e[a+z]&&(f[U[e[a+z]]++]=z);if(0===t?(O=T=f,w=19):1===t?(O=n,D-=257,T=r,F-=257,w=256):(O=s,T=o,w=-1),N=0,z=0,x=B,m=d,A=E,Z=0,b=-1,C=1<<E,g=C-1,1===t&&C>852||2===t&&C>592)return 1;for(;;){p=x-Z,f[z]<w?(v=0,k=f[z]):f[z]>w?(v=T[F+f[z]],k=O[D+f[z]]):(v=96,k=0),u=1<<x-Z,B=c=1<<A;do{h[m+(N>>Z)+(c-=u)]=p<<24|v<<16|k|0}while(0!==c);for(u=1<<x-1;N&u;)u>>=1;if(0!==u?(N&=u-1,N+=u):N=0,z++,0==--I[x]){if(x===S)break;x=e[a+f[z]]}if(x>E&&(N&g)!==b){for(0===Z&&(Z=E),m+=B,R=1<<(A=x-Z);A+Z<S&&!((R-=I[A+Z])<=0);)A++,R<<=1;if(C+=1<<A,1===t&&C>852||2===t&&C>592)return 1;h[b=N&g]=E<<24|A<<16|m-d|0}}return 0!==N&&(h[m+N]=x-Z<<24|64<<16|0),_.bits=E,0}},{"../utils/common":3}],13:[function(t,e,a){"use strict";e.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],14:[function(t,e,a){"use strict";function i(t){for(var e=t.length;--e>=0;)t[e]=0}function n(t,e,a,i,n){this.static_tree=t,this.extra_bits=e,this.extra_base=a,this.elems=i,this.max_length=n,this.has_stree=t&&t.length}function r(t,e){this.dyn_tree=t,this.max_code=0,this.stat_desc=e}function s(t){return t<256?et[t]:et[256+(t>>>7)]}function o(t,e){t.pending_buf[t.pending++]=255&e,t.pending_buf[t.pending++]=e>>>8&255}function l(t,e,a){t.bi_valid>M-a?(t.bi_buf|=e<<t.bi_valid&65535,o(t,t.bi_buf),t.bi_buf=e>>M-t.bi_valid,t.bi_valid+=a-M):(t.bi_buf|=e<<t.bi_valid&65535,t.bi_valid+=a)}function h(t,e,a){l(t,a[2*e],a[2*e+1])}function d(t,e){var a=0;do{a|=1&t,t>>>=1,a<<=1}while(--e>0);return a>>>1}function f(t){16===t.bi_valid?(o(t,t.bi_buf),t.bi_buf=0,t.bi_valid=0):t.bi_valid>=8&&(t.pending_buf[t.pending++]=255&t.bi_buf,t.bi_buf>>=8,t.bi_valid-=8)}function _(t,e){var a,i,n,r,s,o,l=e.dyn_tree,h=e.max_code,d=e.stat_desc.static_tree,f=e.stat_desc.has_stree,_=e.stat_desc.extra_bits,u=e.stat_desc.extra_base,c=e.stat_desc.max_length,b=0;for(r=0;r<=K;r++)t.bl_count[r]=0;for(l[2*t.heap[t.heap_max]+1]=0,a=t.heap_max+1;a<j;a++)(r=l[2*l[2*(i=t.heap[a])+1]+1]+1)>c&&(r=c,b++),l[2*i+1]=r,i>h||(t.bl_count[r]++,s=0,i>=u&&(s=_[i-u]),o=l[2*i],t.opt_len+=o*(r+s),f&&(t.static_len+=o*(d[2*i+1]+s)));if(0!==b){do{for(r=c-1;0===t.bl_count[r];)r--;t.bl_count[r]--,t.bl_count[r+1]+=2,t.bl_count[c]--,b-=2}while(b>0);for(r=c;0!==r;r--)for(i=t.bl_count[r];0!==i;)(n=t.heap[--a])>h||(l[2*n+1]!==r&&(t.opt_len+=(r-l[2*n+1])*l[2*n],l[2*n+1]=r),i--)}}function u(t,e,a){var i,n,r=new Array(K+1),s=0;for(i=1;i<=K;i++)r[i]=s=s+a[i-1]<<1;for(n=0;n<=e;n++){var o=t[2*n+1];0!==o&&(t[2*n]=d(r[o]++,o))}}function c(){var t,e,a,i,r,s=new Array(K+1);for(a=0,i=0;i<U-1;i++)for(it[i]=a,t=0;t<1<<W[i];t++)at[a++]=i;for(at[a-1]=i,r=0,i=0;i<16;i++)for(nt[i]=r,t=0;t<1<<J[i];t++)et[r++]=i;for(r>>=7;i<L;i++)for(nt[i]=r<<7,t=0;t<1<<J[i]-7;t++)et[256+r++]=i;for(e=0;e<=K;e++)s[e]=0;for(t=0;t<=143;)$[2*t+1]=8,t++,s[8]++;for(;t<=255;)$[2*t+1]=9,t++,s[9]++;for(;t<=279;)$[2*t+1]=7,t++,s[7]++;for(;t<=287;)$[2*t+1]=8,t++,s[8]++;for(u($,F+1,s),t=0;t<L;t++)tt[2*t+1]=5,tt[2*t]=d(t,5);rt=new n($,W,T+1,F,K),st=new n(tt,J,0,L,K),ot=new n(new Array(0),Q,0,H,P)}function b(t){var e;for(e=0;e<F;e++)t.dyn_ltree[2*e]=0;for(e=0;e<L;e++)t.dyn_dtree[2*e]=0;for(e=0;e<H;e++)t.bl_tree[2*e]=0;t.dyn_ltree[2*Y]=1,t.opt_len=t.static_len=0,t.last_lit=t.matches=0}function g(t){t.bi_valid>8?o(t,t.bi_buf):t.bi_valid>0&&(t.pending_buf[t.pending++]=t.bi_buf),t.bi_buf=0,t.bi_valid=0}function m(t,e,a,i){g(t),i&&(o(t,a),o(t,~a)),A.arraySet(t.pending_buf,t.window,e,a,t.pending),t.pending+=a}function w(t,e,a,i){var n=2*e,r=2*a;return t[n]<t[r]||t[n]===t[r]&&i[e]<=i[a]}function p(t,e,a){for(var i=t.heap[a],n=a<<1;n<=t.heap_len&&(n<t.heap_len&&w(e,t.heap[n+1],t.heap[n],t.depth)&&n++,!w(e,i,t.heap[n],t.depth));)t.heap[a]=t.heap[n],a=n,n<<=1;t.heap[a]=i}function v(t,e,a){var i,n,r,o,d=0;if(0!==t.last_lit)do{i=t.pending_buf[t.d_buf+2*d]<<8|t.pending_buf[t.d_buf+2*d+1],n=t.pending_buf[t.l_buf+d],d++,0===i?h(t,n,e):(h(t,(r=at[n])+T+1,e),0!==(o=W[r])&&l(t,n-=it[r],o),h(t,r=s(--i),a),0!==(o=J[r])&&l(t,i-=nt[r],o))}while(d<t.last_lit);h(t,Y,e)}function k(t,e){var a,i,n,r=e.dyn_tree,s=e.stat_desc.static_tree,o=e.stat_desc.has_stree,l=e.stat_desc.elems,h=-1;for(t.heap_len=0,t.heap_max=j,a=0;a<l;a++)0!==r[2*a]?(t.heap[++t.heap_len]=h=a,t.depth[a]=0):r[2*a+1]=0;for(;t.heap_len<2;)r[2*(n=t.heap[++t.heap_len]=h<2?++h:0)]=1,t.depth[n]=0,t.opt_len--,o&&(t.static_len-=s[2*n+1]);for(e.max_code=h,a=t.heap_len>>1;a>=1;a--)p(t,r,a);n=l;do{a=t.heap[1],t.heap[1]=t.heap[t.heap_len--],p(t,r,1),i=t.heap[1],t.heap[--t.heap_max]=a,t.heap[--t.heap_max]=i,r[2*n]=r[2*a]+r[2*i],t.depth[n]=(t.depth[a]>=t.depth[i]?t.depth[a]:t.depth[i])+1,r[2*a+1]=r[2*i+1]=n,t.heap[1]=n++,p(t,r,1)}while(t.heap_len>=2);t.heap[--t.heap_max]=t.heap[1],_(t,e),u(r,h,t.bl_count)}function y(t,e,a){var i,n,r=-1,s=e[1],o=0,l=7,h=4;for(0===s&&(l=138,h=3),e[2*(a+1)+1]=65535,i=0;i<=a;i++)n=s,s=e[2*(i+1)+1],++o<l&&n===s||(o<h?t.bl_tree[2*n]+=o:0!==n?(n!==r&&t.bl_tree[2*n]++,t.bl_tree[2*q]++):o<=10?t.bl_tree[2*G]++:t.bl_tree[2*X]++,o=0,r=n,0===s?(l=138,h=3):n===s?(l=6,h=3):(l=7,h=4))}function x(t,e,a){var i,n,r=-1,s=e[1],o=0,d=7,f=4;for(0===s&&(d=138,f=3),i=0;i<=a;i++)if(n=s,s=e[2*(i+1)+1],!(++o<d&&n===s)){if(o<f)do{h(t,n,t.bl_tree)}while(0!=--o);else 0!==n?(n!==r&&(h(t,n,t.bl_tree),o--),h(t,q,t.bl_tree),l(t,o-3,2)):o<=10?(h(t,G,t.bl_tree),l(t,o-3,3)):(h(t,X,t.bl_tree),l(t,o-11,7));o=0,r=n,0===s?(d=138,f=3):n===s?(d=6,f=3):(d=7,f=4)}}function z(t){var e;for(y(t,t.dyn_ltree,t.l_desc.max_code),y(t,t.dyn_dtree,t.d_desc.max_code),k(t,t.bl_desc),e=H-1;e>=3&&0===t.bl_tree[2*V[e]+1];e--);return t.opt_len+=3*(e+1)+5+5+4,e}function B(t,e,a,i){var n;for(l(t,e-257,5),l(t,a-1,5),l(t,i-4,4),n=0;n<i;n++)l(t,t.bl_tree[2*V[n]+1],3);x(t,t.dyn_ltree,e-1),x(t,t.dyn_dtree,a-1)}function S(t){var e,a=4093624447;for(e=0;e<=31;e++,a>>>=1)if(1&a&&0!==t.dyn_ltree[2*e])return R;if(0!==t.dyn_ltree[18]||0!==t.dyn_ltree[20]||0!==t.dyn_ltree[26])return C;for(e=32;e<T;e++)if(0!==t.dyn_ltree[2*e])return C;return R}function E(t,e,a,i){l(t,(O<<1)+(i?1:0),3),m(t,e,a,!0)}var A=t("../utils/common"),Z=4,R=0,C=1,N=2,O=0,D=1,I=2,U=29,T=256,F=T+1+U,L=30,H=19,j=2*F+1,K=15,M=16,P=7,Y=256,q=16,G=17,X=18,W=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],J=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Q=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],V=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],$=new Array(2*(F+2));i($);var tt=new Array(2*L);i(tt);var et=new Array(512);i(et);var at=new Array(256);i(at);var it=new Array(U);i(it);var nt=new Array(L);i(nt);var rt,st,ot,lt=!1;a._tr_init=function(t){lt||(c(),lt=!0),t.l_desc=new r(t.dyn_ltree,rt),t.d_desc=new r(t.dyn_dtree,st),t.bl_desc=new r(t.bl_tree,ot),t.bi_buf=0,t.bi_valid=0,b(t)},a._tr_stored_block=E,a._tr_flush_block=function(t,e,a,i){var n,r,s=0;t.level>0?(t.strm.data_type===N&&(t.strm.data_type=S(t)),k(t,t.l_desc),k(t,t.d_desc),s=z(t),n=t.opt_len+3+7>>>3,(r=t.static_len+3+7>>>3)<=n&&(n=r)):n=r=a+5,a+4<=n&&-1!==e?E(t,e,a,i):t.strategy===Z||r===n?(l(t,(D<<1)+(i?1:0),3),v(t,$,tt)):(l(t,(I<<1)+(i?1:0),3),B(t,t.l_desc.max_code+1,t.d_desc.max_code+1,s+1),v(t,t.dyn_ltree,t.dyn_dtree)),b(t),i&&g(t)},a._tr_tally=function(t,e,a){return t.pending_buf[t.d_buf+2*t.last_lit]=e>>>8&255,t.pending_buf[t.d_buf+2*t.last_lit+1]=255&e,t.pending_buf[t.l_buf+t.last_lit]=255&a,t.last_lit++,0===e?t.dyn_ltree[2*a]++:(t.matches++,e--,t.dyn_ltree[2*(at[a]+T+1)]++,t.dyn_dtree[2*s(e)]++),t.last_lit===t.lit_bufsize-1},a._tr_align=function(t){l(t,D<<1,3),h(t,Y,$),f(t)}},{"../utils/common":3}],15:[function(t,e,a){"use strict";e.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],"/":[function(t,e,a){"use strict";var i={};(0,t("./lib/utils/common").assign)(i,t("./lib/deflate"),t("./lib/inflate"),t("./lib/zlib/constants")),e.exports=i},{"./lib/deflate":1,"./lib/inflate":2,"./lib/utils/common":3,"./lib/zlib/constants":6}]},{},[])("/")}); diff --git a/web/gui/lib/perfect-scrollbar-0.6.15.min.js b/web/gui/lib/perfect-scrollbar-0.6.15.min.js new file mode 100644 index 0000000..7fabff5 --- /dev/null +++ b/web/gui/lib/perfect-scrollbar-0.6.15.min.js @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: MIT +/* perfect-scrollbar v0.6.15 */ +!function t(e,n,r){function o(i,s){if(!n[i]){if(!e[i]){var a="function"==typeof require&&require;if(!s&&a)return a(i,!0);if(l)return l(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var u=n[i]={exports:{}};e[i][0].call(u.exports,function(t){var n=e[i][1][t];return o(n?n:t)},u,u.exports,t,e,n,r)}return n[i].exports}for(var l="function"==typeof require&&require,i=0;i<r.length;i++)o(r[i]);return o}({1:[function(t,e,n){"use strict";var r=t("../main");"function"==typeof define&&define.amd?define(r):(window.PerfectScrollbar=r,"undefined"==typeof window.Ps&&(window.Ps=r))},{"../main":7}],2:[function(t,e,n){"use strict";function r(t,e){var n=t.className.split(" ");n.indexOf(e)<0&&n.push(e),t.className=n.join(" ")}function o(t,e){var n=t.className.split(" "),r=n.indexOf(e);r>=0&&n.splice(r,1),t.className=n.join(" ")}n.add=function(t,e){t.classList?t.classList.add(e):r(t,e)},n.remove=function(t,e){t.classList?t.classList.remove(e):o(t,e)},n.list=function(t){return t.classList?Array.prototype.slice.apply(t.classList):t.className.split(" ")}},{}],3:[function(t,e,n){"use strict";function r(t,e){return window.getComputedStyle(t)[e]}function o(t,e,n){return"number"==typeof n&&(n=n.toString()+"px"),t.style[e]=n,t}function l(t,e){for(var n in e){var r=e[n];"number"==typeof r&&(r=r.toString()+"px"),t.style[n]=r}return t}var i={};i.e=function(t,e){var n=document.createElement(t);return n.className=e,n},i.appendTo=function(t,e){return e.appendChild(t),t},i.css=function(t,e,n){return"object"==typeof e?l(t,e):"undefined"==typeof n?r(t,e):o(t,e,n)},i.matches=function(t,e){return"undefined"!=typeof t.matches?t.matches(e):"undefined"!=typeof t.matchesSelector?t.matchesSelector(e):"undefined"!=typeof t.webkitMatchesSelector?t.webkitMatchesSelector(e):"undefined"!=typeof t.mozMatchesSelector?t.mozMatchesSelector(e):"undefined"!=typeof t.msMatchesSelector?t.msMatchesSelector(e):void 0},i.remove=function(t){"undefined"!=typeof t.remove?t.remove():t.parentNode&&t.parentNode.removeChild(t)},i.queryChildren=function(t,e){return Array.prototype.filter.call(t.childNodes,function(t){return i.matches(t,e)})},e.exports=i},{}],4:[function(t,e,n){"use strict";var r=function(t){this.element=t,this.events={}};r.prototype.bind=function(t,e){"undefined"==typeof this.events[t]&&(this.events[t]=[]),this.events[t].push(e),this.element.addEventListener(t,e,!1)},r.prototype.unbind=function(t,e){var n="undefined"!=typeof e;this.events[t]=this.events[t].filter(function(r){return!(!n||r===e)||(this.element.removeEventListener(t,r,!1),!1)},this)},r.prototype.unbindAll=function(){for(var t in this.events)this.unbind(t)};var o=function(){this.eventElements=[]};o.prototype.eventElement=function(t){var e=this.eventElements.filter(function(e){return e.element===t})[0];return"undefined"==typeof e&&(e=new r(t),this.eventElements.push(e)),e},o.prototype.bind=function(t,e,n){this.eventElement(t).bind(e,n)},o.prototype.unbind=function(t,e,n){this.eventElement(t).unbind(e,n)},o.prototype.unbindAll=function(){for(var t=0;t<this.eventElements.length;t++)this.eventElements[t].unbindAll()},o.prototype.once=function(t,e,n){var r=this.eventElement(t),o=function(t){r.unbind(e,o),n(t)};r.bind(e,o)},e.exports=o},{}],5:[function(t,e,n){"use strict";e.exports=function(){function t(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return function(){return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}}()},{}],6:[function(t,e,n){"use strict";var r=t("./class"),o=t("./dom"),l=n.toInt=function(t){return parseInt(t,10)||0},i=n.clone=function(t){if(t){if(t.constructor===Array)return t.map(i);if("object"==typeof t){var e={};for(var n in t)e[n]=i(t[n]);return e}return t}return null};n.extend=function(t,e){var n=i(t);for(var r in e)n[r]=i(e[r]);return n},n.isEditable=function(t){return o.matches(t,"input,[contenteditable]")||o.matches(t,"select,[contenteditable]")||o.matches(t,"textarea,[contenteditable]")||o.matches(t,"button,[contenteditable]")},n.removePsClasses=function(t){for(var e=r.list(t),n=0;n<e.length;n++){var o=e[n];0===o.indexOf("ps-")&&r.remove(t,o)}},n.outerWidth=function(t){return l(o.css(t,"width"))+l(o.css(t,"paddingLeft"))+l(o.css(t,"paddingRight"))+l(o.css(t,"borderLeftWidth"))+l(o.css(t,"borderRightWidth"))},n.startScrolling=function(t,e){r.add(t,"ps-in-scrolling"),"undefined"!=typeof e?r.add(t,"ps-"+e):(r.add(t,"ps-x"),r.add(t,"ps-y"))},n.stopScrolling=function(t,e){r.remove(t,"ps-in-scrolling"),"undefined"!=typeof e?r.remove(t,"ps-"+e):(r.remove(t,"ps-x"),r.remove(t,"ps-y"))},n.env={isWebKit:"WebkitAppearance"in document.documentElement.style,supportsTouch:"ontouchstart"in window||window.DocumentTouch&&document instanceof window.DocumentTouch,supportsIePointer:null!==window.navigator.msMaxTouchPoints}},{"./class":2,"./dom":3}],7:[function(t,e,n){"use strict";var r=t("./plugin/destroy"),o=t("./plugin/initialize"),l=t("./plugin/update");e.exports={initialize:o,update:l,destroy:r}},{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":21}],8:[function(t,e,n){"use strict";e.exports={handlers:["click-rail","drag-scrollbar","keyboard","wheel","touch"],maxScrollbarLength:null,minScrollbarLength:null,scrollXMarginOffset:0,scrollYMarginOffset:0,suppressScrollX:!1,suppressScrollY:!1,swipePropagation:!0,useBothWheelAxes:!1,wheelPropagation:!1,wheelSpeed:1,theme:"default"}},{}],9:[function(t,e,n){"use strict";var r=t("../lib/helper"),o=t("../lib/dom"),l=t("./instances");e.exports=function(t){var e=l.get(t);e&&(e.event.unbindAll(),o.remove(e.scrollbarX),o.remove(e.scrollbarY),o.remove(e.scrollbarXRail),o.remove(e.scrollbarYRail),r.removePsClasses(t),l.remove(t))}},{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(t,e,n){"use strict";function r(t,e){function n(t){return t.getBoundingClientRect()}var r=function(t){t.stopPropagation()};e.event.bind(e.scrollbarY,"click",r),e.event.bind(e.scrollbarYRail,"click",function(r){var o=r.pageY-window.pageYOffset-n(e.scrollbarYRail).top,s=o>e.scrollbarYTop?1:-1;i(t,"top",t.scrollTop+s*e.containerHeight),l(t),r.stopPropagation()}),e.event.bind(e.scrollbarX,"click",r),e.event.bind(e.scrollbarXRail,"click",function(r){var o=r.pageX-window.pageXOffset-n(e.scrollbarXRail).left,s=o>e.scrollbarXLeft?1:-1;i(t,"left",t.scrollLeft+s*e.containerWidth),l(t),r.stopPropagation()})}var o=t("../instances"),l=t("../update-geometry"),i=t("../update-scroll");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(t,e,n){"use strict";function r(t,e){function n(n){var o=r+n*e.railXRatio,i=Math.max(0,e.scrollbarXRail.getBoundingClientRect().left)+e.railXRatio*(e.railXWidth-e.scrollbarXWidth);o<0?e.scrollbarXLeft=0:o>i?e.scrollbarXLeft=i:e.scrollbarXLeft=o;var s=l.toInt(e.scrollbarXLeft*(e.contentWidth-e.containerWidth)/(e.containerWidth-e.railXRatio*e.scrollbarXWidth))-e.negativeScrollAdjustment;c(t,"left",s)}var r=null,o=null,s=function(e){n(e.pageX-o),a(t),e.stopPropagation(),e.preventDefault()},u=function(){l.stopScrolling(t,"x"),e.event.unbind(e.ownerDocument,"mousemove",s)};e.event.bind(e.scrollbarX,"mousedown",function(n){o=n.pageX,r=l.toInt(i.css(e.scrollbarX,"left"))*e.railXRatio,l.startScrolling(t,"x"),e.event.bind(e.ownerDocument,"mousemove",s),e.event.once(e.ownerDocument,"mouseup",u),n.stopPropagation(),n.preventDefault()})}function o(t,e){function n(n){var o=r+n*e.railYRatio,i=Math.max(0,e.scrollbarYRail.getBoundingClientRect().top)+e.railYRatio*(e.railYHeight-e.scrollbarYHeight);o<0?e.scrollbarYTop=0:o>i?e.scrollbarYTop=i:e.scrollbarYTop=o;var s=l.toInt(e.scrollbarYTop*(e.contentHeight-e.containerHeight)/(e.containerHeight-e.railYRatio*e.scrollbarYHeight));c(t,"top",s)}var r=null,o=null,s=function(e){n(e.pageY-o),a(t),e.stopPropagation(),e.preventDefault()},u=function(){l.stopScrolling(t,"y"),e.event.unbind(e.ownerDocument,"mousemove",s)};e.event.bind(e.scrollbarY,"mousedown",function(n){o=n.pageY,r=l.toInt(i.css(e.scrollbarY,"top"))*e.railYRatio,l.startScrolling(t,"y"),e.event.bind(e.ownerDocument,"mousemove",s),e.event.once(e.ownerDocument,"mouseup",u),n.stopPropagation(),n.preventDefault()})}var l=t("../../lib/helper"),i=t("../../lib/dom"),s=t("../instances"),a=t("../update-geometry"),c=t("../update-scroll");e.exports=function(t){var e=s.get(t);r(t,e),o(t,e)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(t,e,n){"use strict";function r(t,e){function n(n,r){var o=t.scrollTop;if(0===n){if(!e.scrollbarYActive)return!1;if(0===o&&r>0||o>=e.contentHeight-e.containerHeight&&r<0)return!e.settings.wheelPropagation}var l=t.scrollLeft;if(0===r){if(!e.scrollbarXActive)return!1;if(0===l&&n<0||l>=e.contentWidth-e.containerWidth&&n>0)return!e.settings.wheelPropagation}return!0}var r=!1;e.event.bind(t,"mouseenter",function(){r=!0}),e.event.bind(t,"mouseleave",function(){r=!1});var i=!1;e.event.bind(e.ownerDocument,"keydown",function(c){if(!(c.isDefaultPrevented&&c.isDefaultPrevented()||c.defaultPrevented)){var u=l.matches(e.scrollbarX,":focus")||l.matches(e.scrollbarY,":focus");if(r||u){var d=document.activeElement?document.activeElement:e.ownerDocument.activeElement;if(d){if("IFRAME"===d.tagName)d=d.contentDocument.activeElement;else for(;d.shadowRoot;)d=d.shadowRoot.activeElement;if(o.isEditable(d))return}var p=0,f=0;switch(c.which){case 37:p=c.metaKey?-e.contentWidth:c.altKey?-e.containerWidth:-30;break;case 38:f=c.metaKey?e.contentHeight:c.altKey?e.containerHeight:30;break;case 39:p=c.metaKey?e.contentWidth:c.altKey?e.containerWidth:30;break;case 40:f=c.metaKey?-e.contentHeight:c.altKey?-e.containerHeight:-30;break;case 33:f=90;break;case 32:f=c.shiftKey?90:-90;break;case 34:f=-90;break;case 35:f=c.ctrlKey?-e.contentHeight:-e.containerHeight;break;case 36:f=c.ctrlKey?t.scrollTop:e.containerHeight;break;default:return}a(t,"top",t.scrollTop-f),a(t,"left",t.scrollLeft+p),s(t),i=n(p,f),i&&c.preventDefault()}}})}var o=t("../../lib/helper"),l=t("../../lib/dom"),i=t("../instances"),s=t("../update-geometry"),a=t("../update-scroll");e.exports=function(t){var e=i.get(t);r(t,e)}},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(t,e,n){"use strict";function r(t,e){function n(n,r){var o=t.scrollTop;if(0===n){if(!e.scrollbarYActive)return!1;if(0===o&&r>0||o>=e.contentHeight-e.containerHeight&&r<0)return!e.settings.wheelPropagation}var l=t.scrollLeft;if(0===r){if(!e.scrollbarXActive)return!1;if(0===l&&n<0||l>=e.contentWidth-e.containerWidth&&n>0)return!e.settings.wheelPropagation}return!0}function r(t){var e=t.deltaX,n=-1*t.deltaY;return"undefined"!=typeof e&&"undefined"!=typeof n||(e=-1*t.wheelDeltaX/6,n=t.wheelDeltaY/6),t.deltaMode&&1===t.deltaMode&&(e*=10,n*=10),e!==e&&n!==n&&(e=0,n=t.wheelDelta),t.shiftKey?[-n,-e]:[e,n]}function o(e,n){var r=t.querySelector("textarea:hover, select[multiple]:hover, .ps-child:hover");if(r){if(!window.getComputedStyle(r).overflow.match(/(scroll|auto)/))return!1;var o=r.scrollHeight-r.clientHeight;if(o>0&&!(0===r.scrollTop&&n>0||r.scrollTop===o&&n<0))return!0;var l=r.scrollLeft-r.clientWidth;if(l>0&&!(0===r.scrollLeft&&e<0||r.scrollLeft===l&&e>0))return!0}return!1}function s(s){var c=r(s),u=c[0],d=c[1];o(u,d)||(a=!1,e.settings.useBothWheelAxes?e.scrollbarYActive&&!e.scrollbarXActive?(d?i(t,"top",t.scrollTop-d*e.settings.wheelSpeed):i(t,"top",t.scrollTop+u*e.settings.wheelSpeed),a=!0):e.scrollbarXActive&&!e.scrollbarYActive&&(u?i(t,"left",t.scrollLeft+u*e.settings.wheelSpeed):i(t,"left",t.scrollLeft-d*e.settings.wheelSpeed),a=!0):(i(t,"top",t.scrollTop-d*e.settings.wheelSpeed),i(t,"left",t.scrollLeft+u*e.settings.wheelSpeed)),l(t),a=a||n(u,d),a&&(s.stopPropagation(),s.preventDefault()))}var a=!1;"undefined"!=typeof window.onwheel?e.event.bind(t,"wheel",s):"undefined"!=typeof window.onmousewheel&&e.event.bind(t,"mousewheel",s)}var o=t("../instances"),l=t("../update-geometry"),i=t("../update-scroll");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(t,e,n){"use strict";function r(t,e){e.event.bind(t,"scroll",function(){l(t)})}var o=t("../instances"),l=t("../update-geometry");e.exports=function(t){var e=o.get(t);r(t,e)}},{"../instances":18,"../update-geometry":19}],15:[function(t,e,n){"use strict";function r(t,e){function n(){var t=window.getSelection?window.getSelection():document.getSelection?document.getSelection():"";return 0===t.toString().length?null:t.getRangeAt(0).commonAncestorContainer}function r(){c||(c=setInterval(function(){return l.get(t)?(s(t,"top",t.scrollTop+u.top),s(t,"left",t.scrollLeft+u.left),void i(t)):void clearInterval(c)},50))}function a(){c&&(clearInterval(c),c=null),o.stopScrolling(t)}var c=null,u={top:0,left:0},d=!1;e.event.bind(e.ownerDocument,"selectionchange",function(){t.contains(n())?d=!0:(d=!1,a())}),e.event.bind(window,"mouseup",function(){d&&(d=!1,a())}),e.event.bind(window,"keyup",function(){d&&(d=!1,a())}),e.event.bind(window,"mousemove",function(e){if(d){var n={x:e.pageX,y:e.pageY},l={left:t.offsetLeft,right:t.offsetLeft+t.offsetWidth,top:t.offsetTop,bottom:t.offsetTop+t.offsetHeight};n.x<l.left+3?(u.left=-5,o.startScrolling(t,"x")):n.x>l.right-3?(u.left=5,o.startScrolling(t,"x")):u.left=0,n.y<l.top+3?(l.top+3-n.y<5?u.top=-5:u.top=-20,o.startScrolling(t,"y")):n.y>l.bottom-3?(n.y-l.bottom+3<5?u.top=5:u.top=20,o.startScrolling(t,"y")):u.top=0,0===u.top&&0===u.left?a():r()}})}var o=t("../../lib/helper"),l=t("../instances"),i=t("../update-geometry"),s=t("../update-scroll");e.exports=function(t){var e=l.get(t);r(t,e)}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(t,e,n){"use strict";function r(t,e,n,r){function o(n,r){var o=t.scrollTop,l=t.scrollLeft,i=Math.abs(n),s=Math.abs(r);if(s>i){if(r<0&&o===e.contentHeight-e.containerHeight||r>0&&0===o)return!e.settings.swipePropagation}else if(i>s&&(n<0&&l===e.contentWidth-e.containerWidth||n>0&&0===l))return!e.settings.swipePropagation;return!0}function a(e,n){s(t,"top",t.scrollTop-n),s(t,"left",t.scrollLeft-e),i(t)}function c(){w=!0}function u(){w=!1}function d(t){return t.targetTouches?t.targetTouches[0]:t}function p(t){return!(!t.targetTouches||1!==t.targetTouches.length)||!(!t.pointerType||"mouse"===t.pointerType||t.pointerType===t.MSPOINTER_TYPE_MOUSE)}function f(t){if(p(t)){Y=!0;var e=d(t);g.pageX=e.pageX,g.pageY=e.pageY,v=(new Date).getTime(),null!==y&&clearInterval(y),t.stopPropagation()}}function h(t){if(!Y&&e.settings.swipePropagation&&f(t),!w&&Y&&p(t)){var n=d(t),r={pageX:n.pageX,pageY:n.pageY},l=r.pageX-g.pageX,i=r.pageY-g.pageY;a(l,i),g=r;var s=(new Date).getTime(),c=s-v;c>0&&(m.x=l/c,m.y=i/c,v=s),o(l,i)&&(t.stopPropagation(),t.preventDefault())}}function b(){!w&&Y&&(Y=!1,clearInterval(y),y=setInterval(function(){return l.get(t)&&(m.x||m.y)?Math.abs(m.x)<.01&&Math.abs(m.y)<.01?void clearInterval(y):(a(30*m.x,30*m.y),m.x*=.8,void(m.y*=.8)):void clearInterval(y)},10))}var g={},v=0,m={},y=null,w=!1,Y=!1;n&&(e.event.bind(window,"touchstart",c),e.event.bind(window,"touchend",u),e.event.bind(t,"touchstart",f),e.event.bind(t,"touchmove",h),e.event.bind(t,"touchend",b)),r&&(window.PointerEvent?(e.event.bind(window,"pointerdown",c),e.event.bind(window,"pointerup",u),e.event.bind(t,"pointerdown",f),e.event.bind(t,"pointermove",h),e.event.bind(t,"pointerup",b)):window.MSPointerEvent&&(e.event.bind(window,"MSPointerDown",c),e.event.bind(window,"MSPointerUp",u),e.event.bind(t,"MSPointerDown",f),e.event.bind(t,"MSPointerMove",h),e.event.bind(t,"MSPointerUp",b)))}var o=t("../../lib/helper"),l=t("../instances"),i=t("../update-geometry"),s=t("../update-scroll");e.exports=function(t){if(o.env.supportsTouch||o.env.supportsIePointer){var e=l.get(t);r(t,e,o.env.supportsTouch,o.env.supportsIePointer)}}},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(t,e,n){"use strict";var r=t("../lib/helper"),o=t("../lib/class"),l=t("./instances"),i=t("./update-geometry"),s={"click-rail":t("./handler/click-rail"),"drag-scrollbar":t("./handler/drag-scrollbar"),keyboard:t("./handler/keyboard"),wheel:t("./handler/mouse-wheel"),touch:t("./handler/touch"),selection:t("./handler/selection")},a=t("./handler/native-scroll");e.exports=function(t,e){e="object"==typeof e?e:{},o.add(t,"ps-container");var n=l.add(t);n.settings=r.extend(n.settings,e),o.add(t,"ps-theme-"+n.settings.theme),n.settings.handlers.forEach(function(e){s[e](t)}),a(t),i(t)}},{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(t,e,n){"use strict";function r(t){function e(){a.add(t,"ps-focus")}function n(){a.remove(t,"ps-focus")}var r=this;r.settings=s.clone(c),r.containerWidth=null,r.containerHeight=null,r.contentWidth=null,r.contentHeight=null,r.isRtl="rtl"===u.css(t,"direction"),r.isNegativeScroll=function(){var e=t.scrollLeft,n=null;return t.scrollLeft=-1,n=t.scrollLeft<0,t.scrollLeft=e,n}(),r.negativeScrollAdjustment=r.isNegativeScroll?t.scrollWidth-t.clientWidth:0,r.event=new d,r.ownerDocument=t.ownerDocument||document,r.scrollbarXRail=u.appendTo(u.e("div","ps-scrollbar-x-rail"),t),r.scrollbarX=u.appendTo(u.e("div","ps-scrollbar-x"),r.scrollbarXRail),r.scrollbarX.setAttribute("tabindex",0),r.event.bind(r.scrollbarX,"focus",e),r.event.bind(r.scrollbarX,"blur",n),r.scrollbarXActive=null,r.scrollbarXWidth=null,r.scrollbarXLeft=null,r.scrollbarXBottom=s.toInt(u.css(r.scrollbarXRail,"bottom")),r.isScrollbarXUsingBottom=r.scrollbarXBottom===r.scrollbarXBottom,r.scrollbarXTop=r.isScrollbarXUsingBottom?null:s.toInt(u.css(r.scrollbarXRail,"top")),r.railBorderXWidth=s.toInt(u.css(r.scrollbarXRail,"borderLeftWidth"))+s.toInt(u.css(r.scrollbarXRail,"borderRightWidth")),u.css(r.scrollbarXRail,"display","block"),r.railXMarginWidth=s.toInt(u.css(r.scrollbarXRail,"marginLeft"))+s.toInt(u.css(r.scrollbarXRail,"marginRight")),u.css(r.scrollbarXRail,"display",""),r.railXWidth=null,r.railXRatio=null,r.scrollbarYRail=u.appendTo(u.e("div","ps-scrollbar-y-rail"),t),r.scrollbarY=u.appendTo(u.e("div","ps-scrollbar-y"),r.scrollbarYRail),r.scrollbarY.setAttribute("tabindex",0),r.event.bind(r.scrollbarY,"focus",e),r.event.bind(r.scrollbarY,"blur",n),r.scrollbarYActive=null,r.scrollbarYHeight=null,r.scrollbarYTop=null,r.scrollbarYRight=s.toInt(u.css(r.scrollbarYRail,"right")),r.isScrollbarYUsingRight=r.scrollbarYRight===r.scrollbarYRight,r.scrollbarYLeft=r.isScrollbarYUsingRight?null:s.toInt(u.css(r.scrollbarYRail,"left")),r.scrollbarYOuterWidth=r.isRtl?s.outerWidth(r.scrollbarY):null,r.railBorderYWidth=s.toInt(u.css(r.scrollbarYRail,"borderTopWidth"))+s.toInt(u.css(r.scrollbarYRail,"borderBottomWidth")),u.css(r.scrollbarYRail,"display","block"),r.railYMarginHeight=s.toInt(u.css(r.scrollbarYRail,"marginTop"))+s.toInt(u.css(r.scrollbarYRail,"marginBottom")),u.css(r.scrollbarYRail,"display",""),r.railYHeight=null,r.railYRatio=null}function o(t){return t.getAttribute("data-ps-id")}function l(t,e){t.setAttribute("data-ps-id",e)}function i(t){t.removeAttribute("data-ps-id")}var s=t("../lib/helper"),a=t("../lib/class"),c=t("./default-setting"),u=t("../lib/dom"),d=t("../lib/event-manager"),p=t("../lib/guid"),f={};n.add=function(t){var e=p();return l(t,e),f[e]=new r(t),f[e]},n.remove=function(t){delete f[o(t)],i(t)},n.get=function(t){return f[o(t)]}},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(t,e,n){"use strict";function r(t,e){return t.settings.minScrollbarLength&&(e=Math.max(e,t.settings.minScrollbarLength)),t.settings.maxScrollbarLength&&(e=Math.min(e,t.settings.maxScrollbarLength)),e}function o(t,e){var n={width:e.railXWidth};e.isRtl?n.left=e.negativeScrollAdjustment+t.scrollLeft+e.containerWidth-e.contentWidth:n.left=t.scrollLeft,e.isScrollbarXUsingBottom?n.bottom=e.scrollbarXBottom-t.scrollTop:n.top=e.scrollbarXTop+t.scrollTop,s.css(e.scrollbarXRail,n);var r={top:t.scrollTop,height:e.railYHeight};e.isScrollbarYUsingRight?e.isRtl?r.right=e.contentWidth-(e.negativeScrollAdjustment+t.scrollLeft)-e.scrollbarYRight-e.scrollbarYOuterWidth:r.right=e.scrollbarYRight-t.scrollLeft:e.isRtl?r.left=e.negativeScrollAdjustment+t.scrollLeft+2*e.containerWidth-e.contentWidth-e.scrollbarYLeft-e.scrollbarYOuterWidth:r.left=e.scrollbarYLeft+t.scrollLeft,s.css(e.scrollbarYRail,r),s.css(e.scrollbarX,{left:e.scrollbarXLeft,width:e.scrollbarXWidth-e.railBorderXWidth}),s.css(e.scrollbarY,{top:e.scrollbarYTop,height:e.scrollbarYHeight-e.railBorderYWidth})}var l=t("../lib/helper"),i=t("../lib/class"),s=t("../lib/dom"),a=t("./instances"),c=t("./update-scroll");e.exports=function(t){var e=a.get(t);e.containerWidth=t.clientWidth,e.containerHeight=t.clientHeight,e.contentWidth=t.scrollWidth,e.contentHeight=t.scrollHeight;var n;t.contains(e.scrollbarXRail)||(n=s.queryChildren(t,".ps-scrollbar-x-rail"),n.length>0&&n.forEach(function(t){s.remove(t)}),s.appendTo(e.scrollbarXRail,t)),t.contains(e.scrollbarYRail)||(n=s.queryChildren(t,".ps-scrollbar-y-rail"),n.length>0&&n.forEach(function(t){s.remove(t)}),s.appendTo(e.scrollbarYRail,t)),!e.settings.suppressScrollX&&e.containerWidth+e.settings.scrollXMarginOffset<e.contentWidth?(e.scrollbarXActive=!0,e.railXWidth=e.containerWidth-e.railXMarginWidth,e.railXRatio=e.containerWidth/e.railXWidth,e.scrollbarXWidth=r(e,l.toInt(e.railXWidth*e.containerWidth/e.contentWidth)),e.scrollbarXLeft=l.toInt((e.negativeScrollAdjustment+t.scrollLeft)*(e.railXWidth-e.scrollbarXWidth)/(e.contentWidth-e.containerWidth))):e.scrollbarXActive=!1,!e.settings.suppressScrollY&&e.containerHeight+e.settings.scrollYMarginOffset<e.contentHeight?(e.scrollbarYActive=!0,e.railYHeight=e.containerHeight-e.railYMarginHeight,e.railYRatio=e.containerHeight/e.railYHeight,e.scrollbarYHeight=r(e,l.toInt(e.railYHeight*e.containerHeight/e.contentHeight)),e.scrollbarYTop=l.toInt(t.scrollTop*(e.railYHeight-e.scrollbarYHeight)/(e.contentHeight-e.containerHeight))):e.scrollbarYActive=!1,e.scrollbarXLeft>=e.railXWidth-e.scrollbarXWidth&&(e.scrollbarXLeft=e.railXWidth-e.scrollbarXWidth),e.scrollbarYTop>=e.railYHeight-e.scrollbarYHeight&&(e.scrollbarYTop=e.railYHeight-e.scrollbarYHeight),o(t,e),e.scrollbarXActive?i.add(t,"ps-active-x"):(i.remove(t,"ps-active-x"),e.scrollbarXWidth=0,e.scrollbarXLeft=0,c(t,"left",0)),e.scrollbarYActive?i.add(t,"ps-active-y"):(i.remove(t,"ps-active-y"),e.scrollbarYHeight=0,e.scrollbarYTop=0,c(t,"top",0))}},{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(t,e,n){"use strict";var r,o,l=t("./instances"),i=function(t){var e=document.createEvent("Event");return e.initEvent(t,!0,!0),e};e.exports=function(t,e,n){if("undefined"==typeof t)throw"You must provide an element to the update-scroll function";if("undefined"==typeof e)throw"You must provide an axis to the update-scroll function";if("undefined"==typeof n)throw"You must provide a value to the update-scroll function";"top"===e&&n<=0&&(t.scrollTop=n=0,t.dispatchEvent(i("ps-y-reach-start"))),"left"===e&&n<=0&&(t.scrollLeft=n=0,t.dispatchEvent(i("ps-x-reach-start")));var s=l.get(t);"top"===e&&n>=s.contentHeight-s.containerHeight&&(n=s.contentHeight-s.containerHeight,n-t.scrollTop<=1?n=t.scrollTop:t.scrollTop=n,t.dispatchEvent(i("ps-y-reach-end"))),"left"===e&&n>=s.contentWidth-s.containerWidth&&(n=s.contentWidth-s.containerWidth,n-t.scrollLeft<=1?n=t.scrollLeft:t.scrollLeft=n,t.dispatchEvent(i("ps-x-reach-end"))),r||(r=t.scrollTop),o||(o=t.scrollLeft),"top"===e&&n<r&&t.dispatchEvent(i("ps-scroll-up")),"top"===e&&n>r&&t.dispatchEvent(i("ps-scroll-down")),"left"===e&&n<o&&t.dispatchEvent(i("ps-scroll-left")),"left"===e&&n>o&&t.dispatchEvent(i("ps-scroll-right")),"top"===e&&(t.scrollTop=r=n,t.dispatchEvent(i("ps-scroll-y"))),"left"===e&&(t.scrollLeft=o=n,t.dispatchEvent(i("ps-scroll-x")))}},{"./instances":18}],21:[function(t,e,n){"use strict";var r=t("../lib/helper"),o=t("../lib/dom"),l=t("./instances"),i=t("./update-geometry"),s=t("./update-scroll");e.exports=function(t){var e=l.get(t);e&&(e.negativeScrollAdjustment=e.isNegativeScroll?t.scrollWidth-t.clientWidth:0,o.css(e.scrollbarXRail,"display","block"),o.css(e.scrollbarYRail,"display","block"),e.railXMarginWidth=r.toInt(o.css(e.scrollbarXRail,"marginLeft"))+r.toInt(o.css(e.scrollbarXRail,"marginRight")),e.railYMarginHeight=r.toInt(o.css(e.scrollbarYRail,"marginTop"))+r.toInt(o.css(e.scrollbarYRail,"marginBottom")),o.css(e.scrollbarXRail,"display","none"),o.css(e.scrollbarYRail,"display","none"),i(t),s(t,"top",t.scrollTop),s(t,"left",t.scrollLeft),o.css(e.scrollbarXRail,"display",""),o.css(e.scrollbarYRail,"display",""))}},{"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-geometry":19,"./update-scroll":20}]},{},[1]); diff --git a/web/gui/lib/tableExport-1.6.0.min.js b/web/gui/lib/tableExport-1.6.0.min.js new file mode 100644 index 0000000..4841309 --- /dev/null +++ b/web/gui/lib/tableExport-1.6.0.min.js @@ -0,0 +1,55 @@ +/*
+ tableExport.jquery.plugin
+
+ Copyright (c) 2015,2016 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
+ Original work Copyright (c) 2014 Giri Raj, https://github.com/kayalshri/
+
+ Licensed under the MIT License, http://opensource.org/licenses/mit-license
+
+ SPDX-License-Identifier: MIT
+*/
+(function(b){b.fn.extend({tableExport:function(q){function R(d){var a=[];b(d).find("thead").first().find("th").each(function(d,f){void 0!==b(f).attr("data-field")?a[d]=b(f).attr("data-field"):a[d]=d.toString()});return a}function w(d,g,e,f,k){if(-1==b.inArray(e,a.ignoreRow)&&-1==b.inArray(e-f,a.ignoreRow)){var B=b(d).filter(function(){return"none"!=b(this).data("tableexport-display")&&(b(this).is(":visible")||"always"==b(this).data("tableexport-display")||"always"==b(this).closest("table").data("tableexport-display"))}).find(g),
+F=0;B.each(function(d){if("always"==b(this).data("tableexport-display")||"none"!=b(this).css("display")&&"hidden"!=b(this).css("visibility")&&"none"!=b(this).data("tableexport-display")){var g=d,f=!1;0<a.ignoreColumn.length&&("string"==typeof a.ignoreColumn[0]?I.length>g&&"undefined"!=typeof I[g]&&-1!=b.inArray(I[g],a.ignoreColumn)&&(f=!0):"number"!=typeof a.ignoreColumn[0]||-1==b.inArray(g,a.ignoreColumn)&&-1==b.inArray(g-B.length,a.ignoreColumn)||(f=!0));if(0==f&&"function"===typeof k){var f=0,
+h,l=0;if("undefined"!=typeof x[e]&&0<x[e].length)for(g=0;g<=d;g++)"undefined"!=typeof x[e][g]&&(k(null,e,g),delete x[e][g],d++);b(this).is("[colspan]")&&(f=parseInt(b(this).attr("colspan")),F+=0<f?f-1:0);b(this).is("[rowspan]")&&(l=parseInt(b(this).attr("rowspan")));k(this,e,d);for(g=0;g<f-1;g++)k(null,e,d+g);if(l)for(h=1;h<l;h++)for("undefined"==typeof x[e+h]&&(x[e+h]=[]),x[e+h][d+F]="",g=1;g<f;g++)x[e+h][d+F-g]=""}}});if("undefined"!=typeof x[e]&&0<x[e].length)for(c=0;c<=x[e].length;c++)"undefined"!=
+typeof x[e][c]&&(k(null,e,c),delete x[e][c])}}function Y(d){!0===a.consoleLog&&console.log(d.output());if("string"===a.outputMode)return d.output();if("base64"===a.outputMode)return G(d.output());try{var g=d.output("blob");saveAs(g,a.fileName+".pdf")}catch(e){C(a.fileName+".pdf","data:application/pdf;base64,",d.output())}}function Z(d,a,e){var f=0;"undefined"!=typeof e&&(f=e.colspan);if(0<=f){for(var k=d.width,b=d.textPos.x,F=a.table.columns.indexOf(a.column),h=1;h<f;h++)k+=a.table.columns[F+h].width;
+1<f&&("right"===d.styles.halign?b=d.textPos.x+k-d.width:"center"===d.styles.halign&&(b=d.textPos.x+(k-d.width)/2));d.width=k;d.textPos.x=b;"undefined"!=typeof e&&1<e.rowspan&&(d.height*=e.rowspan);if("middle"===d.styles.valign||"bottom"===d.styles.valign)e=("string"===typeof d.text?d.text.split(/\r\n|\r|\n/g):d.text).length||1,2<e&&(d.textPos.y-=(2-1.15)/2*a.row.styles.fontSize*(e-2)/3);return!0}return!1}function aa(d,g,e){g.each(function(){var g=b(this).children();if(b(this).is("div")){var k=M(D(this,
+"background-color"),[255,255,255]),B=M(D(this,"border-top-color"),[0,0,0]),F=N(this,"border-top-width",a.jspdf.unit),h=this.getBoundingClientRect(),l=this.offsetLeft*e.dw,m=this.offsetTop*e.dh,n=h.width*e.dw,h=h.height*e.dh;e.doc.setDrawColor.apply(void 0,B);e.doc.setFillColor.apply(void 0,k);e.doc.setLineWidth(F);e.doc.rect(d.x+l,d.y+m,n,h,F?"FD":"F")}"undefined"!=typeof g&&0<g.length&&aa(d,g,e)})}function S(d,a,e){return d.replace(new RegExp(a.replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),
+e)}function fa(d){d=S(d||"0",a.numbers.html.decimalMark,".");d=S(d,a.numbers.html.thousandsSeparator,"");return"number"===typeof d||!1!==jQuery.isNumeric(d)?d:!1}function v(d,g,e){var f="";if(null!=d){d=b(d);var k;k=d[0].hasAttribute("data-tableexport-value")?d.data("tableexport-value"):d.html();"function"===typeof a.onCellHtmlData&&(k=a.onCellHtmlData(d,g,e,k));if(!0===a.htmlContent)f=b.trim(k);else{var B=k.replace(/\n/g,"\u2028").replace(/<br\s*[\/]?>/gi,"\u2060");k=b("<div/>").html(B).contents();
+B="";b.each(k.text().split("\u2028"),function(d,a){0<d&&(B+=" ");B+=b.trim(a)});b.each(B.split("\u2060"),function(d,a){0<d&&(f+="\n");f+=b.trim(a).replace(/\u00AD/g,"")});if(a.numbers.html.decimalMark!=a.numbers.output.decimalMark||a.numbers.html.thousandsSeparator!=a.numbers.output.thousandsSeparator)if(k=fa(f),!1!==k){var h=(""+k).split(".");1==h.length&&(h[1]="");var l=3<h[0].length?h[0].length%3:0,f=(0>k?"-":"")+(a.numbers.output.thousandsSeparator?(l?h[0].substr(0,l)+a.numbers.output.thousandsSeparator:
+"")+h[0].substr(l).replace(/(\d{3})(?=\d)/g,"$1"+a.numbers.output.thousandsSeparator):h[0])+(h[1].length?a.numbers.output.decimalMark+h[1]:"")}}!0===a.escape&&(f=escape(f));"function"===typeof a.onCellData&&(f=a.onCellData(d,g,e,f))}return f}function ga(d,a,e){return a+"-"+e.toLowerCase()}function M(d,a){var e=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(d),f=a;e&&(f=[parseInt(e[1]),parseInt(e[2]),parseInt(e[3])]);return f}function ba(d){var a=D(d,"text-align"),e=D(d,"font-weight"),f=D(d,"font-style"),
+k="";"start"==a&&(a="rtl"==D(d,"direction")?"right":"left");700<=e&&(k="bold");"italic"==f&&(k+=f);""==k&&(k="normal");a={style:{align:a,bcolor:M(D(d,"background-color"),[255,255,255]),color:M(D(d,"color"),[0,0,0]),fstyle:k},colspan:parseInt(b(d).attr("colspan"))||0,rowspan:parseInt(b(d).attr("rowspan"))||0};null!==d&&(d=d.getBoundingClientRect(),a.rect={width:d.width,height:d.height});return a}function D(d,a){try{return window.getComputedStyle?(a=a.replace(/([a-z])([A-Z])/,ga),window.getComputedStyle(d,
+null).getPropertyValue(a)):d.currentStyle?d.currentStyle[a]:d.style[a]}catch(e){}return""}function N(a,g,e){g=D(a,g).match(/\d+/);if(null!==g){g=g[0];a=a.parentElement;var f=document.createElement("div");f.style.overflow="hidden";f.style.visibility="hidden";a.appendChild(f);f.style.width=100+e;e=100/f.offsetWidth;a.removeChild(f);return g*e}return 0}function T(){if(!(this instanceof T))return new T;this.SheetNames=[];this.Sheets={}}function ha(a){for(var g=new ArrayBuffer(a.length),e=new Uint8Array(g),
+f=0;f!=a.length;++f)e[f]=a.charCodeAt(f)&255;return g}function ia(a){for(var g={},e={s:{c:1E7,r:1E7},e:{c:0,r:0}},f=0;f!=a.length;++f)for(var k=0;k!=a[f].length;++k){e.s.r>f&&(e.s.r=f);e.s.c>k&&(e.s.c=k);e.e.r<f&&(e.e.r=f);e.e.c<k&&(e.e.c=k);var b={v:a[f][k]};if(null!=b.v){var h=XLSX.utils.encode_cell({c:k,r:f});"number"===typeof b.v?b.t="n":"boolean"===typeof b.v?b.t="b":b.v instanceof Date?(b.t="n",b.z=XLSX.SSF._table[14],b.v=datenum(b.v)):b.t="s";g[h]=b}}1E7>e.s.c&&(g["!ref"]=XLSX.utils.encode_range(e));
+return g}function C(a,g,e){var f=window.navigator.userAgent;if(0<f.indexOf("MSIE ")||f.match(/Trident.*rv\:11\./)){if(g=document.createElement("iframe"))document.body.appendChild(g),g.setAttribute("style","display:none"),g.contentDocument.open("txt/html","replace"),g.contentDocument.write(e),g.contentDocument.close(),g.focus(),g.contentDocument.execCommand("SaveAs",!0,a),document.body.removeChild(g)}else if(f=document.createElement("a")){f.style.display="none";f.download=a;0<=g.toLowerCase().indexOf("base64,")?
+f.href=g+G(e):f.href=g+encodeURIComponent(e);document.body.appendChild(f);if(document.createEvent)null==O&&(O=document.createEvent("MouseEvents")),O.initEvent("click",!0,!1),f.dispatchEvent(O);else if(document.createEventObject)f.fireEvent("onclick");else if("function"==typeof f.onclick)f.onclick();document.body.removeChild(f)}}function G(a){var g="",e,f,k,b,h,l,m=0;a=a.replace(/\x0d\x0a/g,"\n");f="";for(k=0;k<a.length;k++)b=a.charCodeAt(k),128>b?f+=String.fromCharCode(b):(127<b&&2048>b?f+=String.fromCharCode(b>>
+6|192):(f+=String.fromCharCode(b>>12|224),f+=String.fromCharCode(b>>6&63|128)),f+=String.fromCharCode(b&63|128));for(a=f;m<a.length;)e=a.charCodeAt(m++),f=a.charCodeAt(m++),k=a.charCodeAt(m++),b=e>>2,e=(e&3)<<4|f>>4,h=(f&15)<<2|k>>6,l=k&63,isNaN(f)?h=l=64:isNaN(k)&&(l=64),g=g+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(b)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(e)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(l);return g}var a={consoleLog:!1,csvEnclosure:'"',csvSeparator:",",csvUseBOM:!0,displayTableName:!1,escape:!1,excelstyles:[],fileName:"tableExport",htmlContent:!1,ignoreColumn:[],ignoreRow:[],jsonScope:"all",jspdf:{orientation:"p",unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},autotable:{styles:{cellPadding:2,rowHeight:12,fontSize:8,fillColor:255,textColor:50,fontStyle:"normal",overflow:"ellipsize",halign:"left",
+valign:"middle"},headerStyles:{fillColor:[52,73,94],textColor:255,fontStyle:"bold",halign:"center"},alternateRowStyles:{fillColor:245},tableExport:{onAfterAutotable:null,onBeforeAutotable:null,onTable:null}}},numbers:{html:{decimalMark:".",thousandsSeparator:","},output:{decimalMark:".",thousandsSeparator:","}},onCellData:null,onCellHtmlData:null,outputMode:"file",pdfmake:{enabled:!1},tbodySelector:"tr",tfootSelector:"tr",theadSelector:"tr",tableName:"myTableName",type:"csv",worksheetName:"xlsWorksheetName"},
+r=this,O=null,t=[],l=[],m=0,x=[],n="",I=[];b.extend(!0,a,q);I=R(r);if("csv"==a.type||"txt"==a.type){q=function(d,g,e,f){l=b(r).find(d).first().find(g);l.each(function(){n="";w(this,e,m,f+l.length,function(d,e,g){var b=n,f="";if(null!=d)if(d=v(d,e,g),e=null===d||""==d?"":d.toString(),d instanceof Date)f=a.csvEnclosure+d.toLocaleString()+a.csvEnclosure;else if(f=S(e,a.csvEnclosure,a.csvEnclosure+a.csvEnclosure),0<=f.indexOf(a.csvSeparator)||/[\r\n ]/g.test(f))f=a.csvEnclosure+f+a.csvEnclosure;n=b+(f+
+a.csvSeparator)});n=b.trim(n).substring(0,n.length-1);0<n.length&&(0<E.length&&(E+="\n"),E+=n);m++});return l.length};var E="",y=0,m=0,y=y+q("thead",a.theadSelector,"th,td",y),y=y+q("tbody",a.tbodySelector,"td",y);a.tfootSelector.length&&q("tfoot",a.tfootSelector,"td",y);E+="\n";!0===a.consoleLog&&console.log(E);if("string"===a.outputMode)return E;if("base64"===a.outputMode)return G(E);try{var z=new Blob([E],{type:"text/"+("csv"==a.type?"csv":"plain")+";charset=utf-8"});saveAs(z,a.fileName+"."+a.type,
+"csv"!=a.type||!1===a.csvUseBOM)}catch(d){C(a.fileName+"."+a.type,"data:text/"+("csv"==a.type?"csv":"plain")+";charset=utf-8,"+("csv"==a.type&&a.csvUseBOM?"\ufeff":""),E)}}else if("sql"==a.type){var m=0,u="INSERT INTO `"+a.tableName+"` (",t=b(r).find("thead").first().find(a.theadSelector);t.each(function(){w(this,"th,td",m,t.length,function(a,g,e){u+="'"+v(a,g,e)+"',"});m++;u=b.trim(u);u=b.trim(u).substring(0,u.length-1)});u+=") VALUES ";l=b(r).find("tbody").first().find(a.tbodySelector);a.tfootSelector.length&&
+l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){n="";w(this,"td",m,t.length+l.length,function(a,g,e){n+="'"+v(a,g,e)+"',"});3<n.length&&(u+="("+n,u=b.trim(u).substring(0,u.length-1),u+="),");m++});u=b.trim(u).substring(0,u.length-1);u+=";";!0===a.consoleLog&&console.log(u);if("string"===a.outputMode)return u;if("base64"===a.outputMode)return G(u);try{z=new Blob([u],{type:"text/plain;charset=utf-8"}),saveAs(z,a.fileName+".sql")}catch(d){C(a.fileName+".sql","data:application/sql;charset=utf-8,",
+u)}}else if("json"==a.type){var J=[],t=b(r).find("thead").first().find(a.theadSelector);t.each(function(){var a=[];w(this,"th,td",m,t.length,function(g,e,b){a.push(v(g,e,b))});J.push(a)});var U=[],l=b(r).find("tbody").first().find(a.tbodySelector);a.tfootSelector.length&&l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){var a={},g=0;w(this,"td",m,t.length+l.length,function(e,b,k){J.length?a[J[J.length-1][g]]=v(e,b,k):a[g]=v(e,b,k);g++});0==b.isEmptyObject(a)&&U.push(a);m++});
+q="";q="head"==a.jsonScope?JSON.stringify(J):"data"==a.jsonScope?JSON.stringify(U):JSON.stringify({header:J,data:U});!0===a.consoleLog&&console.log(q);if("string"===a.outputMode)return q;if("base64"===a.outputMode)return G(q);try{z=new Blob([q],{type:"application/json;charset=utf-8"}),saveAs(z,a.fileName+".json")}catch(d){C(a.fileName+".json","data:application/json;charset=utf-8;base64,",q)}}else if("xml"===a.type){var m=0,A='<?xml version="1.0" encoding="utf-8"?>',A=A+"<tabledata><fields>",t=b(r).find("thead").first().find(a.theadSelector);
+t.each(function(){w(this,"th,td",m,l.length,function(a,b,e){A+="<field>"+v(a,b,e)+"</field>"});m++});var A=A+"</fields><data>",ca=1,l=b(r).find("tbody").first().find(a.tbodySelector);a.tfootSelector.length&&l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){var a=1;n="";w(this,"td",m,t.length+l.length,function(b,e,f){n+="<column-"+a+">"+v(b,e,f)+"</column-"+a+">";a++});0<n.length&&"<column-1></column-1>"!=n&&(A+='<row id="'+ca+'">'+n+"</row>",ca++);m++});A+="</data></tabledata>";
+!0===a.consoleLog&&console.log(A);if("string"===a.outputMode)return A;if("base64"===a.outputMode)return G(A);try{z=new Blob([A],{type:"application/xml;charset=utf-8"}),saveAs(z,a.fileName+".xml")}catch(d){C(a.fileName+".xml","data:application/xml;charset=utf-8;base64,",A)}}else if("excel"==a.type||"xls"==a.type||"word"==a.type||"doc"==a.type){q="excel"==a.type||"xls"==a.type?"excel":"word";var y="excel"==q?"xls":"doc",p='xmlns:x="urn:schemas-microsoft-com:office:'+q+'"',H="";b(r).filter(function(){return"none"!=
+b(this).data("tableexport-display")&&(b(this).is(":visible")||"always"==b(this).data("tableexport-display"))}).each(function(){m=0;I=R(this);H+="<table><thead>";t=b(this).find("thead").first().find(a.theadSelector);t.each(function(){n="";w(this,"th,td",m,t.length,function(d,g,e){if(null!=d){var f="";n+="<th";for(var k in a.excelstyles)if(a.excelstyles.hasOwnProperty(k)){var h=b(d).css(a.excelstyles[k]);""!=h&&"0px none rgb(0, 0, 0)"!=h&&(""==f&&(f='style="'),f+=a.excelstyles[k]+":"+h+";")}""!=f&&
+(n+=" "+f+'"');b(d).is("[colspan]")&&(n+=' colspan="'+b(d).attr("colspan")+'"');b(d).is("[rowspan]")&&(n+=' rowspan="'+b(d).attr("rowspan")+'"');n+=">"+v(d,g,e)+"</th>"}});0<n.length&&(H+="<tr>"+n+"</tr>");m++});H+="</thead><tbody>";l=b(this).find("tbody").first().find(a.tbodySelector);a.tfootSelector.length&&l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){n="";w(this,"td",m,t.length+l.length,function(d,g,e){if(null!=d){var f="",k=b(d).data("tableexport-msonumberformat");
+"undefined"==typeof k&&"function"===typeof a.onMsoNumberFormat&&(k=a.onMsoNumberFormat(d,g,e));"undefined"!=typeof k&&""!=k&&(f="style=\"mso-number-format:'"+k+"'");n+="<td";for(var h in a.excelstyles)a.excelstyles.hasOwnProperty(h)&&(k=b(d).css(a.excelstyles[h]),""!=k&&"0px none rgb(0, 0, 0)"!=k&&(""==f&&(f='style="'),f+=a.excelstyles[h]+":"+k+";"));""!=f&&(n+=" "+f+'"');b(d).is("[colspan]")&&(n+=' colspan="'+b(d).attr("colspan")+'"');b(d).is("[rowspan]")&&(n+=' rowspan="'+b(d).attr("rowspan")+'"');
+n+=">"+v(d,g,e)+"</td>"}});0<n.length&&(H+="<tr>"+n+"</tr>");m++});a.displayTableName&&(H+="<tr><td></td></tr><tr><td></td></tr><tr><td>"+v(b("<p>"+a.tableName+"</p>"))+"</td></tr>");H+="</tbody></table>";!0===a.consoleLog&&console.log(H)});p='<html xmlns:o="urn:schemas-microsoft-com:office:office" '+p+' xmlns="http://www.w3.org/TR/REC-html40">'+('<meta http-equiv="content-type" content="application/vnd.ms-'+q+'; charset=UTF-8">')+"<head>";"excel"===q&&(p+="\x3c!--[if gte mso 9]>",p+="<xml>",p+="<x:ExcelWorkbook>",
+p+="<x:ExcelWorksheets>",p+="<x:ExcelWorksheet>",p+="<x:Name>",p+=a.worksheetName,p+="</x:Name>",p+="<x:WorksheetOptions>",p+="<x:DisplayGridlines/>",p+="</x:WorksheetOptions>",p+="</x:ExcelWorksheet>",p+="</x:ExcelWorksheets>",p+="</x:ExcelWorkbook>",p+="</xml>",p+="<![endif]--\x3e");p+="</head>";p+="<body>";p+=H;p+="</body>";p+="</html>";!0===a.consoleLog&&console.log(p);if("string"===a.outputMode)return p;if("base64"===a.outputMode)return G(p);try{z=new Blob([p],{type:"application/vnd.ms-"+a.type}),
+saveAs(z,a.fileName+"."+y)}catch(d){C(a.fileName+"."+y,"data:application/vnd.ms-"+q+";base64,",p)}}else if("xlsx"==a.type){var P=[],V=[],m=0,l=b(r).find("thead").first().find(a.theadSelector);l.push.apply(l,b(r).find("tbody").first().find(a.tbodySelector));a.tfootSelector.length&&l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){var a=[];w(this,"th,td",m,l.length,function(b,e,f){if("undefined"!==typeof b&&null!=b){var k=b.getAttribute("colspan"),h=b.getAttribute("rowspan");
+b=v(b,e,f);""!==b&&b==+b&&(b=+b);V.forEach(function(b){if(m>=b.s.r&&m<=b.e.r&&a.length>=b.s.c&&a.length<=b.e.c)for(var e=0;e<=b.e.c-b.s.c;++e)a.push(null)});if(h||k)k=k||1,V.push({s:{r:m,c:a.length},e:{r:m+(h||1)-1,c:a.length+k-1}});a.push(""!==b?b:null);if(k)for(h=0;h<k-1;++h)a.push(null)}});P.push(a);m++});console.log(P);q=new T;y=ia(P);y["!merges"]=V;q.SheetNames.push(a.worksheetName);q.Sheets[a.worksheetName]=y;q=XLSX.write(q,{bookType:a.type,bookSST:!1,type:"binary"});try{z=new Blob([ha(q)],
+{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8"}),saveAs(z,a.fileName+"."+a.type)}catch(d){C(a.fileName+"."+a.type,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=UTF-8",P)}}else if("png"==a.type)html2canvas(b(r)[0]).then(function(b){b=b.toDataURL();b=b.substring(22);for(var g=atob(b),e=new ArrayBuffer(g.length),f=new Uint8Array(e),k=0;k<g.length;k++)f[k]=g.charCodeAt(k);!0===a.consoleLog&&console.log(g);if("string"===a.outputMode)return g;
+if("base64"===a.outputMode)return G(b);try{var h=new Blob([e],{type:"image/png"});saveAs(h,a.fileName+".png")}catch(l){C(a.fileName+".png","data:image/png,",b)}});else if("pdf"==a.type)if(!0===a.pdfmake.enabled){var W=[],X=[],m=0,t=b(this).find("thead").find(a.theadSelector);t.each(function(){var a=[];w(this,"th,td",m,t.length,function(b,f,k){a.push(v(b,f,k))});a.length&&X.push(a);for(var b=W.length;b<a.length;b++)W.push("*");m++});l=b(this).find("tbody").find(a.tbodySelector);a.tfootSelector.length&&
+l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){var a=[];w(this,"td",m,t.length+l.length,function(b,e,f){a.push(v(b,e,f))});a.length&&X.push(a);m++});pdfMake.createPdf({pageOrientation:"landscape",content:[{table:{headerRows:t.length,widths:W,body:X}}]}).getBuffer(function(b){try{var g=new Blob([b],{type:"application/pdf"});saveAs(g,a.fileName+".pdf")}catch(e){C(a.fileName+".pdf","data:application/pdf;base64,",b)}})}else if(!1===a.jspdf.autotable){var z={dim:{w:N(b(r).first().get(0),
+"width","mm"),h:N(b(r).first().get(0),"height","mm")},pagesplit:!1},da=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);da.addHTML(b(r).first(),a.jspdf.margins.left,a.jspdf.margins.top,z,function(){Y(da)})}else{var h=a.jspdf.autotable.tableExport;if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var K={a0:[2383.94,3370.39],a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89]},Q="",L="",ea=0;b(r).filter(":visible").each(function(){if("none"!=
+b(this).css("display")){var a=N(b(this).get(0),"width","pt");if(a>ea){a>K.a0[0]&&(Q="a0",L="l");for(var g in K)K.hasOwnProperty(g)&&K[g][1]>a&&(Q=g,L="l",K[g][0]>a&&(L="p"));ea=a}}});a.jspdf.format=""==Q?"a4":Q;a.jspdf.orientation=""==L?"w":L}h.doc=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);b(r).filter(function(){return"none"!=b(this).data("tableexport-display")&&(b(this).is(":visible")||"always"==b(this).data("tableexport-display"))}).each(function(){var d,g=0;I=R(this);h.columns=
+[];h.rows=[];h.rowoptions={};if("function"===typeof h.onTable&&!1===h.onTable(b(this),a))return!0;a.jspdf.autotable.tableExport=null;var e=b.extend(!0,{},a.jspdf.autotable);a.jspdf.autotable.tableExport=h;e.margin={};b.extend(!0,e.margin,a.jspdf.margins);e.tableExport=h;"function"!==typeof e.beforePageContent&&(e.beforePageContent=function(a){1==a.pageCount&&a.table.rows.concat(a.table.headerRow).forEach(function(b){0<b.height&&(b.height+=(2-1.15)/2*b.styles.fontSize,a.table.height+=(2-1.15)/2*b.styles.fontSize)})});
+"function"!==typeof e.createdHeaderCell&&(e.createdHeaderCell=function(a,d){a.styles=b.extend({},d.row.styles);if("undefined"!=typeof h.columns[d.column.dataKey]){var f=h.columns[d.column.dataKey];if("undefined"!=typeof f.rect){var g;a.contentWidth=f.rect.width;if("undefined"==typeof h.heightRatio||0==h.heightRatio)g=d.row.raw[d.column.dataKey].rowspan?d.row.raw[d.column.dataKey].rect.height/d.row.raw[d.column.dataKey].rowspan:d.row.raw[d.column.dataKey].rect.height,h.heightRatio=a.styles.rowHeight/
+g;g=d.row.raw[d.column.dataKey].rect.height*h.heightRatio;g>a.styles.rowHeight&&(a.styles.rowHeight=g)}"undefined"!=typeof f.style&&!0!==f.style.hidden&&(a.styles.halign=f.style.align,"inherit"===e.styles.fillColor&&(a.styles.fillColor=f.style.bcolor),"inherit"===e.styles.textColor&&(a.styles.textColor=f.style.color),"inherit"===e.styles.fontStyle&&(a.styles.fontStyle=f.style.fstyle))}});"function"!==typeof e.createdCell&&(e.createdCell=function(a,b){var d=h.rowoptions[b.row.index+":"+b.column.dataKey];
+"undefined"!=typeof d&&"undefined"!=typeof d.style&&!0!==d.style.hidden&&(a.styles.halign=d.style.align,"inherit"===e.styles.fillColor&&(a.styles.fillColor=d.style.bcolor),"inherit"===e.styles.textColor&&(a.styles.textColor=d.style.color),"inherit"===e.styles.fontStyle&&(a.styles.fontStyle=d.style.fstyle))});"function"!==typeof e.drawHeaderCell&&(e.drawHeaderCell=function(a,b){var d=h.columns[b.column.dataKey];return(1!=d.style.hasOwnProperty("hidden")||!0!==d.style.hidden)&&0<=d.rowIndex?Z(a,b,d):
+!1});"function"!==typeof e.drawCell&&(e.drawCell=function(a,b){var d=h.rowoptions[b.row.index+":"+b.column.dataKey];if(Z(a,b,d)){h.doc.rect(a.x,a.y,a.width,a.height,a.styles.fillStyle);if("undefined"!=typeof d&&"undefined"!=typeof d.kids&&0<d.kids.length){var e=a.height/d.rect.height;if(e>h.dh||"undefined"==typeof h.dh)h.dh=e;h.dw=a.width/d.rect.width;aa(a,d.kids,h)}h.doc.autoTableText(a.text,a.textPos.x,a.textPos.y,{halign:a.styles.halign,valign:a.styles.valign})}return!1});h.headerrows=[];t=b(this).find("thead").find(a.theadSelector);
+t.each(function(){d=0;h.headerrows[g]=[];w(this,"th,td",g,t.length,function(a,b,e){var f=ba(a);f.title=v(a,b,e);f.key=d++;f.rowIndex=g;h.headerrows[g].push(f)});g++});0<g&&b.each(h.headerrows[g-1],function(){obj=1<g&&null==this.rect?h.headerrows[g-2][this.key]:this;null!=obj&&h.columns.push(obj)});var f=0;l=b(this).find("tbody").find(a.tbodySelector);a.tfootSelector.length&&l.push.apply(l,b(r).find("tfoot").find(a.tfootSelector));l.each(function(){var a=[];d=0;w(this,"td",g,t.length+l.length,function(e,
+g,l){if("undefined"===typeof h.columns[d]){var m={title:"",key:d,style:{hidden:!0}};h.columns.push(m)}"undefined"!==typeof e&&null!=e?(m=ba(e),m.kids=b(e).children()):(m=b.extend(!0,{},h.rowoptions[f+":"+(d-1)]),m.colspan=-1);h.rowoptions[f+":"+d++]=m;a.push(v(e,g,l))});a.length&&(h.rows.push(a),f++);g++});if("function"===typeof h.onBeforeAutotable)h.onBeforeAutotable(b(this),h.columns,h.rows,e);h.doc.autoTable(h.columns,h.rows,e);if("function"===typeof h.onAfterAutotable)h.onAfterAutotable(b(this),
+e);a.jspdf.autotable.startY=h.doc.autoTableEndPosY()+e.margin.top});Y(h.doc);"undefined"!=typeof h.headerrows&&(h.headerrows.length=0);"undefined"!=typeof h.columns&&(h.columns.length=0);"undefined"!=typeof h.rows&&(h.rows.length=0);delete h.doc;h.doc=null}return this}})})(jQuery);
diff --git a/web/gui/main.css b/web/gui/main.css new file mode 100644 index 0000000..b1fb94f --- /dev/null +++ b/web/gui/main.css @@ -0,0 +1,669 @@ +/* force the vertical window scrollbar */ +html { + overflow-y: hidden; +} + +/* prevent body from hiding under the navbar */ +body { + padding-top: 50px; +} + +.loadOverlay { + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 100%; + z-index: 2000; + font-size: 10vh; + font-family: sans-serif; + padding: 40vh 0 40vh 0; + font-weight: bold; + text-align: center; +} + +.navbar-highlight { + display: none; + position: fixed; + margin-top: 5px; + height: 26px; + width: 100%; + text-align: center; + overflow: hidden; + z-index: 30; + pointer-events: none !important; +} + +.navbar-highlight-content { + position: relative; + display: inline-block; + margin: 0 auto; + height: 26px; + min-width: 500px; + background-color: rgba(0, 0, 0, 0.7); + padding-top: 2px; + padding-bottom: 2px; + padding-left: 15px; + padding-right: 15px; + border-radius: 10px; + color: lightgrey; + pointer-events: auto !important; +} + +.navbar-highlight-bar { + cursor: pointer; +} + +.navbar-highlight-button-right { + cursor: pointer; + padding-left: 10px; +} + +.modal-wide .modal-dialog { + width: 80%; +} + +/* fix # anchors scrolling under the navbar + https://github.com/twbs/bootstrap/issues/1768#issuecomment-46519033 + */ +h1 { + position: relative; + z-index: -1; +} + +h2 { + position: relative; + z-index: -2; +} + +h1:before, h2:before { + display: block; + content: " "; + margin-top: -70px; + height: 70px; + visibility: hidden; +} + +.p { + display: block; + margin-top: 15px; +} + +.option-row, +.option-control { + vertical-align: top; + padding: 10px; + padding-top: 30px; + padding-left: 30px; +} + +.option-info { + padding: 10px; +} + +.dashboard-submenu-info { + display: block; + margin-top: 10px; +} + +.dashboard-context-info { + display: block; + margin-top: 10px; +} + +#masthead h1 { + /*font-size: 30px;*/ + line-height: 1; + padding-top: 30px; +} + +#masthead .well { + margin-top: 4%; +} + +/* fix the navbar shifting when a modal is open */ +/* https://github.com/twbs/bootstrap/issues/14040#issuecomment-159891033 */ +body.modal-open { + width: 100% !important; + padding-right: 0 !important; + /* overflow-y: scroll !important; */ + /* position: fixed !important;*/ + overflow: visible; +} + +/* make accordion use the whole header bar for expand/collapse */ +.panel-title a { + display: block; + padding: 10px 15px; + margin: -10px -15px; +} + +/* + * Side navigation + * + * Scrollspy and affixed enhanced navigation to highlight sections and secondary + * sections of docs content. + */ + +.affix { + position: static; + top: 70px !important; + /*width: 220px;*/ +} + +/* +.affix-top { + width: 220px; +} +*/ + +.dashboard-sidebar { + max-height: calc(100% - 70px) !important; + overflow-y: auto; + /*width: 220px !important;*/ +} + +/* By default it's not affixed in mobile views, so undo that */ +.dashboard-sidebar.affix { + position: static; +} + +@media (min-width: 768px) { + .dashboard-sidebar { + padding-left: 20px; + } +} + +/* First level of nav */ +.dashboard-sidenav { + margin-top: 20px; + margin-bottom: 20px; +} + +/* All levels of nav */ +.dashboard-sidebar .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} + +.dashboard-sidebar .nav > li > a > .svg-inline--fa { + width: 20px; + text-align: center; +} + +.dashboard-sidebar .nav > li > a:hover, +.dashboard-sidebar .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} + +.dashboard-sidebar .nav > .active > a, +.dashboard-sidebar .nav > .active:hover > a, +.dashboard-sidebar .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +.dashboard-sidebar .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} + +.dashboard-sidebar .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} + +.dashboard-sidebar .nav .nav > li > a:hover, +.dashboard-sidebar .nav .nav > li > a:focus { + padding-left: 29px; +} + +.dashboard-sidebar .nav .nav > .active > a, +.dashboard-sidebar .nav .nav > .active:hover > a, +.dashboard-sidebar .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +.dropdown-menu { + min-width: 200px; +} + +.dropdown-menu.columns-2 { + margin: 0; + padding: 0; + width: 400px; +} + +.dropdown-menu li a { + padding: 5px 15px; + font-weight: 300; +} + +.dropdown-menu.multi-column { + overflow-x: hidden; +} + +.multi-column-dropdown { + list-style: none; + padding: 0; +} + +.multi-column-dropdown li a { + display: inline-block; + clear: both; + line-height: 1.428571429; + white-space: normal; +} + +.multi-column-dropdown li a:hover { + text-decoration: none; + color: #f5f5f5; + background-color: #262626; +} + +.scrollable-menu { + height: auto; + max-height: 80vh; + overflow-x: hidden; +} + +.scrollable-menu-50 { + height: auto; + max-height: 50vh; + overflow-x: hidden; +} + +/* Back to top (hidden on mobile) */ +.back-to-top, +.dashboard-theme-toggle { + display: none; + padding: 4px 10px; + margin-top: 10px; + margin-left: 10px; + font-size: 12px; + font-weight: 500; + color: #999; +} + +.back-to-top:hover, +.dashboard-theme-toggle:hover { + color: #563d7c; + text-decoration: none; +} + +.dashboard-theme-toggle { + margin-top: 0; +} + +.container { + width: calc(100% - 20px) !important; +} + +.charts-body { + display: inline-block; + width: 100%; +} + +.sidebar-body { + position: absolute; + display: none; +} + +.dashboard-section-container { + display: block; + width: 100%; + page-break-before: auto; + page-break-after: auto; + page-break-inside: auto; +} + +.dashboard-print-row { + display: block; + width: 100%; + page-break-before: auto; + page-break-after: auto; + page-break-inside: avoid; +} + +.netdata-chartblock-container { + display: inline-block; +} + +/* https://github.com/seiyria/bootstrap-slider/issues/746 */ +.tooltip { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +@media print { + body { + overflow: visible !important; + -webkit-print-color-adjust: exact; + page-break-inside: auto; + page-break-before: auto; + page-break-after: auto; + } + + .dashboard-section { + page-break-inside: auto; + page-break-before: auto; + page-break-after: auto; + } + + .dashboard-subsection { + page-break-before: avoid; + page-break-after: auto; + page-break-inside: auto; + } + + .charts-body { + padding-left: 0%; + padding-right: 0%; + display: block; + page-break-inside: auto; + page-break-before: auto; + page-break-after: auto; + } + + .back-to-top, + .dashboard-theme-toggle { + display: block; + } +} + +@media (min-width: 768px) { + .charts-body { + padding-left: 0%; + padding-right: 0%; + } + + .back-to-top, + .dashboard-theme-toggle { + display: block; + } +} + +/* Show and affix the side nav when space allows it */ +@media (min-width: 992px) { + .container { + padding-left: 0% !important; + } + + .charts-body { + width: calc(100% - 213px) !important; + padding-left: 1% !important; + padding-right: 0% !important; + } + + .sidebar-body { + display: inline-block !important; + width: 213px !important; + } + + .dashboard-sidebar .nav > .active > ul { + display: block; + } + + /* Widen the fixed sidebar */ + .dashboard-sidebar.affix, + .dashboard-sidebar.affix-top, + .dashboard-sidebar.affix-bottom { + width: 213px !important; + } + + .dashboard-sidebar.affix { + position: fixed; /* Undo the static from mobile first approach */ + top: 20px; + } + + .dashboard-sidebar.affix-bottom { + position: absolute; /* Undo the static from mobile first approach */ + } + + .dashboard-sidebar.affix-bottom .dashboard-sidenav, + .dashboard-sidebar.affix .dashboard-sidenav { + margin-top: 0; + margin-bottom: 0; + } +} + +@media (min-width: 1200px) { + .container { + padding-left: 2% !important; + } + + .charts-body { + width: calc(100% - 233px) !important; + padding-left: 1% !important; + padding-right: 1% !important; + } + + .sidebar-body { + display: inline-block !important; + width: 233px !important; + } + + /* Widen the fixed sidebar again */ + .dashboard-sidebar.affix, + .dashboard-sidebar.affix-top, + .dashboard-sidebar.affix-bottom { + width: 233px !important; + } +} + +@media (min-width: 1360px) { + .container { + padding-left: 3% !important; + } + + .charts-body { + width: calc(100% - 263px) !important; + padding-left: 1% !important; + padding-right: 2% !important; + } + + .sidebar-body { + display: inline-block !important; + width: 263px !important; + } + + /* Widen the fixed sidebar again */ + .dashboard-sidebar.affix, + .dashboard-sidebar.affix-top, + .dashboard-sidebar.affix-bottom { + width: 263px !important; + } +} + +.action-button { + position: relative; + display: inline-block; + color: gray; + cursor: pointer; + margin: 0 auto; + width: 30px; + height: 30px; + font-size: 25px; +} + +.ripple { + position: relative; + /*overflow: hidden;*/ + transform: translate3d(0, 0, 0) +} + +.ripple:after { + content: ""; + display: block; + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; + pointer-events: none; + background-image: radial-gradient(circle, #000 10%, transparent 10.01%); + background-repeat: no-repeat; + background-position: 50%; + transform: scale(18, 18); /* the size of the ripple */ + opacity: 0; + transition: transform .5s, opacity 1s +} + +.ripple:active:after { + transform: scale(0, 0); + opacity: .2; + transition: 0s +} + +/* -------------------------------------------------------------------------- */ + +#my-netdata-dropdown-content { + width: 500px; +} + +#my-netdata-dropdown-content a:hover { + color: #fff; +} + +#my-netdata-dropdown-content .info-item { + height: 32px; + line-height: 32px; + padding-left: 14px; +} + +#my-netdata-dropdown-content .agent-item { + display: flex; + align-items: center; + min-height: 32px; + font-weight: 300; +} + +#my-netdata-dropdown-content .agent-item .__title { + cursor: pointer; +} + +#my-netdata-dropdown-content .agent-item:hover { + background-color: #262626; +} + +#my-netdata-dropdown-content .agent-item a:hover { + text-decoration: none; +} + +#my-netdata-dropdown-content .agent-item > :first-child { + width: 40px; + text-align: center; +} + +#my-netdata-dropdown-content .agent-item > :last-child { + width: 40px; + text-align: center; +} + +#my-netdata-dropdown-content .agent-item :nth-child(2) { + min-width: 420px; + line-height: 32px; +} + +.agent-item--separated { + border-top: 1px solid #333; +} + +.agent-item--alternate a { + color: #999; +} + +#my-netdata-dropdown-content .agent-alternate-urls.collapsed { + display: none; +} + +#my-netdata-dropdown-content hr { + display: block; + margin-top: 5px; + margin-bottom: 0; + border-top: 1px solid #333; + height: 4px; +} + +/* white theme overrides */ + +#my-netdata-dropdown-content.theme-white hr { + border-top: 1px solid #ddd; +} + +#my-netdata-dropdown-content.theme-white .agent-item:hover { + background-color: #e6e6e6; +} + +#my-netdata-dropdown-content.theme-white a { + color: #888; +} + +#my-netdata-dropdown-content.theme-white a:hover { + color: #000; +} + +#sign-in-iframe { + background-color: #fff; + border: none; +} + +#cloud-menu { +} + +#cloud-menu.dropdown-menu > li > a { + text-align: left; +} + +#my-netdata-menu-filter-input { + color: #fff; + border: none; + background-color: #4b4f55; + width: 472px; + margin: 5px 14px; + margin-right: 0; + padding: 2px 5px; + outline: none; +} + +#my-netdata-menu-filter-input::placeholder { + opacity: 0.7; +} + +#my-netdata-dropdown-content.theme-white #my-netdata-menu-filter-input { + background-color: #e7e7e7; + color: #555; +} + +.filter-control { + position: relative; +} + +.filter-control .filter-control__clear { + cursor: pointer; + position: absolute; + top: 7px; + right: 19px; +} + +#hostname { + font-size: 18px; +} + diff --git a/web/gui/main.js b/web/gui/main.js new file mode 100644 index 0000000..b6478f6 --- /dev/null +++ b/web/gui/main.js @@ -0,0 +1,4964 @@ +// Main JavaScript file for the Netdata GUI. + +// Codacy declarations +/* global NETDATA */ + +// netdata snapshot data +var netdataSnapshotData = null; + +// enable alarms checking and notifications +var netdataShowAlarms = true; + +// enable registry updates +var netdataRegistry = true; + +// forward definition only - not used here +var netdataServer = undefined; +var netdataServerStatic = undefined; +var netdataCheckXSS = undefined; + +// control the welcome modal and analytics +var this_is_demo = null; + +function escapeUserInputHTML(s) { + return s.toString() + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/#/g, '#') + .replace(/'/g, ''') + .replace(/\(/g, '(') + .replace(/\)/g, ')') + .replace(/\//g, '/'); +} + +function verifyURL(s) { + if (typeof (s) === 'string' && (s.startsWith('http://') || s.startsWith('https://'))) { + return s + .replace(/'/g, '%22') + .replace(/"/g, '%27') + .replace(/\)/g, '%28') + .replace(/\(/g, '%29'); + } + + console.log('invalid URL detected:'); + console.log(s); + return 'javascript:alert("invalid url");'; +} + +// -------------------------------------------------------------------- +// urlOptions + +var urlOptions = { + hash: '#', + theme: null, + help: null, + mode: 'live', // 'live', 'print' + update_always: false, + pan_and_zoom: false, + server: null, + after: 0, + before: 0, + highlight: false, + highlight_after: 0, + highlight_before: 0, + nowelcome: false, + show_alarms: false, + chart: null, + family: null, + alarm: null, + alarm_unique_id: 0, + alarm_id: 0, + alarm_event_id: 0, + + hasProperty: function (property) { + // console.log('checking property ' + property + ' of type ' + typeof(this[property])); + return typeof this[property] !== 'undefined'; + }, + + genHash: function (forReload) { + var hash = urlOptions.hash; + + if (urlOptions.pan_and_zoom === true) { + hash += ';after=' + urlOptions.after.toString() + + ';before=' + urlOptions.before.toString(); + } + + if (urlOptions.highlight === true) { + hash += ';highlight_after=' + urlOptions.highlight_after.toString() + + ';highlight_before=' + urlOptions.highlight_before.toString(); + } + + if (urlOptions.theme !== null) { + hash += ';theme=' + urlOptions.theme.toString(); + } + + if (urlOptions.help !== null) { + hash += ';help=' + urlOptions.help.toString(); + } + + if (urlOptions.update_always === true) { + hash += ';update_always=true'; + } + + if (forReload === true && urlOptions.server !== null) { + hash += ';server=' + urlOptions.server.toString(); + } + + if (urlOptions.mode !== 'live') { + hash += ';mode=' + urlOptions.mode; + } + + return hash; + }, + + parseHash: function () { + var variables = document.location.hash.split(';'); + var len = variables.length; + while (len--) { + if (len !== 0) { + var p = variables[len].split('='); + if (urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined') { + urlOptions[p[0]] = decodeURIComponent(p[1]); + } + } else { + if (variables[len].length > 0) { + urlOptions.hash = variables[len]; + } + } + } + + var booleans = ['nowelcome', 'show_alarms', 'update_always']; + len = booleans.length; + while (len--) { + if (urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1) { + urlOptions[booleans[len]] = true; + } else { + urlOptions[booleans[len]] = false; + } + } + + var numeric = ['after', 'before', 'highlight_after', 'highlight_before']; + len = numeric.length; + while (len--) { + if (typeof urlOptions[numeric[len]] === 'string') { + try { + urlOptions[numeric[len]] = parseInt(urlOptions[numeric[len]]); + } + catch (e) { + console.log('failed to parse URL hash parameter ' + numeric[len]); + urlOptions[numeric[len]] = 0; + } + } + } + + if (urlOptions.server !== null && urlOptions.server !== '') { + netdataServerStatic = document.location.origin.toString() + document.location.pathname.toString(); + netdataServer = urlOptions.server; + netdataCheckXSS = true; + } else { + urlOptions.server = null; + } + + if (urlOptions.before > 0 && urlOptions.after > 0) { + urlOptions.pan_and_zoom = true; + urlOptions.nowelcome = true; + } else { + urlOptions.pan_and_zoom = false; + } + + if (urlOptions.highlight_before > 0 && urlOptions.highlight_after > 0) { + urlOptions.highlight = true; + } else { + urlOptions.highlight = false; + } + + switch (urlOptions.mode) { + case 'print': + urlOptions.theme = 'white'; + urlOptions.welcome = false; + urlOptions.help = false; + urlOptions.show_alarms = false; + + if (urlOptions.pan_and_zoom === false) { + urlOptions.pan_and_zoom = true; + urlOptions.before = Date.now(); + urlOptions.after = urlOptions.before - 600000; + } + + netdataShowAlarms = false; + netdataRegistry = false; + this_is_demo = false; + break; + + case 'live': + default: + urlOptions.mode = 'live'; + break; + } + + // console.log(urlOptions); + }, + + hashUpdate: function () { + history.replaceState(null, '', urlOptions.genHash(true)); + }, + + netdataPanAndZoomCallback: function (status, after, before) { + //console.log(1); + //console.log(new Error().stack); + + if (netdataSnapshotData === null) { + urlOptions.pan_and_zoom = status; + urlOptions.after = after; + urlOptions.before = before; + urlOptions.hashUpdate(); + } + }, + + netdataHighlightCallback: function (status, after, before) { + //console.log(2); + //console.log(new Error().stack); + + if (status === true && (after === null || before === null || after <= 0 || before <= 0 || after >= before)) { + status = false; + after = 0; + before = 0; + } + + if (netdataSnapshotData === null) { + urlOptions.highlight = status; + } else { + urlOptions.highlight = false; + } + + urlOptions.highlight_after = Math.round(after); + urlOptions.highlight_before = Math.round(before); + urlOptions.hashUpdate(); + + var show_eye = NETDATA.globalChartUnderlay.hasViewport(); + + if (status === true && after > 0 && before > 0 && after < before) { + var d1 = NETDATA.dateTime.localeDateString(after); + var d2 = NETDATA.dateTime.localeDateString(before); + if (d1 === d2) { + d2 = ''; + } + document.getElementById('navbar-highlight-content').innerHTML = + ((show_eye === true) ? '<span class="navbar-highlight-bar highlight-tooltip" onclick="urlOptions.showHighlight();" title="restore the highlighted view" data-toggle="tooltip" data-placement="bottom">' : '<span>').toString() + + 'highlighted time-frame' + + ' <b>' + d1 + ' <code>' + NETDATA.dateTime.localeTimeString(after) + '</code></b> to ' + + ' <b>' + d2 + ' <code>' + NETDATA.dateTime.localeTimeString(before) + '</code></b>, ' + + 'duration <b>' + NETDATA.seconds4human(Math.round((before - after) / 1000)) + '</b>' + + '</span>' + + '<span class="navbar-highlight-button-right highlight-tooltip" onclick="urlOptions.clearHighlight();" title="clear the highlighted time-frame" data-toggle="tooltip" data-placement="bottom"><i class="fas fa-times"></i></span>'; + + $('.navbar-highlight').show(); + + $('.highlight-tooltip').tooltip({ + html: true, + delay: {show: 500, hide: 0}, + container: 'body' + }); + } else { + $('.navbar-highlight').hide(); + } + }, + + clearHighlight: function () { + NETDATA.globalChartUnderlay.clear(); + + if (NETDATA.globalPanAndZoom.isActive() === true) { + NETDATA.globalPanAndZoom.clearMaster(); + } + }, + + showHighlight: function () { + NETDATA.globalChartUnderlay.focus(); + } +}; + +urlOptions.parseHash(); + +// -------------------------------------------------------------------- +// check options that should be processed before loading netdata.js + +var localStorageTested = -1; + +function localStorageTest() { + if (localStorageTested !== -1) { + return localStorageTested; + } + + if (typeof Storage !== "undefined" && typeof localStorage === 'object') { + var test = 'test'; + try { + localStorage.setItem(test, test); + localStorage.removeItem(test); + localStorageTested = true; + } + catch (e) { + console.log(e); + localStorageTested = false; + } + } else { + localStorageTested = false; + } + + return localStorageTested; +} + +function loadLocalStorage(name) { + var ret = null; + + try { + if (localStorageTest() === true) { + ret = localStorage.getItem(name); + } else { + console.log('localStorage is not available'); + } + } + catch (error) { + console.log(error); + return null; + } + + if (typeof ret === 'undefined' || ret === null) { + return null; + } + + // console.log('loaded: ' + name.toString() + ' = ' + ret.toString()); + + return ret; +} + +function saveLocalStorage(name, value) { + // console.log('saving: ' + name.toString() + ' = ' + value.toString()); + try { + if (localStorageTest() === true) { + localStorage.setItem(name, value.toString()); + return true; + } + } + catch (error) { + console.log(error); + } + + return false; +} + +function getTheme(def) { + if (urlOptions.mode === 'print') { + return 'white'; + } + + var ret = loadLocalStorage('netdataTheme'); + if (typeof ret === 'undefined' || ret === null || ret === 'undefined') { + return def; + } else { + return ret; + } +} + +function setTheme(theme) { + if (urlOptions.mode === 'print') { + return false; + } + + if (theme === netdataTheme) { + return false; + } + return saveLocalStorage('netdataTheme', theme); +} + +var netdataTheme = getTheme('slate'); +var netdataShowHelp = true; + +if (urlOptions.theme !== null) { + setTheme(urlOptions.theme); + netdataTheme = urlOptions.theme; +} else { + urlOptions.theme = netdataTheme; +} + +if (urlOptions.help !== null) { + saveLocalStorage('options.show_help', urlOptions.help); + netdataShowHelp = urlOptions.help; +} else { + urlOptions.help = loadLocalStorage('options.show_help'); +} + +// -------------------------------------------------------------------- +// natural sorting +// http://www.davekoelle.com/files/alphanum.js - LGPL + +function naturalSortChunkify(t) { + var tz = []; + var x = 0, y = -1, n = 0, i, j; + + while (i = (j = t.charAt(x++)).charCodeAt(0)) { + var m = (i >= 48 && i <= 57); + if (m !== n) { + tz[++y] = ""; + n = m; + } + tz[y] += j; + } + + return tz; +} + +function naturalSortCompare(a, b) { + var aa = naturalSortChunkify(a.toLowerCase()); + var bb = naturalSortChunkify(b.toLowerCase()); + + for (var x = 0; aa[x] && bb[x]; x++) { + if (aa[x] !== bb[x]) { + var c = Number(aa[x]), d = Number(bb[x]); + if (c.toString() === aa[x] && d.toString() === bb[x]) { + return c - d; + } else { + return (aa[x] > bb[x]) ? 1 : -1; + } + } + } + + return aa.length - bb.length; +} + +// -------------------------------------------------------------------- +// saving files to client + +function saveTextToClient(data, filename) { + var blob = new Blob([data], { + type: 'application/octet-stream' + }); + + var url = URL.createObjectURL(blob); + var link = document.createElement('a'); + link.setAttribute('href', url); + link.setAttribute('download', filename); + + var el = document.getElementById('hiddenDownloadLinks'); + el.innerHTML = ''; + el.appendChild(link); + + setTimeout(function () { + el.removeChild(link); + URL.revokeObjectURL(url); + }, 60); + + link.click(); +} + +function saveObjectToClient(data, filename) { + saveTextToClient(JSON.stringify(data), filename); +} + +// ----------------------------------------------------------------------------- +// registry call back to render my-netdata menu + +function toggleExpandIcon(svgEl) { + if (svgEl.getAttribute('data-icon') === 'caret-down') { + svgEl.setAttribute('data-icon', 'caret-up'); + } else { + svgEl.setAttribute('data-icon', 'caret-down'); + } +} + +function toggleAgentItem(e, guid) { + e.stopPropagation(); + e.preventDefault(); + + toggleExpandIcon(e.currentTarget.children[0]); + + const el = document.querySelector(`.agent-alternate-urls.agent-${guid}`); + if (el) { + el.classList.toggle('collapsed'); + } +} + +// When you stream metrics from netdata to netdata, the recieving netdata now +// has multiple host databases. It's own, and multiple mirrored. Mirrored databases +// can be accessed with <http://localhost:19999/host/NAME/> +function renderStreamedHosts(options) { + let html = `<div class="info-item">Databases streamed to this agent</div>`; + + var base = document.location.origin.toString() + document.location.pathname.toString(); + if (base.endsWith("/host/" + options.hostname + "/")) { + base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length); + } + + if (base.endsWith("/")) { + base = base.substring(0, base.length - 1); + } + + var master = options.hosts[0].hostname; + var sorted = options.hosts.sort(function (a, b) { + if (a.hostname === master) { + return -1; + } + return naturalSortCompare(a.hostname, b.hostname); + }); + + let displayedDatabases = false; + + for (var s of sorted) { + let url, icon; + const hostname = s.hostname; + + if (myNetdataMenuFilterValue !== "") { + if (!hostname.includes(myNetdataMenuFilterValue)) { + continue; + } + } + + displayedDatabases = true; + + if (hostname === master) { + url = `${base}/`; + icon = 'home'; + } else { + url = `${base}/host/${hostname}/`; + icon = 'window-restore'; + } + + html += ( + `<div class="agent-item"> + <a class="registry_link" href="${url}#" onClick="return gotoHostedModalHandler('${url}');"> + <i class="fas fa-${icon}" style="color: #999;"></i> + </a> + <span class="__title" onClick="return gotoHostedModalHandler('${url}');"> + <a class="registry_link" href="${url}#">${hostname}</a> + </span> + <div></div> + </div>` + ) + } + + if (!displayedDatabases) { + html += ( + `<div class="info-item"> + <i class="fas fa-filter"></i> + <span style="margin-left: 8px">no databases match the filter criteria.<span> + </div>` + ) + } + + return html; +} + +function renderMachines(machinesArray) { + // let html = isSignedIn() + // ? `<div class="info-item">My nodes</div>` + // : `<div class="info-item">My nodes</div>`; + + let html = `<div class="info-item">My nodes</div>`; + + if (machinesArray === null) { + let ret = loadLocalStorage("registryCallback"); + if (ret) { + machinesArray = JSON.parse(ret); + console.log("failed to contact the registry - loaded registry data from browser local storage"); + } + } + + let found = false; + let displayedAgents = false; + + const maskedURL = NETDATA.registry.MASKED_DATA; + + if (machinesArray) { + saveLocalStorage("registryCallback", JSON.stringify(machinesArray)); + + var machines = machinesArray.sort(function (a, b) { + return naturalSortCompare(a.name, b.name); + }); + + for (var machine of machines) { + found = true; + + if (myNetdataMenuFilterValue !== "") { + if (!machine.name.includes(myNetdataMenuFilterValue)) { + continue; + } + } + + displayedAgents = true; + + const alternateUrlItems = ( + `<div class="agent-alternate-urls agent-${machine.guid} collapsed"> + ${machine.alternate_urls.reduce((str, url) => { + if (url === maskedURL) { + return str + } + + return str + ( + `<div class="agent-item agent-item--alternate"> + <div></div> + <a href="${url}" title="${url}">${truncateString(url, 64)}</a> + <a href="#" onclick="deleteRegistryModalHandler('${machine.guid}', '${machine.name}', '${url}'); return false;"> + <i class="fas fa-trash" style="color: #777;"></i> + </a> + </div>` + ) + }, + '' + )} + </div>` + ) + + html += ( + `<div class="agent-item agent-${machine.guid}"> + <i class="fas fa-chart-bar" color: #fff"></i> + <span class="__title" onClick="return gotoServerModalHandler('${machine.guid}');"> + <a class="registry_link" href="${machine.url}#">${machine.name}</a> + </span> + <a href="#" onClick="toggleAgentItem(event, '${machine.guid}');"> + <i class="fas fa-caret-down" style="color: #999"></i> + </a> + </div> + ${alternateUrlItems}` + ) + } + + if (found && (!displayedAgents)) { + html += ( + `<div class="info-item"> + <i class="fas fa-filter"></i> + <span style="margin-left: 8px">zero nodes are matching the filter value.<span> + </div>` + ) + } + } + + if (!found) { + if (machines) { + html += ( + `<div class="info-item"> + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">Your nodes list is empty</a> + </div>` + ) + } else { + html += ( + `<div class="info-item"> + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">Failed to contact the registry</a> + </div>` + ) + } + + html += `<hr />`; + html += `<div class="info-item">Demo netdata nodes</div>`; + + const demoServers = [ + {url: "//london.netdata.rocks/default.html", title: "UK - London (DigitalOcean.com)"}, + {url: "//newyork.netdata.rocks/default.html", title: "US - New York (DigitalOcean.com)"}, + {url: "//sanfrancisco.netdata.rocks/default.html", title: "US - San Francisco (DigitalOcean.com)"}, + {url: "//atlanta.netdata.rocks/default.html", title: "US - Atlanta (CDN77.com)"}, + {url: "//frankfurt.netdata.rocks/default.html", title: "Germany - Frankfurt (DigitalOcean.com)"}, + {url: "//toronto.netdata.rocks/default.html", title: "Canada - Toronto (DigitalOcean.com)"}, + {url: "//singapore.netdata.rocks/default.html", title: "Japan - Singapore (DigitalOcean.com)"}, + {url: "//bangalore.netdata.rocks/default.html", title: "India - Bangalore (DigitalOcean.com)"}, + + ] + + for (var server of demoServers) { + html += ( + `<div class="agent-item"> + <i class="fas fa-chart-bar" style="color: #fff"></i> + <a href="${server.url}">${server.title}</a> + <div></div> + </div> + ` + ); + } + } + + return html; +} + +function setMyNetdataMenu(html) { + const el = document.getElementById('my-netdata-dropdown-content') + el.innerHTML = html; +} + +function clearMyNetdataMenu() { + setMyNetdataMenu(`<div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-hourglass-half"></i> + Loading, please wait... + <div></div> + </div>`); +} + +function errorMyNetdataMenu() { + setMyNetdataMenu(`<div class="agent-item" style="white-space: nowrap"> + <i class="fas fa-exclamation-triangle" style="color: red"></i> + Cannot load known netdata agents from netdata.cloud! + <div></div> + </div>`); +} + +function restrictMyNetdataMenu() { + setMyNetdataMenu(`<div class="info-item" style="white-space: nowrap"> + <span>Please <a href="#" onclick="signInDidClick(event); return false">sign in to netdata.cloud</a> to view your nodes!</span> + <div></div> + </div>`); +} + +function renderMyNetdataMenu(machinesArray) { + const el = document.getElementById('my-netdata-dropdown-content'); + el.classList.add(`theme-${netdataTheme}`); + + if (!isSignedIn()) { + if (!NETDATA.registry.isRegistryEnabled()) { + restrictMyNetdataMenu(); + return; + } + } + + if (machinesArray == registryAgents) { + console.log("Rendering my-netdata menu from registry"); + } else { + console.log("Rendering my-netdata menu from netdata.cloud", machinesArray); + } + + let html = ''; + + if (isSignedIn()) { + html += ( + `<div class="filter-control"> + <input + id="my-netdata-menu-filter-input" + type="text" + placeholder="filter nodes..." + autofocus + autocomplete="off" + value="${myNetdataMenuFilterValue}" + onkeydown="myNetdataFilterDidChange(event)" + /> + <span class="filter-control__clear" onclick="myNetdataFilterClearDidClick(event)"><i class="fas fa-times"></i><span> + </div> + <hr />` + ); + } + + if (options.hosts.length > 1) { + html += `<div id="my-netdata-menu-streamed">${renderStreamedHosts(options)}</div><hr />`; + } + + html += `<div id="my-netdata-menu-machines">${renderMachines(machinesArray)}</div>`; + + if (!isSignedIn()) { + html += ( + `<hr /> + <div class="agent-item"> + <i class="fas fa-cog""></i> + <a href="#" onclick="switchRegistryModalHandler(); return false;">Switch Identity</a> + <div></div> + </div> + <div class="agent-item"> + <i class="fas fa-question-circle""></i> + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">What is this?</a> + <div></div> + </div>` + ) + } else { + html += ( + `<hr /> + <div class="agent-item"> + <i class="fas fa-sync"></i> + <a href="#" onclick="showSyncModal(); return false">Synchronize with netdata.cloud</a> + <div></div> + </div> + <div class="agent-item"> + <i class="fas fa-question-circle""></i> + <a href="https://netdata.cloud/about" target="_blank">What is this?</a> + <div></div> + </div>` + ) + } + + el.innerHTML = html; + + gotoServerInit(); +} + +function isdemo() { + if (this_is_demo !== null) { + return this_is_demo; + } + this_is_demo = false; + + try { + if (typeof document.location.hostname === 'string') { + if (document.location.hostname.endsWith('.my-netdata.io') || + document.location.hostname.endsWith('.mynetdata.io') || + document.location.hostname.endsWith('.netdata.rocks') || + document.location.hostname.endsWith('.netdata.ai') || + document.location.hostname.endsWith('.netdata.live') || + document.location.hostname.endsWith('.firehol.org') || + document.location.hostname.endsWith('.netdata.online') || + document.location.hostname.endsWith('.netdata.cloud')) { + this_is_demo = true; + } + } + } + catch (error) { + } + return this_is_demo; +} + +function netdataURL(url, forReload) { + if (typeof url === 'undefined') + // url = document.location.toString(); + { + url = ''; + } + + if (url.indexOf('#') !== -1) { + url = url.substring(0, url.indexOf('#')); + } + + var hash = urlOptions.genHash(forReload); + + // console.log('netdataURL: ' + url + hash); + + return url + hash; +} + +function netdataReload(url) { + document.location = verifyURL(netdataURL(url, true)); + + // since we play with hash + // this is needed to reload the page + location.reload(); +} + +function gotoHostedModalHandler(url) { + document.location = verifyURL(url + urlOptions.genHash()); + return false; +} + +var gotoServerValidateRemaining = 0; +var gotoServerMiddleClick = false; +var gotoServerStop = false; + +function gotoServerValidateUrl(id, guid, url) { + var penalty = 0; + var error = 'failed'; + + if (document.location.toString().startsWith('http://') && url.toString().startsWith('https://')) + // we penalize https only if the current url is http + // to allow the user walk through all its servers. + { + penalty = 500; + } else if (document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) { + error = 'can\'t check'; + } + + var finalURL = netdataURL(url); + + setTimeout(function () { + document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + verifyURL(finalURL) + '" target="_blank">' + escapeUserInputHTML(url) + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>'; + + NETDATA.registry.hello(url, function (data) { + if (typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) { + // console.log('OK ' + id + ' URL: ' + url); + document.getElementById(guid + '-' + id + '-status').innerHTML = "OK"; + + if (!gotoServerStop) { + gotoServerStop = true; + + if (gotoServerMiddleClick) { + window.open(verifyURL(finalURL), '_blank'); + gotoServerMiddleClick = false; + document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + verifyURL(finalURL) + '">' + escapeUserInputHTML(url) + '</a></b><br/>(check your pop-up blocker if it fails)'; + } else { + document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + escapeUserInputHTML(url) + '</small>'; + document.location = verifyURL(finalURL); + $('#gotoServerModal').modal('hide'); + } + } + } else { + if (typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid) { + error = 'wrong machine'; + } + + document.getElementById(guid + '-' + id + '-status').innerHTML = error; + gotoServerValidateRemaining--; + if (gotoServerValidateRemaining <= 0) { + gotoServerMiddleClick = false; + document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>'; + } + } + }); + }, (id * 50) + penalty); +} + +function gotoServerModalHandler(guid) { + // console.log('goto server: ' + guid); + + gotoServerStop = false; + var checked = {}; + var len = NETDATA.registry.machines[guid].alternate_urls.length; + var count = 0; + + document.getElementById('gotoServerResponse').innerHTML = ''; + document.getElementById('gotoServerList').innerHTML = ''; + document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name; + $('#gotoServerModal').modal('show'); + + gotoServerValidateRemaining = len; + while (len--) { + var url = NETDATA.registry.machines[guid].alternate_urls[len]; + checked[url] = true; + gotoServerValidateUrl(count++, guid, url); + } + + if (!isSignedIn()) { + // When the registry is enabled, if the user's known URLs are not working + // we consult the registry to get additional URLs. + setTimeout(function () { + if (gotoServerStop === false) { + document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>'; + NETDATA.registry.search(guid, function (data) { + // console.log(data); + len = data.urls.length; + while (len--) { + var url = data.urls[len][1]; + // console.log(url); + if (typeof checked[url] === 'undefined') { + gotoServerValidateRemaining++; + checked[url] = true; + gotoServerValidateUrl(count++, guid, url); + } + } + }); + } + }, 2000); + } + + return false; +} + +function gotoServerInit() { + $(".registry_link").on('click', function (e) { + if (e.which === 2) { + e.preventDefault(); + gotoServerMiddleClick = true; + } else { + gotoServerMiddleClick = false; + } + + return true; + }); +} + +function switchRegistryModalHandler() { + document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid; + document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server; + document.getElementById('switchRegistryResponse').innerHTML = ''; + $('#switchRegistryModal').modal('show'); +} + +function notifyForSwitchRegistry() { + var n = document.getElementById('switchRegistryPersonGUID').value; + + if (n !== '' && n.length === 36) { + NETDATA.registry.switch(n, function (result) { + if (result !== null) { + $('#switchRegistryModal').modal('hide'); + NETDATA.registry.init(); + } else { + document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>"; + } + }); + } else { + document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>"; + } +} + +var deleteRegistryGuid = null; +var deleteRegistryUrl = null; + +function deleteRegistryModalHandler(guid, name, url) { + // void (guid); + + deleteRegistryGuid = guid; + deleteRegistryUrl = url; + + document.getElementById('deleteRegistryServerName').innerHTML = name; + document.getElementById('deleteRegistryServerName2').innerHTML = name; + document.getElementById('deleteRegistryServerURL').innerHTML = url; + document.getElementById('deleteRegistryResponse').innerHTML = ''; + + $('#deleteRegistryModal').modal('show'); +} + +function notifyForDeleteRegistry() { + const responseEl = document.getElementById('deleteRegistryResponse'); + + if (deleteRegistryUrl) { + if (isSignedIn()) { + deleteCloudAgentURL(deleteRegistryGuid, deleteRegistryUrl) + .then((count) => { + if (!count) { + responseEl.innerHTML = "<b>Sorry, this command was rejected by netdata.cloud!</b>"; + return; + } + NETDATA.registry.delete(deleteRegistryUrl, function (result) { + if (result === null) { + console.log("Received error from registry", result); + } + + deleteRegistryUrl = null; + $('#deleteRegistryModal').modal('hide'); + NETDATA.registry.init(); + }); + }); + } else { + NETDATA.registry.delete(deleteRegistryUrl, function (result) { + if (result !== null) { + deleteRegistryUrl = null; + $('#deleteRegistryModal').modal('hide'); + NETDATA.registry.init(); + } else { + responseEl.innerHTML = "<b>Sorry, this command was rejected by the registry server!</b>"; + } + }); + } + } +} + +var options = { + menus: {}, + submenu_names: {}, + data: null, + hostname: 'netdata_server', // will be overwritten by the netdata server + version: 'unknown', + hosts: [], + + duration: 0, // the default duration of the charts + update_every: 1, + + chartsPerRow: 0, + // chartsMinWidth: 1450, + chartsHeight: 180, +}; + +function chartsPerRow(total) { + void (total); + + if (options.chartsPerRow === 0) { + return 1; + //var width = Math.floor(total / options.chartsMinWidth); + //if(width === 0) width = 1; + //return width; + } else { + return options.chartsPerRow; + } +} + +function prioritySort(a, b) { + if (a.priority < b.priority) { + return -1; + } + if (a.priority > b.priority) { + return 1; + } + return naturalSortCompare(a.name, b.name); +} + +function sortObjectByPriority(object) { + var idx = {}; + var sorted = []; + + for (var i in object) { + if (!object.hasOwnProperty(i)) { + continue; + } + + if (typeof idx[i] === 'undefined') { + idx[i] = object[i]; + sorted.push(i); + } + } + + sorted.sort(function (a, b) { + if (idx[a].priority < idx[b].priority) { + return -1; + } + if (idx[a].priority > idx[b].priority) { + return 1; + } + return naturalSortCompare(a, b); + }); + + return sorted; +} + +// ---------------------------------------------------------------------------- +// scroll to a section, without changing the browser history + +function scrollToId(hash) { + if (hash && hash !== '' && document.getElementById(hash) !== null) { + var offset = $('#' + hash).offset(); + if (typeof offset !== 'undefined') { + //console.log('scrolling to ' + hash + ' at ' + offset.top.toString()); + $('html, body').animate({scrollTop: offset.top - 30}, 0); + } + } + + // we must return false to prevent the default action + return false; +} + +// ---------------------------------------------------------------------------- + +// user editable information +var customDashboard = { + menu: {}, + submenu: {}, + context: {} +}; + +// netdata standard information +var netdataDashboard = { + sparklines_registry: {}, + os: 'unknown', + + menu: {}, + submenu: {}, + context: {}, + + // generate a sparkline + // used in the documentation + sparkline: function (prefix, chart, dimension, units, suffix) { + if (options.data === null || typeof options.data.charts === 'undefined') { + return ''; + } + + if (typeof options.data.charts[chart] === 'undefined') { + return ''; + } + + if (typeof options.data.charts[chart].dimensions === 'undefined') { + return ''; + } + + if (typeof options.data.charts[chart].dimensions[dimension] === 'undefined') { + return ''; + } + + var key = chart + '.' + dimension; + + if (typeof units === 'undefined') { + units = ''; + } + + if (typeof this.sparklines_registry[key] === 'undefined') { + this.sparklines_registry[key] = {count: 1}; + } else { + this.sparklines_registry[key].count++; + } + + key = key + '.' + this.sparklines_registry[key].count; + + return prefix + '<div class="netdata-container" data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')' + suffix; + }, + + gaugeChart: function (title, width, dimensions, colors) { + if (typeof colors === 'undefined') { + colors = ''; + } + + if (typeof dimensions === 'undefined') { + dimensions = ''; + } + + return '<div class="netdata-container" data-netdata="CHART_UNIQUE_ID"' + + ' data-dimensions="' + dimensions + '"' + + ' data-chart-library="gauge"' + + ' data-gauge-adjust="width"' + + ' data-title="' + title + '"' + + ' data-width="' + width + '"' + + ' data-before="0"' + + ' data-after="-CHART_DURATION"' + + ' data-points="CHART_DURATION"' + + ' data-colors="' + colors + '"' + + ' role="application"></div>'; + }, + + anyAttribute: function (obj, attr, key, def) { + if (typeof (obj[key]) !== 'undefined') { + var x = obj[key][attr]; + + if (typeof (x) === 'undefined') { + return def; + } + + if (typeof (x) === 'function') { + return x(netdataDashboard.os); + } + + return x; + } + + return def; + }, + + menuTitle: function (chart) { + if (typeof chart.menu_pattern !== 'undefined') { + return (this.anyAttribute(this.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString() + + ' ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' '); + } + + return (this.anyAttribute(this.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' '); + }, + + menuIcon: function (chart) { + if (typeof chart.menu_pattern !== 'undefined') { + return this.anyAttribute(this.menu, 'icon', chart.menu_pattern, '<i class="fas fa-puzzle-piece"></i>').toString(); + } + + return this.anyAttribute(this.menu, 'icon', chart.menu, '<i class="fas fa-puzzle-piece"></i>'); + }, + + menuInfo: function (chart) { + if (typeof chart.menu_pattern !== 'undefined') { + return this.anyAttribute(this.menu, 'info', chart.menu_pattern, null); + } + + return this.anyAttribute(this.menu, 'info', chart.menu, null); + }, + + menuHeight: function (chart) { + if (typeof chart.menu_pattern !== 'undefined') { + return this.anyAttribute(this.menu, 'height', chart.menu_pattern, 1.0); + } + + return this.anyAttribute(this.menu, 'height', chart.menu, 1.0); + }, + + submenuTitle: function (menu, submenu) { + var key = menu + '.' + submenu; + // console.log(key); + var title = this.anyAttribute(this.submenu, 'title', key, submenu).toString().replace(/_/g, ' '); + if (title.length > 28) { + var a = title.substring(0, 13); + var b = title.substring(title.length - 12, title.length); + return a + '...' + b; + } + return title; + }, + + submenuInfo: function (menu, submenu) { + var key = menu + '.' + submenu; + return this.anyAttribute(this.submenu, 'info', key, null); + }, + + submenuHeight: function (menu, submenu, relative) { + var key = menu + '.' + submenu; + return this.anyAttribute(this.submenu, 'height', key, 1.0) * relative; + }, + + contextInfo: function (id) { + var x = this.anyAttribute(this.context, 'info', id, null); + + if (x !== null) { + return '<div class="shorten dashboard-context-info netdata-chart-alignment" role="document">' + x + '</div>'; + } else { + return ''; + } + }, + + contextValueRange: function (id) { + if (typeof this.context[id] !== 'undefined' && typeof this.context[id].valueRange !== 'undefined') { + return this.context[id].valueRange; + } else { + return '[null, null]'; + } + }, + + contextHeight: function (id, def) { + if (typeof this.context[id] !== 'undefined' && typeof this.context[id].height !== 'undefined') { + return def * this.context[id].height; + } else { + return def; + } + }, + + contextDecimalDigits: function (id, def) { + if (typeof this.context[id] !== 'undefined' && typeof this.context[id].decimalDigits !== 'undefined') { + return this.context[id].decimalDigits; + } else { + return def; + } + } +}; + +// ---------------------------------------------------------------------------- + +// enrich the data structure returned by netdata +// to reflect our menu system and content +// TODO: this is a shame - we should fix charts naming (issue #807) +function enrichChartData(chart) { + var parts = chart.type.split('_'); + var tmp = parts[0]; + + switch (tmp) { + case 'ap': + case 'net': + case 'disk': + case 'powersupply': + case 'statsd': + chart.menu = tmp; + break; + + case 'apache': + chart.menu = chart.type; + if (parts.length > 2 && parts[1] === 'cache') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'bind': + chart.menu = chart.type; + if (parts.length > 2 && parts[1] === 'rndc') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'cgroup': + chart.menu = chart.type; + if (chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/)) { + chart.menu_pattern = 'cgqemu'; + } else { + chart.menu_pattern = 'cgroup'; + } + break; + + case 'go': + chart.menu = chart.type; + if (parts.length > 2 && parts[1] === 'expvar') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'isc': + chart.menu = chart.type; + if (parts.length > 2 && parts[1] === 'dhcpd') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'ovpn': + chart.menu = chart.type; + if (parts.length > 3 && parts[1] === 'status' && parts[2] === 'log') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'smartd': + case 'web': + chart.menu = chart.type; + if (parts.length > 2 && parts[1] === 'log') { + chart.menu_pattern = tmp + '_' + parts[1]; + } else if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + + case 'tc': + chart.menu = tmp; + + // find a name for this device from fireqos info + // we strip '_(in|out)' or '(in|out)_' + if (chart.context === 'tc.qos' && (typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family)) { + var n = chart.name.split('.')[1]; + if (n.endsWith('_in')) { + options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in')); + } else if (n.endsWith('_out')) { + options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out')); + } else if (n.startsWith('in_')) { + options.submenu_names[chart.family] = n.slice(3, n.length); + } else if (n.startsWith('out_')) { + options.submenu_names[chart.family] = n.slice(4, n.length); + } else { + options.submenu_names[chart.family] = n; + } + } + + // increase the priority of IFB devices + // to have inbound appear before outbound + if (chart.id.match(/.*-ifb$/)) { + chart.priority--; + } + + break; + + default: + chart.menu = chart.type; + if (parts.length > 1) { + chart.menu_pattern = tmp; + } + break; + } + + chart.submenu = chart.family; +} + +// ---------------------------------------------------------------------------- + +function headMain(os, charts, duration) { + void (os); + + if (urlOptions.mode === 'print') { + return ''; + } + + var head = ''; + + if (typeof charts['system.swap'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.swap"' + + ' data-dimensions="used"' + + ' data-append-options="percentage"' + + ' data-chart-library="easypiechart"' + + ' data-title="Used Swap"' + + ' data-units="%"' + + ' data-easypiechart-max-value="100"' + + ' data-width="9%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-colors="#DD4400"' + + ' role="application"></div>'; + } + + if (typeof charts['system.io'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"' + + ' data-dimensions="in"' + + ' data-chart-library="easypiechart"' + + ' data-title="Disk Read"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.io.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"' + + ' data-dimensions="out"' + + ' data-chart-library="easypiechart"' + + ' data-title="Disk Write"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.io.mainhead"' + + ' role="application"></div>'; + } + else if (typeof charts['system.pgpgio'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"' + + ' data-dimensions="in"' + + ' data-chart-library="easypiechart"' + + ' data-title="Disk Read"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.pgpgio.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"' + + ' data-dimensions="out"' + + ' data-chart-library="easypiechart"' + + ' data-title="Disk Write"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.pgpgio.mainhead"' + + ' role="application"></div>'; + } + + if (typeof charts['system.cpu'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.cpu"' + + ' data-chart-library="gauge"' + + ' data-title="CPU"' + + ' data-units="%"' + + ' data-gauge-max-value="100"' + + ' data-width="20%"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-colors="' + NETDATA.colors[12] + '"' + + ' role="application"></div>'; + } + + if (typeof charts['system.net'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"' + + ' data-dimensions="received"' + + ' data-chart-library="easypiechart"' + + ' data-title="Net Inbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.net.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"' + + ' data-dimensions="sent"' + + ' data-chart-library="easypiechart"' + + ' data-title="Net Outbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.net.mainhead"' + + ' role="application"></div>'; + } + else if (typeof charts['system.ip'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"' + + ' data-dimensions="received"' + + ' data-chart-library="easypiechart"' + + ' data-title="IP Inbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ip.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"' + + ' data-dimensions="sent"' + + ' data-chart-library="easypiechart"' + + ' data-title="IP Outbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ip.mainhead"' + + ' role="application"></div>'; + } + else if (typeof charts['system.ipv4'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"' + + ' data-dimensions="received"' + + ' data-chart-library="easypiechart"' + + ' data-title="IPv4 Inbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ipv4.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"' + + ' data-dimensions="sent"' + + ' data-chart-library="easypiechart"' + + ' data-title="IPv4 Outbound"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ipv4.mainhead"' + + ' role="application"></div>'; + } + else if (typeof charts['system.ipv6'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"' + + ' data-dimensions="received"' + + ' data-chart-library="easypiechart"' + + ' data-title="IPv6 Inbound"' + + ' data-units="kbps"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ipv6.mainhead"' + + ' role="application"></div>'; + + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"' + + ' data-dimensions="sent"' + + ' data-chart-library="easypiechart"' + + ' data-title="IPv6 Outbound"' + + ' data-units="kbps"' + + ' data-width="11%"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-common-units="system.ipv6.mainhead"' + + ' role="application"></div>'; + } + + if (typeof charts['system.ram'] !== 'undefined') { + head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ram"' + + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats + + ' data-append-options="percentage"' + + ' data-chart-library="easypiechart"' + + ' data-title="Used RAM"' + + ' data-units="%"' + + ' data-easypiechart-max-value="100"' + + ' data-width="9%"' + + ' data-after="-' + duration.toString() + '"' + + ' data-points="' + duration.toString() + '"' + + ' data-colors="' + NETDATA.colors[7] + '"' + + ' role="application"></div>'; + } + + return head; +} + +function generateHeadCharts(type, chart, duration) { + if (urlOptions.mode === 'print') { + return ''; + } + + var head = ''; + var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []); + if (hcharts.length > 0) { + var hi = 0, hlen = hcharts.length; + while (hi < hlen) { + if (typeof hcharts[hi] === 'function') { + head += hcharts[hi](netdataDashboard.os, chart.id).replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id); + } else { + head += hcharts[hi].replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id); + } + hi++; + } + } + return head; +} + +function renderPage(menus, data) { + var div = document.getElementById('charts_div'); + var pcent_width = Math.floor(100 / chartsPerRow($(div).width())); + + // find the proper duration for per-second updates + var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60; + options.duration = duration; + options.update_every = data.update_every; + + var html = ''; + var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">'; + var mainhead = headMain(netdataDashboard.os, data.charts, duration); + + // sort the menus + var main = sortObjectByPriority(menus); + var i = 0, len = main.length; + while (i < len) { + var menu = main[i++]; + + // generate an entry at the main menu + + var menuid = NETDATA.name2id('menu_' + menu); + sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">'; + html += '<div role="section" class="dashboard-section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].icon + ' ' + menus[menu].title + '</h1></div><div role="section" class="dashboard-subsection">'; + + if (menus[menu].info !== null) { + html += menus[menu].info; + } + + // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title); + + var shtml = ''; + var mhead = '<div class="netdata-chart-row">' + mainhead; + mainhead = ''; + + // sort the submenus of this menu + var sub = sortObjectByPriority(menus[menu].submenus); + var si = 0, slen = sub.length; + while (si < slen) { + var submenu = sub[si++]; + + // generate an entry at the submenu + var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu); + sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>'; + shtml += '<div role="section" class="dashboard-section-container" id="' + submenuid + '"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>'; + + if (menus[menu].submenus[submenu].info !== null) { + shtml += '<div class="dashboard-submenu-info netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>'; + } + + var head = '<div class="netdata-chart-row">'; + var chtml = ''; + + // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title); + + // sort the charts in this submenu of this menu + menus[menu].submenus[submenu].charts.sort(prioritySort); + var ci = 0, clen = menus[menu].submenus[submenu].charts.length; + while (ci < clen) { + var chart = menus[menu].submenus[submenu].charts[ci++]; + + // generate the submenu heading charts + mhead += generateHeadCharts('mainheads', chart, duration); + head += generateHeadCharts('heads', chart, duration); + + function chartCommonMin(family, context, units) { + var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMin', context, undefined); + if (typeof x !== 'undefined') { + return ' data-common-min="' + family + '/' + context + '/' + units + '"'; + } else { + return ''; + } + } + + function chartCommonMax(family, context, units) { + var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMax', context, undefined); + if (typeof x !== 'undefined') { + return ' data-common-max="' + family + '/' + context + '/' + units + '"'; + } else { + return ''; + } + } + + // generate the chart + if (urlOptions.mode === 'print') { + chtml += '<div role="row" class="dashboard-print-row">'; + } + + chtml += '<div class="netdata-chartblock-container" style="width: ' + pcent_width.toString() + '%;">' + netdataDashboard.contextInfo(chart.context) + '<div class="netdata-container" id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"' + + ' data-width="100%"' + + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"' + + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"' + + ' data-before="0"' + + ' data-after="-' + duration.toString() + '"' + + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"' + + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"' + + ' data-decimal-digits="' + netdataDashboard.contextDecimalDigits(chart.context, -1) + '"' + + chartCommonMin(chart.family, chart.context, chart.units) + + chartCommonMax(chart.family, chart.context, chart.units) + + ' role="application"></div></div>'; + + if (urlOptions.mode === 'print') { + chtml += '</div>'; + } + + // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height); + } + + head += '</div>'; + shtml += head + chtml + '</div>'; + } + + mhead += '</div>'; + sidebar += '</ul></li>'; + html += mhead + shtml + '</div></div><hr role="separator"/>'; + } + + sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/netdata/netdata/blob/master/docs/Add-more-charts-to-netdata.md#add-more-charts-to-netdata" target="_blank"><i class="fas fa-plus"></i> add more charts</a></li>'; + sidebar += '<li class=""><a href="https://github.com/netdata/netdata/tree/master/health#Health-monitoring" target="_blank"><i class="fas fa-plus"></i> add more alarms</a></li>'; + sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every === 1) ? 'second' : data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + NETDATA.seconds4human(data.update_every * data.history, {space: ' '}) + ' of real-time history.<br/> <br/><b>netdata</b><br/>' + data.version.toString() + '</small></li>'; + sidebar += '</ul>'; + div.innerHTML = html; + document.getElementById('sidebar').innerHTML = sidebar; + + if (urlOptions.highlight === true) { + NETDATA.globalChartUnderlay.init(null + , urlOptions.highlight_after + , urlOptions.highlight_before + , (urlOptions.after > 0) ? urlOptions.after : null + , (urlOptions.before > 0) ? urlOptions.before : null + ); + } else { + NETDATA.globalChartUnderlay.clear(); + } + + if (urlOptions.mode === 'print') { + printPage(); + } else { + finalizePage(); + } +} + +function renderChartsAndMenu(data) { + options.menus = {}; + options.submenu_names = {}; + + var menus = options.menus; + var charts = data.charts; + var m, menu_key; + + for (var c in charts) { + if (!charts.hasOwnProperty(c)) { + continue; + } + + var chart = charts[c]; + enrichChartData(chart); + m = chart.menu; + + // create the menu + if (typeof menus[m] === 'undefined') { + menus[m] = { + menu_pattern: chart.menu_pattern, + priority: chart.priority, + submenus: {}, + title: netdataDashboard.menuTitle(chart), + icon: netdataDashboard.menuIcon(chart), + info: netdataDashboard.menuInfo(chart), + height: netdataDashboard.menuHeight(chart) * options.chartsHeight + }; + } else { + if (typeof (menus[m].menu_pattern) === 'undefined') { + menus[m].menu_pattern = chart.menu_pattern; + } + + if (chart.priority < menus[m].priority) { + menus[m].priority = chart.priority; + } + } + + menu_key = (typeof (menus[m].menu_pattern) !== 'undefined') ? menus[m].menu_pattern : m; + + // create the submenu + if (typeof menus[m].submenus[chart.submenu] === 'undefined') { + menus[m].submenus[chart.submenu] = { + priority: chart.priority, + charts: [], + title: null, + info: netdataDashboard.submenuInfo(menu_key, chart.submenu), + height: netdataDashboard.submenuHeight(menu_key, chart.submenu, menus[m].height) + }; + } else { + if (chart.priority < menus[m].submenus[chart.submenu].priority) { + menus[m].submenus[chart.submenu].priority = chart.priority; + } + } + + // index the chart in the menu/submenu + menus[m].submenus[chart.submenu].charts.push(chart); + } + + // propagate the descriptive subname given to QoS + // to all the other submenus with the same name + for (var m in menus) { + if (!menus.hasOwnProperty(m)) { + continue; + } + + for (var s in menus[m].submenus) { + if (!menus[m].submenus.hasOwnProperty(s)) { + continue; + } + + // set the family using a name + if (typeof options.submenu_names[s] !== 'undefined') { + menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')'; + } else { + menu_key = (typeof (menus[m].menu_pattern) !== 'undefined') ? menus[m].menu_pattern : m; + menus[m].submenus[s].title = netdataDashboard.submenuTitle(menu_key, s); + } + } + } + + renderPage(menus, data); +} + +// ---------------------------------------------------------------------------- + +function loadJs(url, callback) { + $.ajax({ + url: url, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .fail(function () { + alert('Cannot load required JS library: ' + url); + }) + .always(function () { + if (typeof callback === 'function') { + callback(); + } + }) +} + +var clipboardLoaded = false; + +function loadClipboard(callback) { + if (clipboardLoaded === false) { + clipboardLoaded = true; + loadJs('lib/clipboard-polyfill-be05dad.js', callback); + } else { + callback(); + } +} + +var bootstrapTableLoaded = false; + +function loadBootstrapTable(callback) { + if (bootstrapTableLoaded === false) { + bootstrapTableLoaded = true; + loadJs('lib/bootstrap-table-1.11.0.min.js', function () { + loadJs('lib/bootstrap-table-export-1.11.0.min.js', function () { + loadJs('lib/tableExport-1.6.0.min.js', callback); + }) + }); + } else { + callback(); + } +} + +var bootstrapSliderLoaded = false; + +function loadBootstrapSlider(callback) { + if (bootstrapSliderLoaded === false) { + bootstrapSliderLoaded = true; + loadJs('lib/bootstrap-slider-10.0.0.min.js', function () { + NETDATA._loadCSS('css/bootstrap-slider-10.0.0.min.css'); + callback(); + }); + } else { + callback(); + } +} + +var lzStringLoaded = false; + +function loadLzString(callback) { + if (lzStringLoaded === false) { + lzStringLoaded = true; + loadJs('lib/lz-string-1.4.4.min.js', callback); + } else { + callback(); + } +} + +var pakoLoaded = false; + +function loadPako(callback) { + if (pakoLoaded === false) { + pakoLoaded = true; + loadJs('lib/pako-1.0.6.min.js', callback); + } else { + callback(); + } +} + +// ---------------------------------------------------------------------------- + +function clipboardCopy(text) { + clipboard.writeText(text); +} + +function clipboardCopyBadgeEmbed(url) { + clipboard.writeText('<embed src="' + url + '" type="image/svg+xml" height="20"/>'); +} + +// ---------------------------------------------------------------------------- + +function alarmsUpdateModal() { + var active = '<h3>Raised Alarms</h3><table class="table">'; + var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">'; + var footer = '<hr/><a href="https://github.com/netdata/netdata/tree/master/web/api/badges#netdata-badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b> red </b></span> is critical, <span style="color:#fe7d37"><b> orange </b></span> is warning, <span style="color: #4c1"><b> bright green </b></span> is ok, <span style="color: #9f9f9f"><b> light grey </b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b> black </b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/netdata/netdata/blob/master/health/notifications/health_alarm_notify.conf">this configuration file</a> for more information.'; + + loadClipboard(function () { + }); + + NETDATA.alarms.get('all', function (data) { + options.alarm_families = []; + + alarmsCallback(data); + + if (data === null) { + document.getElementById('alarms_active').innerHTML = + document.getElementById('alarms_all').innerHTML = + document.getElementById('alarms_log').innerHTML = + 'failed to load alarm data!'; + return; + } + + function alarmid4human(id) { + if (id === 0) { + return '-'; + } + + return id.toString(); + } + + function timestamp4human(timestamp, space) { + if (timestamp === 0) { + return '-'; + } + + if (typeof space === 'undefined') { + space = ' '; + } + + var t = new Date(timestamp * 1000); + var now = new Date(); + + if (t.toDateString() === now.toDateString()) { + return t.toLocaleTimeString(); + } + + return t.toLocaleDateString() + space + t.toLocaleTimeString(); + } + + function alarm_lookup_explain(alarm, chart) { + var dimensions = ' of all values '; + + if (chart.dimensions.length > 1) { + dimensions = ' of the sum of all dimensions '; + } + + if (typeof alarm.lookup_dimensions !== 'undefined') { + var d = alarm.lookup_dimensions.replace(/|/g, ','); + var x = d.split(','); + if (x.length > 1) { + dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> '; + } else { + dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> '; + } + } + + return '<code>' + alarm.lookup_method + '</code> ' + + dimensions + ', of chart <code>' + alarm.chart + '</code>' + + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, {space: ' '}) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, {space: ' '}) + '</code>' + + ((alarm.lookup_options) ? (', with options <code>' + alarm.lookup_options.replace(/ /g, ', ') + '</code>') : '') + + '.'; + } + + function alarm_to_html(alarm, full) { + var chart = options.data.charts[alarm.chart]; + if (typeof (chart) === 'undefined') { + chart = options.data.charts_by_name[alarm.chart]; + if (typeof (chart) === 'undefined') { + // this means the charts loaded are incomplete + // probably netdata was restarted and more alarms + // are now available. + console.log('Cannot find chart ' + alarm.chart + ', you probably need to refresh the page.'); + return ''; + } + } + + var has_alarm = (typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined'); + var badge_url = NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto'; + + var action_buttons = '<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/>' + + '<div class="action-button ripple" title="click to scroll the dashboard to the chart of this alarm" data-toggle="tooltip" data-placement="bottom" onClick="scrollToChartAfterHidingModal(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>' + + '<div class="action-button ripple" title="click to copy to the clipboard the URL of this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopy(\'' + badge_url + '\'); return false;"><i class="far fa-copy"></i></div>' + + '<div class="action-button ripple" title="click to copy to the clipboard an auto-refreshing <code>embed</code> html element for this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopyBadgeEmbed(\'' + badge_url + '\'); return false;"><i class="fas fa-copy"></i></div>'; + + var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <br/><embed src="' + badge_url + '" type="image/svg+xml" height="20"/><br/> <br/><span style="font-size: 18px">' + alarm.info + '</span>' + action_buttons + '</td>' + + '<td><table class="table">' + + ((typeof alarm.warn !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">warning when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>') : '') + + ((typeof alarm.crit !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">critical when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>') : ''); + + if (full === true) { + var units = chart.units; + if (units === '%') { + units = '%'; + } + + html += ((typeof alarm.lookup_after !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">db lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>') : '') + + ((typeof alarm.calc !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>') : '') + + ((chart.green !== null) ? ('<tr><td width="10%" style="text-align:right">green threshold</td><td><code>' + chart.green + ' ' + units + '</code></td></tr>') : '') + + ((chart.red !== null) ? ('<tr><td width="10%" style="text-align:right">red threshold</td><td><code>' + chart.red + ' ' + units + '</code></td></tr>') : ''); + } + + var delay = ''; + if ((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier !== 0 && alarm.delay_max_duration > 0) { + if (alarm.delay_up_duration === alarm.delay_down_duration) { + delay += '<small><br/>hysteresis ' + NETDATA.seconds4human(alarm.delay_up_duration, { + space: ' ', + negative_suffix: '' + }); + } else { + delay = '<small><br/>hysteresis '; + if (alarm.delay_up_duration > 0) { + delay += 'on escalation <code>' + NETDATA.seconds4human(alarm.delay_up_duration, { + space: ' ', + negative_suffix: '' + }) + '</code>, '; + } + if (alarm.delay_down_duration > 0) { + delay += 'on recovery <code>' + NETDATA.seconds4human(alarm.delay_down_duration, { + space: ' ', + negative_suffix: '' + }) + '</code>, '; + } + } + if (alarm.delay_multiplier !== 1.0) { + delay += 'multiplied by <code>' + alarm.delay_multiplier.toString() + '</code>'; + delay += ', up to <code>' + NETDATA.seconds4human(alarm.delay_max_duration, { + space: ' ', + negative_suffix: '' + }) + '</code>'; + } + delay += '</small>'; + } + + html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + NETDATA.seconds4human(alarm.update_every, { + space: ' ', + negative_suffix: '' + }) + '</td></tr>' + + ((has_alarm === true) ? ('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>') : '') + + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>' + + '</table></td></tr>'; + + return html; + } + + function alarm_family_show(id) { + var html = '<table class="table">'; + var family = options.alarm_families[id]; + var len = family.arr.length; + while (len--) { + var alarm = family.arr[len]; + html += alarm_to_html(alarm, true); + } + html += '</table>'; + + $('#alarm_all_' + id.toString()).html(html); + enableTooltipsAndPopovers(); + } + + // find the proper family of each alarm + var x, family, alarm; + var count_active = 0; + var count_all = 0; + var families = {}; + var families_sort = []; + for (x in data.alarms) { + if (!data.alarms.hasOwnProperty(x)) { + continue; + } + + alarm = data.alarms[x]; + family = alarm.family; + + // find the chart + var chart = options.data.charts[alarm.chart]; + if (typeof chart === 'undefined') { + chart = options.data.charts_by_name[alarm.chart]; + } + + // not found - this should never happen! + if (typeof chart === 'undefined') { + console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.'); + chart = {priority: 9999999}; + } + else if (typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined') + // the family based on the chart + { + family = chart.menu + ' - ' + chart.submenu; + } + + if (typeof families[family] === 'undefined') { + families[family] = { + name: family, + arr: [], + priority: chart.priority + }; + + families_sort.push(families[family]); + } + + if (chart.priority < families[family].priority) { + families[family].priority = chart.priority; + } + + families[family].arr.unshift(alarm); + } + + // sort the families, like the dashboard menu does + var families_sorted = families_sort.sort(function (a, b) { + if (a.priority < b.priority) { + return -1; + } + if (a.priority > b.priority) { + return 1; + } + return naturalSortCompare(a.name, b.name); + }); + + var i = 0; + var fc = 0; + var len = families_sorted.length; + while (len--) { + family = families_sorted[i++].name; + var active_family_added = false; + var expanded = 'true'; + var collapsed = ''; + var cin = 'in'; + + if (fc !== 0) { + all += "</table></div></div></div>"; + expanded = 'false'; + collapsed = 'class="collapsed"'; + cin = ''; + } + + all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">'; + + options.alarm_families[fc] = families[family]; + + fc++; + + var arr = families[family].arr; + var c = arr.length; + while (c--) { + alarm = arr[c]; + if (alarm.status === 'WARNING' || alarm.status === 'CRITICAL') { + if (!active_family_added) { + active_family_added = true; + active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>'; + } + count_active++; + active += alarm_to_html(alarm, true); + } + + count_all++; + } + } + active += "</table>"; + if (families_sorted.length > 0) { + all += "</div></div></div>"; + } + all += "</div>"; + + if (!count_active) { + active += '<div style="width:100%; height: 100px; text-align: center;"><span style="font-size: 50px;"><i class="fas fa-thumbs-up"></i></span><br/>Everything is normal. No raised alarms.</div>'; + } else { + active += footer; + } + + if (!count_all) { + all += "<h4>No alarms are running in this system.</h4>"; + } else { + all += footer; + } + + document.getElementById('alarms_active').innerHTML = active; + document.getElementById('alarms_all').innerHTML = all; + enableTooltipsAndPopovers(); + + if (families_sorted.length > 0) { + alarm_family_show(0); + } + + // register bootstrap events + var $accordion = $('#alarms_all_accordion'); + $accordion.on('show.bs.collapse', function (d) { + var target = $(d.target); + var id = $(target).data('alarm-id'); + alarm_family_show(id); + }); + $accordion.on('hidden.bs.collapse', function (d) { + var target = $(d.target); + var id = $(target).data('alarm-id'); + $('#alarm_all_' + id.toString()).html(''); + }); + + document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>'; + + loadBootstrapTable(function () { + $('#alarms_log_table').bootstrapTable({ + url: NETDATA.alarms.server + '/api/v1/alarm_log?all', + cache: false, + pagination: true, + pageSize: 10, + showPaginationSwitch: false, + search: true, + searchTimeOut: 300, + searchAlign: 'left', + showColumns: true, + showExport: true, + exportDataType: 'basic', + exportOptions: { + fileName: 'netdata_alarm_log' + }, + rowStyle: function (row, index) { + void (index); + + switch (row.status) { + case 'CRITICAL': + return {classes: 'danger'}; + break; + case 'WARNING': + return {classes: 'warning'}; + break; + case 'UNDEFINED': + return {classes: 'info'}; + break; + case 'CLEAR': + return {classes: 'success'}; + break; + } + return {}; + }, + showFooter: false, + showHeader: true, + showRefresh: true, + showToggle: false, + sortable: true, + silentSort: false, + columns: [ + { + field: 'when', + title: 'Event Date', + valign: 'middle', + titleTooltip: 'The date and time the even took place', + formatter: function (value, row, index) { + void (row); + void (index); + return timestamp4human(value, ' '); + }, + align: 'center', + switchable: false, + sortable: true + }, + { + field: 'hostname', + title: 'Host', + valign: 'middle', + titleTooltip: 'The host that generated this event', + align: 'center', + visible: false, + sortable: true + }, + { + field: 'unique_id', + title: 'Unique ID', + titleTooltip: 'The host unique ID for this event', + formatter: function (value, row, index) { + void (row); + void (index); + return alarmid4human(value); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'alarm_id', + title: 'Alarm ID', + titleTooltip: 'The ID of the alarm that generated this event', + formatter: function (value, row, index) { + void (row); + void (index); + return alarmid4human(value); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'alarm_event_id', + title: 'Alarm Event ID', + titleTooltip: 'The incremental ID of this event for the given alarm', + formatter: function (value, row, index) { + void (row); + void (index); + return alarmid4human(value); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'chart', + title: 'Chart', + titleTooltip: 'The chart the alarm is attached to', + align: 'center', + valign: 'middle', + switchable: false, + sortable: true + }, + { + field: 'family', + title: 'Family', + titleTooltip: 'The family of the chart the alarm is attached to', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'name', + title: 'Alarm', + titleTooltip: 'The alarm name that generated this event', + formatter: function (value, row, index) { + void (row); + void (index); + return value.toString().replace(/_/g, ' '); + }, + align: 'center', + valign: 'middle', + switchable: false, + sortable: true + }, + { + field: 'value_string', + title: 'Friendly Value', + titleTooltip: 'The value of the alarm, that triggered this event', + align: 'right', + valign: 'middle', + sortable: true + }, + { + field: 'old_value_string', + title: 'Friendly Old Value', + titleTooltip: 'The value of the alarm, just before this event', + align: 'right', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'old_value', + title: 'Old Value', + titleTooltip: 'The value of the alarm, just before this event', + formatter: function (value, row, index) { + void (row); + void (index); + return ((value !== null) ? Math.round(value * 100) / 100 : 'NaN').toString(); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'value', + title: 'Value', + titleTooltip: 'The value of the alarm, that triggered this event', + formatter: function (value, row, index) { + void (row); + void (index); + return ((value !== null) ? Math.round(value * 100) / 100 : 'NaN').toString(); + }, + align: 'right', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'units', + title: 'Units', + titleTooltip: 'The units of the value of the alarm', + align: 'left', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'old_status', + title: 'Old Status', + titleTooltip: 'The status of the alarm, just before this event', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'status', + title: 'Status', + titleTooltip: 'The status of the alarm, that was set due to this event', + align: 'center', + valign: 'middle', + switchable: false, + sortable: true + }, + { + field: 'duration', + title: 'Last Duration', + titleTooltip: 'The duration the alarm was at its previous state, just before this event', + formatter: function (value, row, index) { + void (row); + void (index); + return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'}); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'non_clear_duration', + title: 'Raised Duration', + titleTooltip: 'The duration the alarm was raised, just before this event', + formatter: function (value, row, index) { + void (row); + void (index); + return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'}); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'recipient', + title: 'Recipient', + titleTooltip: 'The recipient of this event', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'processed', + title: 'Processed Status', + titleTooltip: 'True when this event is processed', + formatter: function (value, row, index) { + void (row); + void (index); + + if (value === true) { + return 'DONE'; + } else { + return 'PENDING'; + } + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'updated', + title: 'Updated Status', + titleTooltip: 'True when this event has been updated by another event', + formatter: function (value, row, index) { + void (row); + void (index); + + if (value === true) { + return 'UPDATED'; + } else { + return 'CURRENT'; + } + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'updated_by_id', + title: 'Updated By ID', + titleTooltip: 'The unique ID of the event that obsoleted this one', + formatter: function (value, row, index) { + void (row); + void (index); + return alarmid4human(value); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'updates_id', + title: 'Updates ID', + titleTooltip: 'The unique ID of the event obsoleted because of this event', + formatter: function (value, row, index) { + void (row); + void (index); + return alarmid4human(value); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'exec', + title: 'Script', + titleTooltip: 'The script to handle the event notification', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'exec_run', + title: 'Script Run At', + titleTooltip: 'The date and time the script has been ran', + formatter: function (value, row, index) { + void (row); + void (index); + return timestamp4human(value, ' '); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'exec_code', + title: 'Script Return Value', + titleTooltip: 'The return code of the script', + formatter: function (value, row, index) { + void (row); + void (index); + + if (value === 0) { + return 'OK (returned 0)'; + } else { + return 'FAILED (with code ' + value.toString() + ')'; + } + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'delay', + title: 'Script Delay', + titleTooltip: 'The hysteresis of the notification', + formatter: function (value, row, index) { + void (row); + void (index); + + return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'}); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'delay_up_to_timestamp', + title: 'Script Delay Run At', + titleTooltip: 'The date and time the script should be run, after hysteresis', + formatter: function (value, row, index) { + void (row); + void (index); + return timestamp4human(value, ' '); + }, + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'info', + title: 'Description', + titleTooltip: 'A short description of the alarm', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + }, + { + field: 'source', + title: 'Alarm Source', + titleTooltip: 'The source of configuration of the alarm', + align: 'center', + valign: 'middle', + visible: false, + sortable: true + } + ] + }); + // console.log($('#alarms_log_table').bootstrapTable('getOptions')); + }); + }); +} + +function alarmsCallback(data) { + var count = 0, x; + for (x in data.alarms) { + if (!data.alarms.hasOwnProperty(x)) { + continue; + } + + var alarm = data.alarms[x]; + if (alarm.status === 'WARNING' || alarm.status === 'CRITICAL') { + count++; + } + } + + if (count > 0) { + document.getElementById('alarms_count_badge').innerHTML = count.toString(); + } else { + document.getElementById('alarms_count_badge').innerHTML = ''; + } +} + +function initializeDynamicDashboardWithData(data) { + if (data !== null) { + options.hostname = data.hostname; + options.data = data; + options.version = data.version; + netdataDashboard.os = data.os; + + if (typeof data.hosts !== 'undefined') { + options.hosts = data.hosts; + } + + // update the dashboard hostname + document.getElementById('hostname').innerHTML = options.hostname + ((netdataSnapshotData !== null) ? ' (snap)' : '').toString() + ' <strong class="caret">'; + document.getElementById('hostname').href = NETDATA.serverDefault; + document.getElementById('netdataVersion').innerHTML = options.version; + + if (netdataSnapshotData !== null) { + $('#alarmsButton').hide(); + $('#updateButton').hide(); + // $('#loadButton').hide(); + $('#saveButton').hide(); + $('#printButton').hide(); + } + + // update the dashboard title + document.title = options.hostname + ' netdata dashboard'; + + // close the splash screen + $("#loadOverlay").css("display", "none"); + + // create a chart_by_name index + data.charts_by_name = {}; + var charts = data.charts; + var x; + for (x in charts) { + if (!charts.hasOwnProperty(x)) { + continue; + } + + var chart = charts[x]; + data.charts_by_name[chart.name] = chart; + } + + // render all charts + renderChartsAndMenu(data); + } +} + +// an object to keep initilization configuration +// needed due to the async nature of the XSS modal +var initializeConfig = { + url: null, + custom_info: true, +}; + +function loadCustomDashboardInfo(url, callback) { + loadJs(url, function () { + $.extend(true, netdataDashboard, customDashboard); + callback(); + }); +} + +function initializeChartsAndCustomInfo() { + NETDATA.alarms.callback = alarmsCallback; + + // download all the charts the server knows + NETDATA.chartRegistry.downloadAll(initializeConfig.url, function (data) { + if (data !== null) { + if (initializeConfig.custom_info === true && typeof data.custom_info !== 'undefined' && data.custom_info !== "" && netdataSnapshotData === null) { + //console.log('loading custom dashboard decorations from server ' + initializeConfig.url); + loadCustomDashboardInfo(NETDATA.serverDefault + data.custom_info, function () { + initializeDynamicDashboardWithData(data); + }); + } else { + //console.log('not loading custom dashboard decorations from server ' + initializeConfig.url); + initializeDynamicDashboardWithData(data); + } + } + }); +} + +function xssModalDisableXss() { + //console.log('disabling xss checks'); + NETDATA.xss.enabled = false; + NETDATA.xss.enabled_for_data = false; + initializeConfig.custom_info = true; + initializeChartsAndCustomInfo(); + return false; +} + +function xssModalKeepXss() { + //console.log('keeping xss checks'); + NETDATA.xss.enabled = true; + NETDATA.xss.enabled_for_data = true; + initializeConfig.custom_info = false; + initializeChartsAndCustomInfo(); + return false; +} + +function initializeDynamicDashboard(netdata_url) { + if (typeof netdata_url === 'undefined' || netdata_url === null) { + netdata_url = NETDATA.serverDefault; + } + + initializeConfig.url = netdata_url; + + // initialize clickable alarms + NETDATA.alarms.chart_div_offset = -50; + NETDATA.alarms.chart_div_id_prefix = 'chart_'; + NETDATA.alarms.chart_div_animation_duration = 0; + + NETDATA.pause(function () { + if (typeof netdataCheckXSS !== 'undefined' && netdataCheckXSS === true) { + //$("#loadOverlay").css("display","none"); + document.getElementById('netdataXssModalServer').innerText = initializeConfig.url; + $('#xssModal').modal('show'); + } else { + initializeChartsAndCustomInfo(); + } + }); +} + +// ---------------------------------------------------------------------------- + +function versionLog(msg) { + document.getElementById('versionCheckLog').innerHTML = msg; +} + +// New way of checking for updates, based only on versions + +function versionsMatch(v1, v2) { + if (v1 == v2) { + return true; + } else { + var s1=v1.split('-'); + var s2=v2.split('-'); + if (s1.length !== s2.length) return false; + if (s1.length === 4) s1.pop(); + if (s2.length === 4) s2.pop(); + return (s1.join('-') === s2.join('-')); + } +} + +function getGithubLatestVersion(callback) { + versionLog('Downloading latest version id from github...'); + + $.ajax({ + url: 'https://api.github.com/repositories/10744183/contents/packaging/version?ref=master', + async: true, + cache: false + }) + .done(function (data) { + data = atob(data.content.replace(/(\r\n|\n|\r| |\t)/gm, "")); + versionLog('Latest version from github is ' + data); + callback(data); + }) + .fail(function () { + versionLog('Failed to download the latest version id from github!'); + callback(null); + }); +} + +function checkForUpdateByVersion(force, callback) { + getGithubLatestVersion(function (sha2) { + callback(options.version, sha2); + }); + + return null; +} + +function notifyForUpdate(force) { + versionLog('<p>checking for updates...</p>'); + + var now = Date.now(); + + if (typeof force === 'undefined' || force !== true) { + var last = loadLocalStorage('last_update_check'); + + if (typeof last === 'string') { + last = parseInt(last); + } else { + last = 0; + } + + if (now - last < 3600000 * 8) { + // no need to check it - too soon + return; + } + } + + checkForUpdateByVersion(force, function (sha1, sha2) { + var save = false; + + if (sha1 === null) { + save = false; + versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>'); + } else if (sha2 === null) { + save = false; + versionLog('<p><big>Failed to get the latest netdata version github.</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>'); + } else if (versionsMatch(sha1, sha2)) { + save = true; + versionLog('<p><big>You already have the latest netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/netdata/netdata" target="_blank">give netdata a <b><i class="fas fa-star"></i></b> at its github page</a>.</p>'); + } else { + save = true; + var compare = 'https://docs.netdata.cloud/changelog/'; + versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: <b><code>' + sha2 + '</code></b></p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> and<br/><a href="https://github.com/netdata/netdata/tree/master/packaging/installer/UPDATE.md" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated is generally a good idea.</p>'); + + document.getElementById('update_badge').innerHTML = '!'; + } + + if (save) { + saveLocalStorage('last_update_check', now.toString()); + } + }); +} + +// ---------------------------------------------------------------------------- +// printing dashboards + +function showPageFooter() { + document.getElementById('footer').style.display = 'block'; +} + +function printPreflight() { + var url = document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString() + urlOptions.genHash() + ';mode=print'; + var width = 990; + var height = screen.height * 90 / 100; + //console.log(url); + //console.log(document.location); + window.open(url, '', 'width=' + width.toString() + ',height=' + height.toString() + ',menubar=no,toolbar=no,personalbar=no,location=no,resizable=no,scrollbars=yes,status=no,chrome=yes,centerscreen=yes,attention=yes,dialog=yes'); + $('#printPreflightModal').modal('hide'); +} + +function printPage() { + var print_is_rendering = true; + + $('#printModal').on('hide.bs.modal', function (e) { + if (print_is_rendering === true) { + e.preventDefault(); + return false; + } + + return true; + }); + + $('#printModal').on('show.bs.modal', function () { + var print_options = { + stop_updates_when_focus_is_lost: false, + update_only_visible: false, + sync_selection: false, + eliminate_zero_dimensions: false, + pan_and_zoom_data_padding: false, + show_help: false, + legend_toolbox: false, + resize_charts: false, + pixels_per_point: 1 + }; + + var x; + for (x in print_options) { + if (print_options.hasOwnProperty(x)) { + NETDATA.options.current[x] = print_options[x]; + } + } + + NETDATA.parseDom(); + showPageFooter(); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before); + // NETDATA.onresize(); + + var el = document.getElementById('printModalProgressBar'); + var eltxt = document.getElementById('printModalProgressBarText'); + + function update_chart(idx) { + var state = NETDATA.options.targets[--idx]; + + var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length; + $(el).css('width', pcent + '%').attr('aria-valuenow', pcent); + eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id; + + setTimeout(function () { + state.updateChart(function () { + NETDATA.options.targets[idx].resizeForPrint(); + + if (idx > 0) { + update_chart(idx); + } else { + print_is_rendering = false; + $('#printModal').modal('hide'); + window.print(); + window.close(); + } + }) + }, 0); + } + + print_is_rendering = true; + update_chart(NETDATA.options.targets.length); + }); + + $('#printModal').modal('show'); +} + +// -------------------------------------------------------------------- + +function jsonStringifyFn(obj) { + return JSON.stringify(obj, function (key, value) { + return (typeof value === 'function') ? value.toString() : value; + }); +} + +function jsonParseFn(str) { + return JSON.parse(str, function (key, value) { + if (typeof value != 'string') { + return value; + } + return (value.substring(0, 8) == 'function') ? eval('(' + value + ')') : value; + }); +} + +// -------------------------------------------------------------------- + +var snapshotOptions = { + bytes_per_chart: 2048, + compressionDefault: 'pako.deflate.base64', + + compressions: { + 'none': { + bytes_per_point_memory: 5.2, + bytes_per_point_disk: 5.6, + + compress: function (s) { + return s; + }, + + compressed_length: function (s) { + return s.length; + }, + + uncompress: function (s) { + return s; + } + }, + + 'pako.deflate.base64': { + bytes_per_point_memory: 1.8, + bytes_per_point_disk: 1.9, + + compress: function (s) { + return btoa(pako.deflate(s, {to: 'string'})); + }, + + compressed_length: function (s) { + return s.length; + }, + + uncompress: function (s) { + return pako.inflate(atob(s), {to: 'string'}); + } + }, + + 'pako.deflate': { + bytes_per_point_memory: 1.4, + bytes_per_point_disk: 3.2, + + compress: function (s) { + return pako.deflate(s, {to: 'string'}); + }, + + compressed_length: function (s) { + return s.length; + }, + + uncompress: function (s) { + return pako.inflate(s, {to: 'string'}); + } + }, + + 'lzstring.utf16': { + bytes_per_point_memory: 1.7, + bytes_per_point_disk: 2.6, + + compress: function (s) { + return LZString.compressToUTF16(s); + }, + + compressed_length: function (s) { + return s.length * 2; + }, + + uncompress: function (s) { + return LZString.decompressFromUTF16(s); + } + }, + + 'lzstring.base64': { + bytes_per_point_memory: 2.1, + bytes_per_point_disk: 2.3, + + compress: function (s) { + return LZString.compressToBase64(s); + }, + + compressed_length: function (s) { + return s.length; + }, + + uncompress: function (s) { + return LZString.decompressFromBase64(s); + } + }, + + 'lzstring.uri': { + bytes_per_point_memory: 2.1, + bytes_per_point_disk: 2.3, + + compress: function (s) { + return LZString.compressToEncodedURIComponent(s); + }, + + compressed_length: function (s) { + return s.length; + }, + + uncompress: function (s) { + return LZString.decompressFromEncodedURIComponent(s); + } + } + } +}; + +// -------------------------------------------------------------------- +// loading snapshots + +function loadSnapshotModalLog(priority, msg) { + document.getElementById('loadSnapshotStatus').className = "alert alert-" + priority; + document.getElementById('loadSnapshotStatus').innerHTML = msg; +} + +var tmpSnapshotData = null; + +function loadSnapshot() { + $('#loadSnapshotImport').addClass('disabled'); + + if (tmpSnapshotData === null) { + loadSnapshotPreflightEmpty(); + loadSnapshotModalLog('danger', 'no data have been loaded'); + return; + } + + loadPako(function () { + loadLzString(function () { + loadSnapshotModalLog('info', 'Please wait, activating snapshot...'); + $('#loadSnapshotModal').modal('hide'); + + netdataShowAlarms = false; + netdataRegistry = false; + netdataServer = tmpSnapshotData.server; + NETDATA.serverDefault = netdataServer; + + document.getElementById('charts_div').innerHTML = ''; + document.getElementById('sidebar').innerHTML = ''; + NETDATA.globalReset(); + + if (typeof tmpSnapshotData.hash !== 'undefined') { + urlOptions.hash = tmpSnapshotData.hash; + } else { + urlOptions.hash = '#'; + } + + if (typeof tmpSnapshotData.info !== 'undefined') { + var info = jsonParseFn(tmpSnapshotData.info); + if (typeof info.menu !== 'undefined') { + netdataDashboard.menu = info.menu; + } + + if (typeof info.submenu !== 'undefined') { + netdataDashboard.submenu = info.submenu; + } + + if (typeof info.context !== 'undefined') { + netdataDashboard.context = info.context; + } + } + + if (typeof tmpSnapshotData.compression !== 'string') { + tmpSnapshotData.compression = 'none'; + } + + if (typeof snapshotOptions.compressions[tmpSnapshotData.compression] === 'undefined') { + alert('unknown compression method: ' + tmpSnapshotData.compression); + tmpSnapshotData.compression = 'none'; + } + + tmpSnapshotData.uncompress = snapshotOptions.compressions[tmpSnapshotData.compression].uncompress; + netdataSnapshotData = tmpSnapshotData; + + urlOptions.after = tmpSnapshotData.after_ms; + urlOptions.before = tmpSnapshotData.before_ms; + + if (typeof tmpSnapshotData.highlight_after_ms !== 'undefined' + && tmpSnapshotData.highlight_after_ms !== null + && tmpSnapshotData.highlight_after_ms > 0 + && typeof tmpSnapshotData.highlight_before_ms !== 'undefined' + && tmpSnapshotData.highlight_before_ms !== null + && tmpSnapshotData.highlight_before_ms > 0 + ) { + urlOptions.highlight_after = tmpSnapshotData.highlight_after_ms; + urlOptions.highlight_before = tmpSnapshotData.highlight_before_ms; + urlOptions.highlight = true; + } else { + urlOptions.highlight_after = 0; + urlOptions.highlight_before = 0; + urlOptions.highlight = false; + } + + netdataCheckXSS = false; // disable the modal - this does not affect XSS checks, since dashboard.js is already loaded + NETDATA.xss.enabled = true; // we should not do any remote requests, but if we do, check them + NETDATA.xss.enabled_for_data = true; // check also snapshot data - that have been excluded from the initial check, due to compression + loadSnapshotPreflightEmpty(); + initializeDynamicDashboard(); + }); + }); +}; + +function loadSnapshotPreflightFile(file) { + var filename = NETDATA.xss.string(file.name); + var fr = new FileReader(); + fr.onload = function (e) { + document.getElementById('loadSnapshotFilename').innerHTML = filename; + var result = null; + try { + result = NETDATA.xss.checkAlways('snapshot', JSON.parse(e.target.result), /^(snapshot\.info|snapshot\.data)$/); + + //console.log(result); + var date_after = new Date(result.after_ms); + var date_before = new Date(result.before_ms); + + if (typeof result.charts_ok === 'undefined') { + result.charts_ok = 'unknown'; + } + + if (typeof result.charts_failed === 'undefined') { + result.charts_failed = 0; + } + + if (typeof result.compression === 'undefined') { + result.compression = 'none'; + } + + if (typeof result.data_size === 'undefined') { + result.data_size = 0; + } + + document.getElementById('loadSnapshotFilename').innerHTML = '<code>' + filename + '</code>'; + document.getElementById('loadSnapshotHostname').innerHTML = '<b>' + result.hostname + '</b>, netdata version: <b>' + result.netdata_version.toString() + '</b>'; + document.getElementById('loadSnapshotURL').innerHTML = result.url; + document.getElementById('loadSnapshotCharts').innerHTML = result.charts.charts_count.toString() + ' charts, ' + result.charts.dimensions_count.toString() + ' dimensions, ' + result.data_points.toString() + ' points per dimension, ' + Math.round(result.duration_ms / result.data_points).toString() + ' ms per point'; + document.getElementById('loadSnapshotInfo').innerHTML = 'version: <b>' + result.snapshot_version.toString() + '</b>, includes <b>' + result.charts_ok.toString() + '</b> unique chart data queries ' + ((result.charts_failed > 0) ? ('<b>' + result.charts_failed.toString() + '</b> failed') : '').toString() + ', compressed with <code>' + result.compression.toString() + '</code>, data size ' + (Math.round(result.data_size * 100 / 1024 / 1024) / 100).toString() + ' MB'; + document.getElementById('loadSnapshotTimeRange').innerHTML = '<b>' + NETDATA.dateTime.localeDateString(date_after) + ' ' + NETDATA.dateTime.localeTimeString(date_after) + '</b> to <b>' + NETDATA.dateTime.localeDateString(date_before) + ' ' + NETDATA.dateTime.localeTimeString(date_before) + '</b>'; + document.getElementById('loadSnapshotComments').innerHTML = ((result.comments) ? result.comments : '').toString(); + loadSnapshotModalLog('success', 'File loaded, click <b>Import</b> to render it!'); + $('#loadSnapshotImport').removeClass('disabled'); + + tmpSnapshotData = result; + } + catch (e) { + console.log(e); + document.getElementById('loadSnapshotStatus').className = "alert alert-danger"; + document.getElementById('loadSnapshotStatus').innerHTML = "Failed to parse this file!"; + $('#loadSnapshotImport').addClass('disabled'); + } + } + + //console.log(file); + fr.readAsText(file); +}; + +function loadSnapshotPreflightEmpty() { + document.getElementById('loadSnapshotFilename').innerHTML = ''; + document.getElementById('loadSnapshotHostname').innerHTML = ''; + document.getElementById('loadSnapshotURL').innerHTML = ''; + document.getElementById('loadSnapshotCharts').innerHTML = ''; + document.getElementById('loadSnapshotInfo').innerHTML = ''; + document.getElementById('loadSnapshotTimeRange').innerHTML = ''; + document.getElementById('loadSnapshotComments').innerHTML = ''; + loadSnapshotModalLog('success', 'Browse for a snapshot file (or drag it and drop it here), then click <b>Import</b> to render it.'); + $('#loadSnapshotImport').addClass('disabled'); +}; + +var loadSnapshotDragAndDropInitialized = false; + +function loadSnapshotDragAndDropSetup() { + if (loadSnapshotDragAndDropInitialized === false) { + loadSnapshotDragAndDropInitialized = true; + $('#loadSnapshotDragAndDrop') + .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) { + e.preventDefault(); + e.stopPropagation(); + }) + .on('drop', function (e) { + if (e.originalEvent.dataTransfer.files.length) { + loadSnapshotPreflightFile(e.originalEvent.dataTransfer.files.item(0)); + } else { + loadSnapshotPreflightEmpty(); + loadSnapshotModalLog('danger', 'No file selected'); + } + }); + } +}; + +function loadSnapshotPreflight() { + var files = document.getElementById('loadSnapshotSelectFiles').files; + if (files.length <= 0) { + loadSnapshotPreflightEmpty(); + loadSnapshotModalLog('danger', 'No file selected'); + return; + } + + loadSnapshotModalLog('info', 'Loading file...'); + + loadSnapshotPreflightFile(files.item(0)); +} + +// -------------------------------------------------------------------- +// saving snapshots + +var saveSnapshotStop = false; + +function saveSnapshotCancel() { + saveSnapshotStop = true; +} + +var saveSnapshotModalInitialized = false; + +function saveSnapshotModalSetup() { + if (saveSnapshotModalInitialized === false) { + saveSnapshotModalInitialized = true; + $('#saveSnapshotModal') + .on('hide.bs.modal', saveSnapshotCancel) + .on('show.bs.modal', saveSnapshotModalInit) + .on('shown.bs.modal', function () { + $('#saveSnapshotResolutionSlider').find(".slider-handle:first").attr("tabindex", 1); + document.getElementById('saveSnapshotComments').focus(); + }); + } +}; + +function saveSnapshotModalLog(priority, msg) { + document.getElementById('saveSnapshotStatus').className = "alert alert-" + priority; + document.getElementById('saveSnapshotStatus').innerHTML = msg; +} + +function saveSnapshotModalShowExpectedSize() { + var points = Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint); + var priority = 'info'; + var msg = 'A moderate snapshot.'; + + var sizemb = Math.round( + (options.data.charts_count * snapshotOptions.bytes_per_chart + + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_disk) + * 10 / 1024 / 1024) / 10; + + var memmb = Math.round( + (options.data.charts_count * snapshotOptions.bytes_per_chart + + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_memory) + * 10 / 1024 / 1024) / 10; + + if (sizemb < 10) { + priority = 'success'; + msg = 'A nice small snapshot!'; + } + if (sizemb > 50) { + priority = 'warning'; + msg = 'Will stress your browser...'; + } + if (sizemb > 100) { + priority = 'danger'; + msg = 'Hm... good luck...'; + } + + saveSnapshotModalLog(priority, 'The snapshot will have ' + points.toString() + ' points per dimension. Expected size on disk ' + sizemb + ' MB, at browser memory ' + memmb + ' MB.<br/>' + msg); +} + +var saveSnapshotCompression = snapshotOptions.compressionDefault; + +function saveSnapshotSetCompression(name) { + saveSnapshotCompression = name; + document.getElementById('saveSnapshotCompressionName').innerHTML = saveSnapshotCompression; + saveSnapshotModalShowExpectedSize(); +} + +var saveSnapshotSlider = null; +var saveSnapshotSelectedSecondsPerPoint = 1; +var saveSnapshotViewDuration = 1; + +function saveSnapshotModalInit() { + $('#saveSnapshotModalProgressSection').hide(); + $('#saveSnapshotResolutionRadio').show(); + saveSnapshotModalLog('info', 'Select resolution and click <b>Save</b>'); + $('#saveSnapshotExport').removeClass('disabled'); + + loadBootstrapSlider(function () { + saveSnapshotViewDuration = options.duration; + var start_ms = Math.round(Date.now() - saveSnapshotViewDuration * 1000); + + if (NETDATA.globalPanAndZoom.isActive() === true) { + saveSnapshotViewDuration = Math.round((NETDATA.globalPanAndZoom.force_before_ms - NETDATA.globalPanAndZoom.force_after_ms) / 1000); + start_ms = NETDATA.globalPanAndZoom.force_after_ms; + } + + var start_date = new Date(start_ms); + var yyyymmddhhssmm = start_date.getFullYear() + NETDATA.zeropad(start_date.getMonth() + 1) + NETDATA.zeropad(start_date.getDate()) + '-' + NETDATA.zeropad(start_date.getHours()) + NETDATA.zeropad(start_date.getMinutes()) + NETDATA.zeropad(start_date.getSeconds()); + + document.getElementById('saveSnapshotFilename').value = 'netdata-' + options.hostname.toString() + '-' + yyyymmddhhssmm.toString() + '-' + saveSnapshotViewDuration.toString() + '.snapshot'; + saveSnapshotSetCompression(saveSnapshotCompression); + + var min = options.update_every; + var max = Math.round(saveSnapshotViewDuration / 100); + + if (NETDATA.globalPanAndZoom.isActive() === false) { + max = Math.round(saveSnapshotViewDuration / 50); + } + + var view = Math.round(saveSnapshotViewDuration / Math.round($(document.getElementById('charts_div')).width() / 2)); + + // console.log('view duration: ' + saveSnapshotViewDuration + ', min: ' + min + ', max: ' + max + ', view: ' + view); + + if (max < 10) { + max = 10; + } + if (max < min) { + max = min; + } + if (view < min) { + view = min; + } + if (view > max) { + view = max; + } + + if (saveSnapshotSlider !== null) { + saveSnapshotSlider.destroy(); + } + + saveSnapshotSlider = new Slider('#saveSnapshotResolutionSlider', { + ticks: [min, view, max], + min: min, + max: max, + step: options.update_every, + value: view, + scale: (max > 100) ? 'logarithmic' : 'linear', + tooltip: 'always', + formatter: function (value) { + if (value < 1) { + value = 1; + } + + if (value < options.data.update_every) { + value = options.data.update_every; + } + + saveSnapshotSelectedSecondsPerPoint = value; + saveSnapshotModalShowExpectedSize(); + + var seconds = ' seconds '; + if (value === 1) { + seconds = ' second '; + } + + return value + seconds + 'per point' + ((value === options.data.update_every) ? ', server default' : '').toString(); + } + }); + }); +} + +function saveSnapshot() { + loadPako(function () { + loadLzString(function () { + saveSnapshotStop = false; + $('#saveSnapshotModalProgressSection').show(); + $('#saveSnapshotResolutionRadio').hide(); + $('#saveSnapshotExport').addClass('disabled'); + + var filename = document.getElementById('saveSnapshotFilename').value; + // console.log(filename); + saveSnapshotModalLog('info', 'Generating snapshot as <code>' + filename.toString() + '</code>'); + + var save_options = { + stop_updates_when_focus_is_lost: false, + update_only_visible: false, + sync_selection: false, + eliminate_zero_dimensions: true, + pan_and_zoom_data_padding: false, + show_help: false, + legend_toolbox: false, + resize_charts: false, + pixels_per_point: 1 + }; + var backedup_options = {}; + + var x; + for (x in save_options) { + if (save_options.hasOwnProperty(x)) { + backedup_options[x] = NETDATA.options.current[x]; + NETDATA.options.current[x] = save_options[x]; + } + } + + var el = document.getElementById('saveSnapshotModalProgressBar'); + var eltxt = document.getElementById('saveSnapshotModalProgressBarText'); + + options.data.charts_by_name = null; + + var saveData = { + hostname: options.hostname, + server: NETDATA.serverDefault, + netdata_version: options.data.version, + snapshot_version: 1, + after_ms: Date.now() - options.duration * 1000, + before_ms: Date.now(), + highlight_after_ms: urlOptions.highlight_after, + highlight_before_ms: urlOptions.highlight_before, + duration_ms: options.duration * 1000, + update_every_ms: options.update_every * 1000, + data_points: 0, + url: ((urlOptions.server !== null) ? urlOptions.server : document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString()).toString(), + comments: document.getElementById('saveSnapshotComments').value.toString(), + hash: urlOptions.hash, + charts: options.data, + info: jsonStringifyFn({ + menu: netdataDashboard.menu, + submenu: netdataDashboard.submenu, + context: netdataDashboard.context + }), + charts_ok: 0, + charts_failed: 0, + compression: saveSnapshotCompression, + data_size: 0, + data: {} + }; + + if (typeof snapshotOptions.compressions[saveData.compression] === 'undefined') { + alert('unknown compression method: ' + saveData.compression); + saveData.compression = 'none'; + } + + var compress = snapshotOptions.compressions[saveData.compression].compress; + var compressed_length = snapshotOptions.compressions[saveData.compression].compressed_length; + + function pack_api1_v1_chart_data(state) { + if (state.library_name === null || state.data === null) { + return; + } + + var data = state.data; + state.data = null; + data.state = null; + var str = JSON.stringify(data); + + if (typeof str === 'string') { + var cstr = compress(str); + saveData.data[state.chartDataUniqueID()] = cstr; + return compressed_length(cstr); + } else { + return 0; + } + } + + var clearPanAndZoom = false; + if (NETDATA.globalPanAndZoom.isActive() === false) { + NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], saveData.after_ms, saveData.before_ms); + clearPanAndZoom = true; + } + + saveData.after_ms = NETDATA.globalPanAndZoom.force_after_ms; + saveData.before_ms = NETDATA.globalPanAndZoom.force_before_ms; + saveData.duration_ms = saveData.before_ms - saveData.after_ms; + saveData.data_points = Math.round((saveData.before_ms - saveData.after_ms) / (saveSnapshotSelectedSecondsPerPoint * 1000)); + saveSnapshotModalLog('info', 'Generating snapshot with ' + saveData.data_points.toString() + ' data points per dimension...'); + + var charts_count = 0; + var charts_ok = 0; + var charts_failed = 0; + + function saveSnapshotRestore() { + $('#saveSnapshotModal').modal('hide'); + + // restore the options + var x; + for (x in backedup_options) { + if (backedup_options.hasOwnProperty(x)) { + NETDATA.options.current[x] = backedup_options[x]; + } + } + + $(el).css('width', '0%').attr('aria-valuenow', 0); + eltxt.innerText = '0%'; + + if (clearPanAndZoom) { + NETDATA.globalPanAndZoom.clearMaster(); + } + + NETDATA.options.force_data_points = 0; + NETDATA.options.fake_chart_rendering = false; + NETDATA.onscroll_updater_enabled = true; + NETDATA.onresize(); + NETDATA.unpause(); + + $('#saveSnapshotExport').removeClass('disabled'); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.options.force_data_points = saveData.data_points; + NETDATA.options.fake_chart_rendering = true; + NETDATA.onscroll_updater_enabled = false; + NETDATA.abortAllRefreshes(); + + var size = 0; + var info = ' Resolution: <b>' + saveSnapshotSelectedSecondsPerPoint.toString() + ((saveSnapshotSelectedSecondsPerPoint === 1) ? ' second ' : ' seconds ').toString() + 'per point</b>.'; + + function update_chart(idx) { + if (saveSnapshotStop === true) { + saveSnapshotModalLog('info', 'Cancelled!'); + saveSnapshotRestore(); + return; + } + + var state = NETDATA.options.targets[--idx]; + + var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length; + $(el).css('width', pcent + '%').attr('aria-valuenow', pcent); + eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id; + + setTimeout(function () { + charts_count++; + state.isVisible(true); + state.current.force_after_ms = saveData.after_ms; + state.current.force_before_ms = saveData.before_ms; + + state.updateChart(function (status, reason) { + state.current.force_after_ms = null; + state.current.force_before_ms = null; + + if (status === true) { + charts_ok++; + // state.log('ok'); + size += pack_api1_v1_chart_data(state); + } else { + charts_failed++; + state.log('failed to be updated: ' + reason); + } + + saveSnapshotModalLog((charts_failed) ? 'danger' : 'info', 'Generated snapshot data size <b>' + (Math.round(size * 100 / 1024 / 1024) / 100).toString() + ' MB</b>. ' + ((charts_failed) ? (charts_failed.toString() + ' charts have failed to be downloaded') : '').toString() + info); + + if (idx > 0) { + update_chart(idx); + } else { + saveData.charts_ok = charts_ok; + saveData.charts_failed = charts_failed; + saveData.data_size = size; + // console.log(saveData.compression + ': ' + (size / (options.data.dimensions_count * Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint))).toString()); + + // save it + // console.log(saveData); + saveObjectToClient(saveData, filename); + + if (charts_failed > 0) { + alert(charts_failed.toString() + ' failed to be downloaded'); + } + + saveSnapshotRestore(); + saveData = null; + } + }) + }, 0); + } + + update_chart(NETDATA.options.targets.length); + }); + }); +} + +// -------------------------------------------------------------------- +// activate netdata on the page + +function dashboardSettingsSetup() { + var update_options_modal = function () { + // console.log('update_options_modal'); + + var sync_option = function (option) { + var self = $('#' + option); + + if (self.prop('checked') !== NETDATA.getOption(option)) { + // console.log('switching ' + option.toString()); + self.bootstrapToggle(NETDATA.getOption(option) ? 'on' : 'off'); + } + }; + + var theme_sync_option = function (option) { + var self = $('#' + option); + + self.bootstrapToggle(netdataTheme === 'slate' ? 'on' : 'off'); + }; + var units_sync_option = function (option) { + var self = $('#' + option); + + if (self.prop('checked') !== (NETDATA.getOption('units') === 'auto')) { + self.bootstrapToggle(NETDATA.getOption('units') === 'auto' ? 'on' : 'off'); + } + + if (self.prop('checked') === true) { + $('#settingsLocaleTempRow').show(); + $('#settingsLocaleTimeRow').show(); + } else { + $('#settingsLocaleTempRow').hide(); + $('#settingsLocaleTimeRow').hide(); + } + }; + var temp_sync_option = function (option) { + var self = $('#' + option); + + if (self.prop('checked') !== (NETDATA.getOption('temperature') === 'celsius')) { + self.bootstrapToggle(NETDATA.getOption('temperature') === 'celsius' ? 'on' : 'off'); + } + }; + var timezone_sync_option = function (option) { + var self = $('#' + option); + + document.getElementById('browser_timezone').innerText = NETDATA.options.browser_timezone; + document.getElementById('server_timezone').innerText = NETDATA.options.server_timezone; + document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default') ? 'unset, using browser default' : NETDATA.options.current.timezone; + + if (self.prop('checked') === NETDATA.dateTime.using_timezone) { + self.bootstrapToggle(NETDATA.dateTime.using_timezone ? 'off' : 'on'); + } + }; + + sync_option('eliminate_zero_dimensions'); + sync_option('destroy_on_hide'); + sync_option('async_on_scroll'); + sync_option('parallel_refresher'); + sync_option('concurrent_refreshes'); + sync_option('sync_selection'); + sync_option('sync_pan_and_zoom'); + sync_option('stop_updates_when_focus_is_lost'); + sync_option('smooth_plot'); + sync_option('pan_and_zoom_data_padding'); + sync_option('show_help'); + sync_option('seconds_as_time'); + theme_sync_option('netdata_theme_control'); + units_sync_option('units_conversion'); + temp_sync_option('units_temp'); + timezone_sync_option('local_timezone'); + + if (NETDATA.getOption('parallel_refresher') === false) { + $('#concurrent_refreshes_row').hide(); + } else { + $('#concurrent_refreshes_row').show(); + } + }; + NETDATA.setOption('setOptionCallback', update_options_modal); + + // handle options changes + $('#eliminate_zero_dimensions').change(function () { + NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); + }); + $('#destroy_on_hide').change(function () { + NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); + }); + $('#async_on_scroll').change(function () { + NETDATA.setOption('async_on_scroll', $(this).prop('checked')); + }); + $('#parallel_refresher').change(function () { + NETDATA.setOption('parallel_refresher', $(this).prop('checked')); + }); + $('#concurrent_refreshes').change(function () { + NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); + }); + $('#sync_selection').change(function () { + NETDATA.setOption('sync_selection', $(this).prop('checked')); + }); + $('#sync_pan_and_zoom').change(function () { + NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); + }); + $('#stop_updates_when_focus_is_lost').change(function () { + urlOptions.update_always = !$(this).prop('checked'); + urlOptions.hashUpdate(); + + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always); + }); + $('#smooth_plot').change(function () { + NETDATA.setOption('smooth_plot', $(this).prop('checked')); + }); + $('#pan_and_zoom_data_padding').change(function () { + NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); + }); + $('#seconds_as_time').change(function () { + NETDATA.setOption('seconds_as_time', $(this).prop('checked')); + }); + $('#local_timezone').change(function () { + if ($(this).prop('checked')) { + selected_server_timezone('default', true); + } else { + selected_server_timezone('default', false); + } + }); + + $('#units_conversion').change(function () { + NETDATA.setOption('units', $(this).prop('checked') ? 'auto' : 'original'); + }); + $('#units_temp').change(function () { + NETDATA.setOption('temperature', $(this).prop('checked') ? 'celsius' : 'fahrenheit'); + }); + + $('#show_help').change(function () { + urlOptions.help = $(this).prop('checked'); + urlOptions.hashUpdate(); + + NETDATA.setOption('show_help', urlOptions.help); + netdataReload(); + }); + + // this has to be the last + // it reloads the page + $('#netdata_theme_control').change(function () { + urlOptions.theme = $(this).prop('checked') ? 'slate' : 'white'; + urlOptions.hashUpdate(); + + if (setTheme(urlOptions.theme)) { + netdataReload(); + } + }); +} + +function scrollDashboardTo() { + if (netdataSnapshotData !== null && typeof netdataSnapshotData.hash !== 'undefined') { + //console.log(netdataSnapshotData.hash); + scrollToId(netdataSnapshotData.hash.replace('#', '')); + } else { + // check if we have to jump to a specific section + scrollToId(urlOptions.hash.replace('#', '')); + + if (urlOptions.chart !== null) { + NETDATA.alarms.scrollToChart(urlOptions.chart); + //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu); + //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart); + //console.log('hash = ' + urlOptions.hash); + } + } +} + +var modalHiddenCallback = null; + +function scrollToChartAfterHidingModal(chart) { + modalHiddenCallback = function () { + NETDATA.alarms.scrollToChart(chart); + }; +} + +// ---------------------------------------------------------------------------- + +function enableTooltipsAndPopovers() { + $('[data-toggle="tooltip"]').tooltip({ + animated: 'fade', + trigger: 'hover', + html: true, + delay: {show: 500, hide: 0}, + container: 'body' + }); + $('[data-toggle="popover"]').popover(); +} + +// ---------------------------------------------------------------------------- + +var runOnceOnDashboardLastRun = 0; + +function runOnceOnDashboardWithjQuery() { + if (runOnceOnDashboardLastRun !== 0) { + scrollDashboardTo(); + + // restore the scrollspy at the proper position + $(document.body).scrollspy('refresh'); + $(document.body).scrollspy('process'); + + return; + } + + runOnceOnDashboardLastRun = Date.now(); + + // ------------------------------------------------------------------------ + // bootstrap modals + + // prevent bootstrap modals from scrolling the page + // maintains the current scroll position + // https://stackoverflow.com/a/34754029/4525767 + + var scrollPos = 0; + var modal_depth = 0; // how many modals are currently open + var modal_shown = false; // set to true, if a modal is shown + var netdata_paused_on_modal = false; // set to true, if the modal paused netdata + var scrollspyOffset = $(window).height() / 3; // will be updated below - the offset of scrollspy to select an item + + $('.modal') + .on('show.bs.modal', function () { + if (modal_depth === 0) { + scrollPos = window.scrollY; + + $('body').css({ + overflow: 'hidden', + position: 'fixed', + top: -scrollPos + }); + + modal_shown = true; + + if (NETDATA.options.pauseCallback === null) { + NETDATA.pause(function () { + }); + netdata_paused_on_modal = true; + } else { + netdata_paused_on_modal = false; + } + } + + modal_depth++; + //console.log(urlOptions.after); + + }) + .on('hide.bs.modal', function () { + + modal_depth--; + + if (modal_depth <= 0) { + modal_depth = 0; + + $('body') + .css({ + overflow: '', + position: '', + top: '' + }); + + // scroll to the position we had open before the modal + $('html, body') + .animate({scrollTop: scrollPos}, 0); + + // unpause netdata, if we paused it + if (netdata_paused_on_modal === true) { + NETDATA.unpause(); + netdata_paused_on_modal = false; + } + + // restore the scrollspy at the proper position + $(document.body).scrollspy('process'); + } + //console.log(urlOptions.after); + }) + .on('hidden.bs.modal', function () { + if (modal_depth === 0) { + modal_shown = false; + } + + if (typeof modalHiddenCallback === 'function') { + modalHiddenCallback(); + } + + modalHiddenCallback = null; + //console.log(urlOptions.after); + }); + + // ------------------------------------------------------------------------ + // sidebar / affix + + $('#sidebar') + .affix({ + offset: { + top: (isdemo()) ? 150 : 0, + bottom: 0 + } + }) + .on('affixed.bs.affix', function () { + // fix scrolling of very long affix lists + // http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long + + $(this).removeAttr('style'); + }) + .on('affix-top.bs.affix', function () { + // fix bootstrap affix click bug + // https://stackoverflow.com/a/37847981/4525767 + + if (modal_shown) { + return false; + } + }) + .on('activate.bs.scrollspy', function (e) { + // change the URL based on the current position of the screen + + if (modal_shown === false) { + var el = $(e.target); + var hash = el.find('a').attr('href'); + if (typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) { + urlOptions.hash = hash; + urlOptions.hashUpdate(); + } + } + }); + + Ps.initialize(document.getElementById('sidebar'), { + wheelSpeed: 0.5, + wheelPropagation: true, + swipePropagation: true, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + + // ------------------------------------------------------------------------ + // scrollspy + + if (scrollspyOffset > 250) { + scrollspyOffset = 250; + } + if (scrollspyOffset < 75) { + scrollspyOffset = 75; + } + document.body.setAttribute('data-offset', scrollspyOffset); + + // scroll the dashboard, before activating the scrollspy, so that our + // hash will not be updated before we got the chance to scroll to it + scrollDashboardTo(); + + $(document.body).scrollspy({ + target: '#sidebar', + offset: scrollspyOffset // controls the diff of the <hX> element to the top, to select it + }); + + // ------------------------------------------------------------------------ + // my-netdata menu + + Ps.initialize(document.getElementById('my-netdata-dropdown-content'), { + wheelSpeed: 1, + wheelPropagation: false, + swipePropagation: false, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + + $('#myNetdataDropdownParent') + .on('show.bs.dropdown', function () { + var hash = urlOptions.genHash(); + $('.registry_link').each(function (idx) { + this.setAttribute('href', this.getAttribute("href").replace(/#.*$/, hash)); + }); + + NETDATA.pause(function () { + }); + }) + .on('shown.bs.dropdown', function () { + Ps.update(document.getElementById('my-netdata-dropdown-content')); + myNetdataMenuDidShow(); + }) + .on('hidden.bs.dropdown', function () { + NETDATA.unpause(); + }); + + $('#deleteRegistryModal') + .on('hidden.bs.modal', function () { + deleteRegistryGuid = null; + }); + + // ------------------------------------------------------------------------ + // update modal + + $('#updateModal') + .on('show.bs.modal', function () { + versionLog('checking, please wait...'); + }) + .on('shown.bs.modal', function () { + notifyForUpdate(true); + }); + + // ------------------------------------------------------------------------ + // alarms modal + + $('#alarmsModal') + .on('shown.bs.modal', function () { + alarmsUpdateModal(); + }) + .on('hidden.bs.modal', function () { + document.getElementById('alarms_active').innerHTML = + document.getElementById('alarms_all').innerHTML = + document.getElementById('alarms_log').innerHTML = + 'loading...'; + }); + + // ------------------------------------------------------------------------ + + dashboardSettingsSetup(); + loadSnapshotDragAndDropSetup(); + saveSnapshotModalSetup(); + showPageFooter(); + + // ------------------------------------------------------------------------ + // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js + + $.fn.shorten = function (settings) { + "use strict"; + + var config = { + showChars: 750, + minHideChars: 10, + ellipsesText: "...", + moreText: '<i class="fas fa-expand"></i> show more information', + lessText: '<i class="fas fa-compress"></i> show less information', + onLess: function () { + NETDATA.onscroll(); + }, + onMore: function () { + NETDATA.onscroll(); + }, + errMsg: null, + force: false + }; + + if (settings) { + $.extend(config, settings); + } + + if ($(this).data('jquery.shorten') && !config.force) { + return false; + } + $(this).data('jquery.shorten', true); + + $(document).off("click", '.morelink'); + + $(document).on({ + click: function () { + + var $this = $(this); + if ($this.hasClass('less')) { + $this.removeClass('less'); + $this.html(config.moreText); + $this.parent().prev().animate({'height': '0' + '%'}, 0, function () { + $this.parent().prev().prev().show(); + }).hide(0, function () { + config.onLess(); + }); + } else { + $this.addClass('less'); + $this.html(config.lessText); + $this.parent().prev().animate({'height': '100' + '%'}, 0, function () { + $this.parent().prev().prev().hide(); + }).show(0, function () { + config.onMore(); + }); + } + return false; + } + }, '.morelink'); + + return this.each(function () { + var $this = $(this); + + var content = $this.html(); + var contentlen = $this.text().length; + if (contentlen > config.showChars + config.minHideChars) { + var c = content.substr(0, config.showChars); + if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it + { + var inTag = false; // I'm in a tag? + var bag = ''; // Put the characters to be shown here + var countChars = 0; // Current bag size + var openTags = []; // Stack for opened tags, so I can close them later + var tagName = null; + + for (var i = 0, r = 0; r <= config.showChars; i++) { + if (content[i] === '<' && !inTag) { + inTag = true; + + // This could be "tag" or "/tag" + tagName = content.substring(i + 1, content.indexOf('>', i)); + + // If its a closing tag + if (tagName[0] === '/') { + + if (tagName !== ('/' + openTags[0])) { + config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes'; + } else { + openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!) + } + + } else { + // There are some nasty tags that don't have a close tag like <br/> + if (tagName.toLowerCase() !== 'br') { + openTags.unshift(tagName); // Add to start the name of the tag that opens + } + } + } + + if (inTag && content[i] === '>') { + inTag = false; + } + + if (inTag) { + bag += content.charAt(i); + } else { + // Add tag name chars to the result + r++; + if (countChars <= config.showChars) { + bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the [] + countChars++; + } else { + // Now I have the characters needed + if (openTags.length > 0) { + // I have unclosed tags + + //console.log('They were open tags'); + //console.log(openTags); + for (var j = 0; j < openTags.length; j++) { + //console.log('Cierro tag ' + openTags[j]); + bag += '</' + openTags[j] + '>'; // Close all tags that were opened + + // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags + } + break; + } + } + } + } + c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html(); + } else { + c += config.ellipsesText; + } + + var html = '<div class="shortcontent">' + c + + '</div><div class="allcontent">' + content + + '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>'; + + $this.html(html); + $this.find(".allcontent").hide(); // Hide all text + $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened + } + }); + }; +} + +function finalizePage() { + // resize all charts - without starting the background thread + // this has to be done while NETDATA is paused + // if we ommit this, the affix menu will be wrong, since all + // the Dom elements are initially zero-sized + NETDATA.parseDom(); + + // ------------------------------------------------------------------------ + + NETDATA.globalPanAndZoom.callback = null; + NETDATA.globalChartUnderlay.callback = null; + + if (urlOptions.pan_and_zoom === true && NETDATA.options.targets.length > 0) { + NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before); + } + + // callback for us to track PanAndZoom operations + NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback; + NETDATA.globalChartUnderlay.callback = urlOptions.netdataHighlightCallback; + + // ------------------------------------------------------------------------ + + // let it run (update the charts) + NETDATA.unpause(); + + runOnceOnDashboardWithjQuery(); + $(".shorten").shorten(); + enableTooltipsAndPopovers(); + + if (isdemo()) { + // do not to give errors on netdata demo servers for 60 seconds + NETDATA.options.current.retries_on_data_failures = 60; + + if (urlOptions.nowelcome !== true) { + setTimeout(function () { + $('#welcomeModal').modal(); + }, 1000); + } + + // google analytics when this is used for the home page of the demo sites + // this does not run on user's installations + setTimeout(function () { + (function (i, s, o, g, r, a, m) { + i['GoogleAnalyticsObject'] = r; + i[r] = i[r] || function () { + (i[r].q = i[r].q || []).push(arguments) + }, i[r].l = 1 * new Date(); + a = s.createElement(o), + m = s.getElementsByTagName(o)[0]; + a.async = 1; + a.src = g; + m.parentNode.insertBefore(a, m) + })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga'); + + ga('create', 'UA-64295674-3', 'auto'); + ga('send', 'pageview', '/demosite/' + window.location.host); + }, 2000); + } else { + notifyForUpdate(); + } + + if (urlOptions.show_alarms === true) { + setTimeout(function () { + $('#alarmsModal').modal('show'); + }, 1000); + } + + NETDATA.onresizeCallback = function () { + Ps.update(document.getElementById('sidebar')); + Ps.update(document.getElementById('my-netdata-dropdown-content')); + }; + NETDATA.onresizeCallback(); + + if (netdataSnapshotData !== null) { + NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], netdataSnapshotData.after_ms, netdataSnapshotData.before_ms); + } + + // var netdataEnded = performance.now(); + // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms'); +} + +function resetDashboardOptions() { + var help = NETDATA.options.current.show_help; + + NETDATA.resetOptions(); + if (setTheme('slate')) { + netdataReload(); + } + + if (help !== NETDATA.options.current.show_help) { + netdataReload(); + } +} + +// callback to add the dashboard info to the +// parallel javascript downloader in netdata +var netdataPrepCallback = function () { + NETDATA.requiredCSS.push({ + url: NETDATA.serverStatic + 'css/bootstrap-toggle-2.2.2.min.css', + isAlreadyLoaded: function () { + return false; + } + }); + + NETDATA.requiredJs.push({ + url: NETDATA.serverStatic + 'lib/bootstrap-toggle-2.2.2.min.js', + isAlreadyLoaded: function () { + return false; + } + }); + + NETDATA.requiredJs.push({ + url: NETDATA.serverStatic + 'dashboard_info.js?v20181019-1', + async: false, + isAlreadyLoaded: function () { + return false; + } + }); + + if (isdemo()) { + document.getElementById('masthead').style.display = 'block'; + } else { + if (urlOptions.update_always === true) { + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always); + } + } +}; + +var selected_server_timezone = function (timezone, status) { + //console.log('called with timezone: ' + timezone + ", status: " + ((typeof status === 'undefined')?'undefined':status).toString()); + + // clear the error + document.getElementById('timezone_error_message').innerHTML = ''; + + if (typeof status === 'undefined') { + // the user selected a timezone from the menu + + NETDATA.setOption('user_set_server_timezone', timezone); + + if (NETDATA.dateTime.init(timezone) === false) { + NETDATA.dateTime.init(); + + if (!$('#local_timezone').prop('checked')) { + $('#local_timezone').bootstrapToggle('on'); + } + + document.getElementById('timezone_error_message').innerHTML = 'Ooops! That timezone was not accepted by your browser. Please open a github issue to help us fix it.'; + NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone); + } else { + if ($('#local_timezone').prop('checked')) { + $('#local_timezone').bootstrapToggle('off'); + } + } + } else if (status === true) { + // the user wants the browser default timezone to be activated + + NETDATA.dateTime.init(); + } else { + // the user wants the server default timezone to be activated + //console.log('found ' + NETDATA.options.current.user_set_server_timezone); + + if (NETDATA.options.current.user_set_server_timezone === 'default') { + NETDATA.options.current.user_set_server_timezone = NETDATA.options.server_timezone; + } + + timezone = NETDATA.options.current.user_set_server_timezone; + + if (NETDATA.dateTime.init(timezone) === false) { + NETDATA.dateTime.init(); + + if (!$('#local_timezone').prop('checked')) { + $('#local_timezone').bootstrapToggle('on'); + } + + document.getElementById('timezone_error_message').innerHTML = 'Sorry. The timezone "' + timezone.toString() + '" is not accepted by your browser. Please select one from the list.'; + NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone); + } + } + + document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default') ? 'unset, using browser default' : NETDATA.options.current.timezone; + return false; +}; + +// our entry point +// var netdataStarted = performance.now(); + +var netdataCallback = initializeDynamicDashboard; + +// ================================================================================================= +// netdata.cloud + +let registryAgents = []; + +let cloudAgents = []; + +let myNetdataMenuFilterValue = ""; + +let cloudAccountID = null; + +let cloudAccountName = null; + +let cloudToken = null; + +/// Enforces a maximum string length while retaining the prefix and the postfix of +/// the string. +function truncateString(str, maxLength) { + if (str.length <= maxLength) { + return str; + } + + const spanLength = Math.floor((maxLength - 3) / 2); + return `${str.substring(0, spanLength)}...${str.substring(str.length - spanLength)}`; +} + +// ------------------------------------------------------------------------------------------------- +// netdata.cloud API Client +// ------------------------------------------------------------------------------------------------- + +function isValidAgent(a) { + return a.urls != null && a.urls.length > 0; +} + +// https://github.com/netdata/hub/issues/146 +function getCloudAccountAgents() { + if (!isSignedIn()) { + return []; + } + + return fetch( + `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents`, + { + method: "GET", + mode: "cors", + headers: { + "Authorization": `Bearer ${cloudToken}` + } + } + ).then((response) => { + if (!response.ok) { + throw Error("Cannot fetch known accounts"); + } + return response.json(); + }).then((payload) => { + const agents = payload.result ? payload.result.agents : null; + + if (!agents) { + return []; + } + + return agents.filter((a) => isValidAgent(a)).map((a) => { + return { + "guid": a.id, + "name": a.name, + "url": a.urls[0], + "alternate_urls": a.urls + } + }) + }).catch(function (error) { + console.log(error); + return null; + }); +} + +// https://github.com/netdata/hub/issues/128 +function postCloudAccountAgents(agentsToSync) { + if (!isSignedIn()) { + return []; + } + + const maskedURL = NETDATA.registry.MASKED_DATA; + + const agents = agentsToSync.map((a) => { + const urls = a.alternate_urls.filter((url) => url != maskedURL); + + return { + "id": a.guid, + "name": a.name, + "urls": urls + } + }).filter((a) => isValidAgent(a)) + + const payload = { + "accountID": cloudAccountID, + "agents": agents, + "merge": false, + }; + + return fetch( + `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents`, + { + method: "POST", + mode: "cors", + headers: { + "Content-Type": "application/json; charset=utf-8", + "Authorization": `Bearer ${cloudToken}` + }, + body: JSON.stringify(payload) + } + ).then((response) => { + return response.json(); + }).then((payload) => { + const agents = payload.result ? payload.result.agents : null; + + if (!agents) { + return []; + } + + return agents.filter((a) => isValidAgent(a)).map((a) => { + return { + "guid": a.id, + "name": a.name, + "url": a.urls[0], + "alternate_urls": a.urls + } + }) + }); +} + +function deleteCloudAgentURL(agentID, url) { + if (!isSignedIn()) { + return []; + } + + return fetch( + `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents/${agentID}/url?value=${encodeURIComponent(url)}`, + { + method: "DELETE", + mode: "cors", + headers: { + "Content-Type": "application/json; charset=utf-8", + "Authorization": `Bearer ${cloudToken}` + }, + } + ).then((response) => { + return response.json(); + }).then((payload) => { + const count = payload.result ? payload.result.count : 0; + return count; + }); +} + +// ------------------------------------------------------------------------------------------------- + +function signInDidClick(e) { + e.preventDefault(); + e.stopPropagation(); + + if (!NETDATA.registry.isUsingGlobalRegistry()) { + // If user is using a private registry, request his consent for + // synchronizing with cloud. + showSignInModal(); + return; + } + + signIn(); +} + +function signOutDidClick(e) { + e.preventDefault(); + e.stopPropagation(); + signOut(); +} + +// ------------------------------------------------------------------------------------------------- + +function updateMyNetdataAfterFilterChange() { + const machinesEl = document.getElementById("my-netdata-menu-machines") + machinesEl.innerHTML = renderMachines(cloudAgents); + + if (options.hosts.length > 1) { + const streamedEl = document.getElementById("my-netdata-menu-streamed") + streamedEl.innerHTML = renderStreamedHosts(options); + } +} + +function myNetdataMenuDidShow() { + const filterEl = document.getElementById("my-netdata-menu-filter-input"); + if (filterEl) { + filterEl.focus(); + } +} + +function myNetdataFilterDidChange(e) { + const inputEl = e.target; + setTimeout(() => { + myNetdataMenuFilterValue = inputEl.value; + updateMyNetdataAfterFilterChange(); + }, 1); +} + +function myNetdataFilterClearDidClick(e) { + e.preventDefault(); + e.stopPropagation(); + + const inputEl = document.getElementById("my-netdata-menu-filter-input"); + inputEl.value = ""; + myNetdataMenuFilterValue = ""; + + updateMyNetdataAfterFilterChange(); + + inputEl.focus(); +} + +// ------------------------------------------------------------------------------------------------- + +function clearCloudVariables() { + cloudAccountID = null; + cloudAccountName = null; + cloudToken = null; +} + +function clearCloudLocalStorageItems() { + localStorage.removeItem("cloud.baseURL"); + localStorage.removeItem("cloud.agentID"); + localStorage.removeItem("cloud.sync"); +} + +function signIn() { + const url = `${NETDATA.registry.cloudBaseURL}/account/sign-in-agent?origin=${encodeURIComponent(window.location.origin + "/")}`; + window.open(url); +} + +function signOut() { + cloudSSOSignOut(); +} + +function renderAccountUI() { + if (!NETDATA.registry.isCloudEnabled) { + return + } + + const container = document.getElementById("account-menu-container"); + if (isSignedIn()) { + container.removeAttribute("title"); + container.removeAttribute("data-original-title"); + container.removeAttribute("data-placement"); + container.innerHTML = ( + `<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span id="amc-account-name"></span> <strong class="caret"></strong></a> + <ul id="cloud-menu" class="dropdown-menu scrollable-menu inpagemenu" role="menu"> + <li> + <a href="#" class="btn" onclick="signOutDidClick(event); return false"> + <i class="fas fa-sign-out-alt"></i> <span class="hidden-sm hidden-md">Sign Out</span> + </a> + </li> + </ul>` + ) + document.getElementById("amc-account-name").textContent = cloudAccountName; // Anti-XSS + } else { + container.setAttribute("data-original-title", "sign in"); + container.setAttribute("data-placement", "bottom"); + container.innerHTML = ( + `<a href="#" class="btn" onclick="signInDidClick(event); return false"> + <i class="fas fa-sign-in-alt"></i> <span class="hidden-sm hidden-md">Sign In</span> + </a>` + ) + } +} + +function handleMessage(e) { + switch (e.data.type) { + case "sign-in": + handleSignInMessage(e); + break; + + case "sign-out": + handleSignOutMessage(e); + break; + + default: + return; + } +} + +function handleSignInMessage(e) { + localStorage.setItem("cloud.baseURL", NETDATA.registry.cloudBaseURL); + + cloudAccountID = e.data.accountID; + cloudAccountName = e.data.accountName; + cloudToken = e.data.token; + + netdataRegistryCallback(registryAgents); +} + +function handleSignOutMessage(e) { + clearCloudVariables(); + renderAccountUI(); + renderMyNetdataMenu(registryAgents); +} + +function isSignedIn() { + return cloudToken != null && cloudAccountID != null; +} + +function sortedArraysEqual(a, b) { + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +// If merging is needed returns the merged agents set, otherwise returns null. +function mergeAgents(cloud, local) { + let dirty = false; + + const union = new Map(); + + for (const cagent of cloud) { + union.set(cagent.guid, cagent); + } + + for (const lagent of local) { + const cagent = union.get(lagent.guid); + if (cagent) { + for (const u of lagent.alternate_urls) { + if (u === NETDATA.registry.MASKED_DATA) { // TODO: temp until registry is updated. + continue; + } + + if (!cagent.alternate_urls.includes(u)) { + dirty = true; + cagent.alternate_urls.push(u); + } + } + } else { + dirty = true; + union.set(lagent.guid, lagent); + } + } + + if (dirty) { + return Array.from(union.values()); + } + + return null; +} + +function showSignInModal() { + document.getElementById("sim-registry").innerHTML = NETDATA.registry.server; + $("#signInModal").modal("show"); +} + +function explicitlySignIn() { + $("#signInModal").modal("hide"); + signIn(); +} + +function showSyncModal() { + document.getElementById("sync-registry-modal-registry").innerHTML = NETDATA.registry.server; + $("#syncRegistryModal").modal("show"); +} + +function explicitlySyncAgents() { + $("#syncRegistryModal").modal("hide"); + + const json = localStorage.getItem("cloud.sync"); + const sync = json ? JSON.parse(json): {}; + delete sync[cloudAccountID]; + localStorage.setItem("cloud.sync", JSON.stringify(sync)); + + NETDATA.registry.init(); +} + +function syncAgents(callback) { + const json = localStorage.getItem("cloud.sync"); + const sync = json ? JSON.parse(json): {}; + + const currentAgent = { + guid: NETDATA.registry.machine_guid, + name: NETDATA.registry.hostname, + url: NETDATA.serverDefault, + alternate_urls: [NETDATA.serverDefault], + } + + const localAgents = sync[cloudAccountID] + ? [currentAgent] + : registryAgents.concat([currentAgent]); + + console.log("Checking if sync is needed.", localAgents); + + const agentsToSync = mergeAgents(cloudAgents, localAgents); + + if ((!sync[cloudAccountID]) || agentsToSync) { + sync[cloudAccountID] = new Date().getTime(); + localStorage.setItem("cloud.sync", JSON.stringify(sync)); + } + + if (agentsToSync) { + console.log("Synchronizing with netdata.cloud."); + + postCloudAccountAgents(agentsToSync).then((agents) => { + // TODO: clear syncTime on error! + cloudAgents = agents; + callback(cloudAgents); + }); + + return + } + + callback(cloudAgents); +} + +let isCloudSSOInitialized = false; + +function cloudSSOInit() { + const iframeEl = document.getElementById("ssoifrm"); + const url = `${NETDATA.registry.cloudBaseURL}/account/sso-agent?id=${NETDATA.registry.machine_guid}`; + iframeEl.src = url; + isCloudSSOInitialized = true; +} + +function cloudSSOSignOut() { + const iframe = document.getElementById("ssoifrm"); + const url = `${NETDATA.registry.cloudBaseURL}/account/sign-out-agent`; + iframe.src = url; +} + +function initCloud() { + if (!NETDATA.registry.isCloudEnabled) { + clearCloudVariables(); + clearCloudLocalStorageItems(); + return; + } + + if (NETDATA.registry.cloudBaseURL != localStorage.getItem("cloud.baseURL")) { + clearCloudVariables(); + clearCloudLocalStorageItems(); + if (NETDATA.registry.cloudBaseURL) { + localStorage.setItem("cloud.baseURL", NETDATA.registry.cloudBaseURL); + } + } + + if (!isCloudSSOInitialized) { + cloudSSOInit(); + } + + renderAccountUI(); +} + +// This callback is called after NETDATA.registry is initialized. +function netdataRegistryCallback(machinesArray) { + localStorage.setItem("cloud.agentID", NETDATA.registry.machine_guid); + + initCloud(); + + registryAgents = machinesArray; + + if (isSignedIn()) { + // We call getCloudAccountAgents() here because it requires that + // NETDATA.registry is initialized. + clearMyNetdataMenu(); + getCloudAccountAgents().then((agents) => { + if (!agents) { + errorMyNetdataMenu(); + return; + } + cloudAgents = agents; + syncAgents((agents) => { + const agentsMap = {} + for (const agent of agents) { + agentsMap[agent.guid] = agent; + } + + NETDATA.registry.machines = agentsMap; + NETDATA.registry.machines_array = agents; + + renderMyNetdataMenu(agents); + }); + }); + } else { + renderMyNetdataMenu(machinesArray) + } +}; + +// If we know the cloudBaseURL and agentID from local storage render (eagerly) +// the account ui before receiving the definitive response from the web server. +// This improves the perceived performance. +function tryFastInitCloud() { + const baseURL = localStorage.getItem("cloud.baseURL"); + const agentID = localStorage.getItem("cloud.agentID"); + + if (baseURL && agentID) { + NETDATA.registry.cloudBaseURL = baseURL; + NETDATA.registry.machine_guid = agentID; + NETDATA.registry.isCloudEnabled = true; + + initCloud(); + } +} + +function initializeApp() { + window.addEventListener("message", handleMessage, false); + +// tryFastInitCloud(); +} + +if (document.readyState === "complete") { + initializeApp(); +} else { + document.addEventListener("readystatechange", () => { + if (document.readyState === "complete") { + initializeApp(); + } + }) +} diff --git a/web/gui/manifest.json b/web/gui/manifest.json new file mode 100644 index 0000000..52cb483 --- /dev/null +++ b/web/gui/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "images\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "images\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "images\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "images\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "images\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "images\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} diff --git a/web/gui/refresh-badges.js b/web/gui/refresh-badges.js new file mode 100644 index 0000000..00dd4da --- /dev/null +++ b/web/gui/refresh-badges.js @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// ---------------------------------------------------------------------------- +// This script periodically updates all the netdata badges you have added to a +// page as images. You don't need this script if you add the badges with +// <embed src="..."/> - embedded badges auto-refresh by themselves. +// +// You can set the following variables before loading this script: + +/*global netdata_update_every *//* number, the time in seconds to update the badges + * (default: 15) */ +/*global netdata_live_callback *//* function, callback to be called on each iteration while updating the badges + * (default: null) */ +/*global netdata_paused_callback *//* function, callback to be called when the update pauses + * (default: null) */ + +/* +// EXAMPLE HTML PAGE: + +<html> +<head> +<script> +// how frequently to update the badges? +var netdata_update_every = 15; + +// show a count-down for badge refreshes +var netdata_live_callback = function(secs, count) { + document.body.style.opacity = 1; + if(count) + document.getElementById("pageliveinfo").innerHTML = "This page is live - updated <b>" + count + "</b> badges..."; + else + document.getElementById("pageliveinfo").innerHTML = "This page is live - badges will be updated in <b>" + secs + "</b> seconds..."; +}; + +// show that we paused refreshes +var netdata_paused_callback = function() { + document.body.style.opacity = 0.5; + document.getElementById("pageliveinfo").innerHTML = "Refresh paused - the page does not have your focus"; +}; +</script> +<script src="https://localhost:19999/refresh-badges.js"></script> + +</head> +<body> +<div id="pageliveinfo">Please wait... loading...</div> +<img src="http://localhost:19999/api/v1/badge.svg?chart=system.cpu"/> +</body> +</html> + +*/ + +if(typeof netdata_update_every === 'undefined') + netdata_update_every = 15; + +var netdata_was_live = false; +var netdata_is_live = true; +var netdata_loops = 0; + +function update_netdata_badges() { + netdata_loops++; + netdata_is_live = false; + + var updated = 0; + var focus = document.hasFocus(); + + if(focus && netdata_loops >= netdata_update_every) { + var len = document.images.length; + while(len--) { + var url = document.images[len].src; + if(url.match(/\api\/v1\/badge\.svg/)) { + if(url.match(/\?/)) + url = url.replace(/&cacheBuster=\d*/, "") + "&cacheBuster=" + new Date().getTime().toString(); + else + url = url.replace(/\?cacheBuster=\d*/, "") + "?cacheBuster=" + new Date().getTime().toString(); + + document.images[len].src = url; + updated++; + } + } + netdata_loops = 0; + } + + if(focus || updated) + netdata_is_live = true; + + try { + if(netdata_is_live && typeof netdata_live_callback === 'function') + netdata_live_callback(netdata_update_every - netdata_loops, updated); + else if(netdata_was_live !== netdata_is_live && typeof netdata_paused_callback === 'function') + netdata_paused_callback(); + } + catch(e) { + console.log(e); + } + netdata_was_live = netdata_is_live; + + setTimeout(update_netdata_badges, 1000); +} +setTimeout(update_netdata_badges, 1000); diff --git a/web/gui/robots.txt b/web/gui/robots.txt new file mode 100644 index 0000000..e434d9c --- /dev/null +++ b/web/gui/robots.txt @@ -0,0 +1,7 @@ +User-agent: * +Allow: /$ +Allow: /index.html +Allow: /default.html +Allow: /demosites.html +Allow: /sitemap.xml +Disallow: / diff --git a/web/gui/sitemap.xml b/web/gui/sitemap.xml new file mode 100644 index 0000000..4438e8b --- /dev/null +++ b/web/gui/sitemap.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> + <url> + <loc>https://my-netdata.io/</loc> + <lastmod>2017-01-02</lastmod> + <changefreq>always</changefreq> + </url> +</urlset> diff --git a/web/gui/src/dashboard.js/alarms.js b/web/gui/src/dashboard.js/alarms.js new file mode 100644 index 0000000..8247767 --- /dev/null +++ b/web/gui/src/dashboard.js/alarms.js @@ -0,0 +1,422 @@ + +// Registry of netdata hosts + +NETDATA.alarms = { + onclick: null, // the callback to handle the click - it will be called with the alarm log entry + chart_div_offset: -50, // give that space above the chart when scrolling to it + chart_div_id_prefix: 'chart_', // the chart DIV IDs have this prefix (they should be NETDATA.name2id(chart.id)) + chart_div_animation_duration: 0,// the duration of the animation while scrolling to a chart + + ms_penalty: 0, // the time penalty of the next alarm + ms_between_notifications: 500, // firefox moves the alarms off-screen (above, outside the top of the screen) + // if alarms are shown faster than: one per 500ms + + update_every: 10000, // the time in ms between alarm checks + + notifications: false, // when true, the browser supports notifications (may not be granted though) + last_notification_id: 0, // the id of the last alarm_log we have raised an alarm for + first_notification_id: 0, // the id of the first alarm_log entry for this session + // this is used to prevent CLEAR notifications for past events + // notifications_shown: [], + + server: null, // the server to connect to for fetching alarms + current: null, // the list of raised alarms - updated in the background + + // a callback function to call every time the list of raised alarms is refreshed + callback: (typeof netdataAlarmsActiveCallback === 'function') ? netdataAlarmsActiveCallback : null, + + // a callback function to call every time a notification is shown + // the return value is used to decide if the notification will be shown + notificationCallback: (typeof netdataAlarmsNotifCallback === 'function') ? netdataAlarmsNotifCallback : null, + + recipients: null, // the list (array) of recipients to show alarms for, or null + + recipientMatches: function (to_string, wanted_array) { + if (typeof wanted_array === 'undefined' || wanted_array === null || Array.isArray(wanted_array) === false) { + return true; + } + + let r = ' ' + to_string.toString() + ' '; + let len = wanted_array.length; + while (len--) { + if (r.indexOf(' ' + wanted_array[len] + ' ') >= 0) { + return true; + } + } + + return false; + }, + + activeForRecipients: function () { + let active = {}; + let data = NETDATA.alarms.current; + + if (typeof data === 'undefined' || data === null) { + return active; + } + + for (let x in data.alarms) { + if (!data.alarms.hasOwnProperty(x)) { + continue; + } + + let alarm = data.alarms[x]; + if ((alarm.status === 'WARNING' || alarm.status === 'CRITICAL') && NETDATA.alarms.recipientMatches(alarm.recipient, NETDATA.alarms.recipients)) { + active[x] = alarm; + } + } + + return active; + }, + + notify: function (entry) { + // console.log('alarm ' + entry.unique_id); + + if (entry.updated) { + // console.log('alarm ' + entry.unique_id + ' has been updated by another alarm'); + return; + } + + let value_string = entry.value_string; + + if (NETDATA.alarms.current !== null) { + // get the current value_string + let t = NETDATA.alarms.current.alarms[entry.chart + '.' + entry.name]; + if (typeof t !== 'undefined' && entry.status === t.status && typeof t.value_string !== 'undefined') { + value_string = t.value_string; + } + } + + let name = entry.name.replace(/_/g, ' '); + let status = entry.status.toLowerCase(); + let title = name + ' = ' + value_string.toString(); + let tag = entry.alarm_id; + let icon = 'images/banner-icon-144x144.png'; + let interaction = false; + let data = entry; + let show = true; + + // console.log('alarm ' + entry.unique_id + ' ' + entry.chart + '.' + entry.name + ' is ' + entry.status); + + switch (entry.status) { + case 'REMOVED': + show = false; + break; + + case 'UNDEFINED': + return; + + case 'UNINITIALIZED': + return; + + case 'CLEAR': + if (entry.unique_id < NETDATA.alarms.first_notification_id) { + // console.log('alarm ' + entry.unique_id + ' is not current'); + return; + } + if (entry.old_status === 'UNINITIALIZED' || entry.old_status === 'UNDEFINED') { + // console.log('alarm' + entry.unique_id + ' switch to CLEAR from ' + entry.old_status); + return; + } + if (entry.no_clear_notification) { + // console.log('alarm' + entry.unique_id + ' is CLEAR but has no_clear_notification flag'); + return; + } + title = name + ' back to normal (' + value_string.toString() + ')'; + icon = 'images/check-mark-2-128-green.png'; + interaction = false; + break; + + case 'WARNING': + if (entry.old_status === 'CRITICAL') { + status = 'demoted to ' + entry.status.toLowerCase(); + } + + icon = 'images/alert-128-orange.png'; + interaction = false; + break; + + case 'CRITICAL': + if (entry.old_status === 'WARNING') { + status = 'escalated to ' + entry.status.toLowerCase(); + } + + icon = 'images/alert-128-red.png'; + interaction = true; + break; + + default: + console.log('invalid alarm status ' + entry.status); + return; + } + + // filter recipients + if (show) { + show = NETDATA.alarms.recipientMatches(entry.recipient, NETDATA.alarms.recipients); + } + + /* + // cleanup old notifications with the same alarm_id as this one + // it does not seem to work on any web browser - so notifications cannot be removed + + let len = NETDATA.alarms.notifications_shown.length; + while (len--) { + let n = NETDATA.alarms.notifications_shown[len]; + if (n.data.alarm_id === entry.alarm_id) { + console.log('removing old alarm ' + n.data.unique_id); + + // close the notification + n.close.bind(n); + + // remove it from the array + NETDATA.alarms.notifications_shown.splice(len, 1); + len = NETDATA.alarms.notifications_shown.length; + } + } + */ + + if (show) { + if (typeof NETDATA.alarms.notificationCallback === 'function') { + show = NETDATA.alarms.notificationCallback(entry); + } + + if (show) { + setTimeout(function () { + // show this notification + // console.log('new notification: ' + title); + let n = new Notification(title, { + body: entry.hostname + ' - ' + entry.chart + ' (' + entry.family + ') - ' + status + ': ' + entry.info, + tag: tag, + requireInteraction: interaction, + icon: NETDATA.serverStatic + icon, + data: data + }); + + n.onclick = function (event) { + event.preventDefault(); + NETDATA.alarms.onclick(event.target.data); + }; + + // console.log(n); + // NETDATA.alarms.notifications_shown.push(n); + // console.log(entry); + }, NETDATA.alarms.ms_penalty); + + NETDATA.alarms.ms_penalty += NETDATA.alarms.ms_between_notifications; + } + } + }, + + scrollToChart: function (chart_id) { + if (typeof chart_id === 'string') { + let offset = $('#' + NETDATA.alarms.chart_div_id_prefix + NETDATA.name2id(chart_id)).offset(); + if (typeof offset !== 'undefined') { + $('html, body').animate({scrollTop: offset.top + NETDATA.alarms.chart_div_offset}, NETDATA.alarms.chart_div_animation_duration); + return true; + } + } + return false; + }, + + scrollToAlarm: function (alarm) { + if (typeof alarm === 'object') { + let ret = NETDATA.alarms.scrollToChart(alarm.chart); + + if (ret && NETDATA.options.page_is_visible === false) { + window.focus(); + } + // alert('netdata dashboard will now scroll to chart: ' + alarm.chart + '\n\nThis alarm opened to bring the browser window in front of the screen. Click on the dashboard to prevent it from appearing again.'); + } + + }, + + notifyAll: function () { + // console.log('FETCHING ALARM LOG'); + NETDATA.alarms.get_log(NETDATA.alarms.last_notification_id, function (data) { + // console.log('ALARM LOG FETCHED'); + + if (data === null || typeof data !== 'object') { + console.log('invalid alarms log response'); + return; + } + + if (data.length === 0) { + console.log('received empty alarm log'); + return; + } + + // console.log('received alarm log of ' + data.length + ' entries, from ' + data[data.length - 1].unique_id.toString() + ' to ' + data[0].unique_id.toString()); + + data.sort(function (a, b) { + if (a.unique_id > b.unique_id) { + return -1; + } + if (a.unique_id < b.unique_id) { + return 1; + } + return 0; + }); + + NETDATA.alarms.ms_penalty = 0; + + let len = data.length; + while (len--) { + if (data[len].unique_id > NETDATA.alarms.last_notification_id) { + NETDATA.alarms.notify(data[len]); + } + //else + // console.log('ignoring alarm (older) with id ' + data[len].unique_id.toString()); + } + + NETDATA.alarms.last_notification_id = data[0].unique_id; + + if (typeof netdataAlarmsRemember === 'undefined' || netdataAlarmsRemember) { + NETDATA.localStorageSet('last_notification_id', NETDATA.alarms.last_notification_id, null); + } + // console.log('last notification id = ' + NETDATA.alarms.last_notification_id); + }) + }, + + check_notifications: function () { + // returns true if we should fire 1+ notifications + + if (NETDATA.alarms.notifications !== true) { + // console.log('web notifications are not available'); + return false; + } + + if (Notification.permission !== 'granted') { + // console.log('web notifications are not granted'); + return false; + } + + if (typeof NETDATA.alarms.current !== 'undefined' && typeof NETDATA.alarms.current.alarms === 'object') { + // console.log('can do alarms: old id = ' + NETDATA.alarms.last_notification_id + ' new id = ' + NETDATA.alarms.current.latest_alarm_log_unique_id); + + if (NETDATA.alarms.current.latest_alarm_log_unique_id > NETDATA.alarms.last_notification_id) { + // console.log('new alarms detected'); + return true; + } + //else console.log('no new alarms'); + } + // else console.log('cannot process alarms'); + + return false; + }, + + get: function (what, callback) { + $.ajax({ + url: NETDATA.alarms.server + '/api/v1/alarms?' + what.toString(), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/alarms', data /*, '.*\.(calc|calc_parsed|warn|warn_parsed|crit|crit_parsed)$' */); + + if (NETDATA.alarms.first_notification_id === 0 && typeof data.latest_alarm_log_unique_id === 'number') { + NETDATA.alarms.first_notification_id = data.latest_alarm_log_unique_id; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(415, NETDATA.alarms.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + update_forever: function () { + if (netdataShowAlarms !== true || netdataSnapshotData !== null) { + return; + } + + NETDATA.alarms.get('active', function (data) { + if (data !== null) { + NETDATA.alarms.current = data; + + if (NETDATA.alarms.check_notifications()) { + NETDATA.alarms.notifyAll(); + } + + if (typeof NETDATA.alarms.callback === 'function') { + NETDATA.alarms.callback(data); + } + + // Health monitoring is disabled on this netdata + if (data.status === false) { + return; + } + } + + setTimeout(NETDATA.alarms.update_forever, NETDATA.alarms.update_every); + }); + }, + + get_log: function (last_id, callback) { + // console.log('fetching all log after ' + last_id.toString()); + $.ajax({ + url: NETDATA.alarms.server + '/api/v1/alarm_log?after=' + last_id.toString(), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/alarm_log', data); + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(416, NETDATA.alarms.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + init: function () { + NETDATA.alarms.server = NETDATA.fixHost(NETDATA.serverDefault); + + if (typeof netdataAlarmsRemember === 'undefined' || netdataAlarmsRemember) { + NETDATA.alarms.last_notification_id = + NETDATA.localStorageGet('last_notification_id', NETDATA.alarms.last_notification_id, null); + } + + if (NETDATA.alarms.onclick === null) { + NETDATA.alarms.onclick = NETDATA.alarms.scrollToAlarm; + } + + if (typeof netdataAlarmsRecipients !== 'undefined' && Array.isArray(netdataAlarmsRecipients)) { + NETDATA.alarms.recipients = netdataAlarmsRecipients; + } + + if (netdataShowAlarms) { + NETDATA.alarms.update_forever(); + + if ('Notification' in window) { + // console.log('notifications available'); + NETDATA.alarms.notifications = true; + + if (Notification.permission === 'default') { + Notification.requestPermission(); + } + } + } + } +}; diff --git a/web/gui/src/dashboard.js/boot.js b/web/gui/src/dashboard.js/boot.js new file mode 100644 index 0000000..c448213 --- /dev/null +++ b/web/gui/src/dashboard.js/boot.js @@ -0,0 +1,142 @@ + +// Load required JS libraries and CSS + +NETDATA.requiredJs = [ + { + url: NETDATA.serverStatic + 'lib/bootstrap-3.3.7.min.js', + async: false, + isAlreadyLoaded: function () { + // check if bootstrap is loaded + if (typeof $().emulateTransitionEnd === 'function') { + return true; + } else { + return typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap; + } + } + }, + { + url: NETDATA.serverStatic + 'lib/fontawesome-all-5.0.1.min.js', + async: true, + isAlreadyLoaded: function () { + return typeof netdataNoFontAwesome !== 'undefined' && netdataNoFontAwesome; + } + }, + { + url: NETDATA.serverStatic + 'lib/perfect-scrollbar-0.6.15.min.js', + isAlreadyLoaded: function () { + return false; + } + } +]; + +NETDATA.requiredCSS = [ + { + url: NETDATA.themes.current.bootstrap_css, + isAlreadyLoaded: function () { + return typeof netdataNoBootstrap !== 'undefined' && netdataNoBootstrap; + } + }, + { + url: NETDATA.themes.current.dashboard_css, + isAlreadyLoaded: function () { + return false; + } + } +]; + +NETDATA.loadedRequiredJs = 0; +NETDATA.loadRequiredJs = function (index, callback) { + if (index >= NETDATA.requiredJs.length) { + if (typeof callback === 'function') { + return callback(); + } + return; + } + + if (NETDATA.requiredJs[index].isAlreadyLoaded()) { + NETDATA.loadedRequiredJs++; + NETDATA.loadRequiredJs(++index, callback); + return; + } + + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.requiredJs[index].url); + } + + let async = true; + if (typeof NETDATA.requiredJs[index].async !== 'undefined' && NETDATA.requiredJs[index].async === false) { + async = false; + } + + $.ajax({ + url: NETDATA.requiredJs[index].url, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + if (NETDATA.options.debug.main_loop) { + console.log('loaded ' + NETDATA.requiredJs[index].url); + } + }) + .fail(function () { + alert('Cannot load required JS library: ' + NETDATA.requiredJs[index].url); + }) + .always(function () { + NETDATA.loadedRequiredJs++; + + // if (async === false) + if (!async) { + NETDATA.loadRequiredJs(++index, callback); + } + }); + + // if (async === true) + if (async) { + NETDATA.loadRequiredJs(++index, callback); + } +}; + +NETDATA.loadRequiredCSS = function (index) { + if (index >= NETDATA.requiredCSS.length) { + return; + } + + if (NETDATA.requiredCSS[index].isAlreadyLoaded()) { + NETDATA.loadRequiredCSS(++index); + return; + } + + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.requiredCSS[index].url); + } + + NETDATA._loadCSS(NETDATA.requiredCSS[index].url); + NETDATA.loadRequiredCSS(++index); +}; + +// Boot it! + +if (typeof netdataPrepCallback === 'function') { + netdataPrepCallback(); +} + +NETDATA.errorReset(); +NETDATA.loadRequiredCSS(0); + +NETDATA._loadjQuery(function () { + NETDATA.loadRequiredJs(0, function () { + if (typeof $().emulateTransitionEnd !== 'function') { + // bootstrap is not available + NETDATA.options.current.show_help = false; + } + + if (typeof netdataDontStart === 'undefined' || !netdataDontStart) { + if (NETDATA.options.debug.main_loop) { + console.log('starting chart refresh thread'); + } + + NETDATA.start(); + } + }); +}); diff --git a/web/gui/src/dashboard.js/chart-registry.js b/web/gui/src/dashboard.js/chart-registry.js new file mode 100644 index 0000000..542f4e0 --- /dev/null +++ b/web/gui/src/dashboard.js/chart-registry.js @@ -0,0 +1,94 @@ + +// *** src/dashboard.js/chart-registry.js + +// Chart Registry + +// When multiple charts need the same chart, we avoid downloading it +// multiple times (and having it in browser memory multiple time) +// by using this registry. + +// Every time we download a chart definition, we save it here with .add() +// Then we try to get it back with .get(). If that fails, we download it. + +NETDATA.fixHost = function (host) { + while (host.slice(-1) === '/') { + host = host.substring(0, host.length - 1); + } + + return host; +}; + +NETDATA.chartRegistry = { + charts: {}, + + globalReset: function () { + this.charts = {}; + }, + + add: function (host, id, data) { + if (typeof this.charts[host] === 'undefined') { + this.charts[host] = {}; + } + + //console.log('added ' + host + '/' + id); + this.charts[host][id] = data; + }, + + get: function (host, id) { + if (typeof this.charts[host] === 'undefined') { + return null; + } + + if (typeof this.charts[host][id] === 'undefined') { + return null; + } + + //console.log('cached ' + host + '/' + id); + return this.charts[host][id]; + }, + + downloadAll: function (host, callback) { + host = NETDATA.fixHost(host); + + let self = this; + + function got_data(h, data, callback) { + if (data !== null) { + self.charts[h] = data.charts; + + // update the server timezone in our options + if (typeof data.timezone === 'string') { + NETDATA.options.server_timezone = data.timezone; + } + } else { + NETDATA.error(406, h + '/api/v1/charts'); + } + + if (typeof callback === 'function') { + callback(data); + } + } + + if (netdataSnapshotData !== null) { + got_data(host, netdataSnapshotData.charts, callback); + } else { + $.ajax({ + url: host + '/api/v1/charts', + async: true, + cache: false, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/charts', data); + got_data(host, data, callback); + }) + .fail(function () { + NETDATA.error(405, host + '/api/v1/charts'); + + if (typeof callback === 'function') { + callback(null); + } + }); + } + } +}; diff --git a/web/gui/src/dashboard.js/charting.js b/web/gui/src/dashboard.js/charting.js new file mode 100644 index 0000000..e2e44b7 --- /dev/null +++ b/web/gui/src/dashboard.js/charting.js @@ -0,0 +1,450 @@ + +// Charts Libraries Registration + +NETDATA.chartLibraries = { + "dygraph": { + initialize: NETDATA.dygraphInitialize, + create: NETDATA.dygraphChartCreate, + update: NETDATA.dygraphChartUpdate, + resize: function (state) { + if (typeof state.tmp.dygraph_instance !== 'undefined' && typeof state.tmp.dygraph_instance.resize === 'function') { + state.tmp.dygraph_instance.resize(); + } + }, + setSelection: NETDATA.dygraphSetSelection, + clearSelection: NETDATA.dygraphClearSelection, + toolboxPanAndZoom: NETDATA.dygraphToolboxPanAndZoom, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + return 'ms' + '%7C' + 'flip' + (this.isLogScale(state) ? ('%7C' + 'abs') : '').toString(); + }, + legend: function (state) { + return (this.isSparkline(state) === false && NETDATA.dataAttributeBoolean(state.element, 'legend', true) === true) ? 'right-side' : null; + }, + autoresize: function (state) { + void(state); + return true; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + return (this.isSparkline(state) === false) ? 3 : 2; + }, + isSparkline: function (state) { + if (typeof state.tmp.dygraph_sparkline === 'undefined') { + state.tmp.dygraph_sparkline = (this.theme(state) === 'sparkline'); + } + return state.tmp.dygraph_sparkline; + }, + isLogScale: function (state) { + if (typeof state.tmp.dygraph_logscale === 'undefined') { + state.tmp.dygraph_logscale = (this.theme(state) === 'logscale'); + } + return state.tmp.dygraph_logscale; + }, + theme: function (state) { + if (typeof state.tmp.dygraph_theme === 'undefined') { + state.tmp.dygraph_theme = NETDATA.dataAttribute(state.element, 'dygraph-theme', 'default'); + } + return state.tmp.dygraph_theme; + }, + container_class: function (state) { + if (this.legend(state) !== null) { + return 'netdata-container-with-legend'; + } + return 'netdata-container'; + } + }, + "sparkline": { + initialize: NETDATA.sparklineInitialize, + create: NETDATA.sparklineChartCreate, + update: NETDATA.sparklineChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'flip' + '%7C' + 'abs'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "peity": { + initialize: NETDATA.peityInitialize, + create: NETDATA.peityChartCreate, + update: NETDATA.peityChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'ssvcomma'; + }, + options: function (state) { + void(state); + return 'null2zero' + '%7C' + 'flip' + '%7C' + 'abs'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + // "morris": { + // initialize: NETDATA.morrisInitialize, + // create: NETDATA.morrisChartCreate, + // update: NETDATA.morrisChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + // format: function(state) { void(state); return 'json'; }, + // options: function(state) { void(state); return 'objectrows' + '%7C' + 'ms'; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 50; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 15; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + "google": { + initialize: NETDATA.googleInitialize, + create: NETDATA.googleChartCreate, + update: NETDATA.googleChartUpdate, + resize: null, + setSelection: undefined, //function(state, t) { void(state); return true; }, + clearSelection: undefined, //function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.rows$'), + format: function (state) { + void(state); + return 'datatable'; + }, + options: function (state) { + void(state); + return ''; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 300; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 4; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + // "raphael": { + // initialize: NETDATA.raphaelInitialize, + // create: NETDATA.raphaelChartCreate, + // update: NETDATA.raphaelChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + // format: function(state) { void(state); return 'json'; }, + // options: function(state) { void(state); return ''; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 5000; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 3; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + // "c3": { + // initialize: NETDATA.c3Initialize, + // create: NETDATA.c3ChartCreate, + // update: NETDATA.c3ChartUpdate, + // resize: null, + // setSelection: undefined, // function(state, t) { void(state); return true; }, + // clearSelection: undefined, // function(state) { void(state); return true; }, + // toolboxPanAndZoom: null, + // initialized: false, + // enabled: true, + // xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + // format: function(state) { void(state); return 'csvjsonarray'; }, + // options: function(state) { void(state); return 'milliseconds'; }, + // legend: function(state) { void(state); return null; }, + // autoresize: function(state) { void(state); return false; }, + // max_updates_to_recreate: function(state) { void(state); return 5000; }, + // track_colors: function(state) { void(state); return false; }, + // pixels_per_point: function(state) { void(state); return 15; }, + // container_class: function(state) { void(state); return 'netdata-container'; } + // }, + "d3pie": { + initialize: NETDATA.d3pieInitialize, + create: NETDATA.d3pieChartCreate, + update: NETDATA.d3pieChartUpdate, + resize: null, + setSelection: NETDATA.d3pieSetSelection, + clearSelection: NETDATA.d3pieClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + void(state); + return 'objectrows' + '%7C' + 'ms'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 15; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "d3": { + initialize: NETDATA.d3Initialize, + create: NETDATA.d3ChartCreate, + update: NETDATA.d3ChartUpdate, + resize: null, + setSelection: undefined, // function(state, t) { void(state); return true; }, + clearSelection: undefined, // function(state) { void(state); return true; }, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result.data$'), + format: function (state) { + void(state); + return 'json'; + }, + options: function (state) { + void(state); + return ''; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return false; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + container_class: function (state) { + void(state); + return 'netdata-container'; + } + }, + "easypiechart": { + initialize: NETDATA.easypiechartInitialize, + create: NETDATA.easypiechartChartCreate, + update: NETDATA.easypiechartChartUpdate, + resize: null, + setSelection: NETDATA.easypiechartSetSelection, + clearSelection: NETDATA.easypiechartClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'absolute'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + aspect_ratio: 100, + container_class: function (state) { + void(state); + return 'netdata-container-easypiechart'; + } + }, + "gauge": { + initialize: NETDATA.gaugeInitialize, + create: NETDATA.gaugeChartCreate, + update: NETDATA.gaugeChartUpdate, + resize: null, + setSelection: NETDATA.gaugeSetSelection, + clearSelection: NETDATA.gaugeClearSelection, + toolboxPanAndZoom: null, + initialized: false, + enabled: true, + xssRegexIgnore: new RegExp('^/api/v1/data\.result$'), + format: function (state) { + void(state); + return 'array'; + }, + options: function (state) { + void(state); + return 'absolute'; + }, + legend: function (state) { + void(state); + return null; + }, + autoresize: function (state) { + void(state); + return false; + }, + max_updates_to_recreate: function (state) { + void(state); + return 5000; + }, + track_colors: function (state) { + void(state); + return true; + }, + pixels_per_point: function (state) { + void(state); + return 3; + }, + aspect_ratio: 60, + container_class: function (state) { + void(state); + return 'netdata-container-gauge'; + } + } +}; + +NETDATA.registerChartLibrary = function (library, url) { + if (NETDATA.options.debug.libraries) { + console.log("registering chart library: " + library); + } + + NETDATA.chartLibraries[library].url = url; + NETDATA.chartLibraries[library].initialized = true; + NETDATA.chartLibraries[library].enabled = true; +}; diff --git a/web/gui/src/dashboard.js/charting/_c3.js b/web/gui/src/dashboard.js/charting/_c3.js new file mode 100644 index 0000000..6688bbc --- /dev/null +++ b/web/gui/src/dashboard.js/charting/_c3.js @@ -0,0 +1,114 @@ + +// DEPRECATED: will be removed! + +// c3 + +NETDATA.c3Initialize = function(callback) { + if (typeof netdataNoC3 === 'undefined' || !netdataNoC3) { + + // C3 requires D3 + if (!NETDATA.chartLibraries.d3.initialized) { + if (NETDATA.chartLibraries.d3.enabled) { + NETDATA.d3Initialize(function() { + NETDATA.c3Initialize(callback); + }); + } else { + NETDATA.chartLibraries.c3.enabled = false; + if (typeof callback === "function") + return callback(); + } + } else { + NETDATA._loadCSS(NETDATA.c3_css); + + $.ajax({ + url: NETDATA.c3_js, + cache: true, + dataType: "script", + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function() { + NETDATA.registerChartLibrary('c3', NETDATA.c3_js); + }) + .fail(function() { + NETDATA.chartLibraries.c3.enabled = false; + NETDATA.error(100, NETDATA.c3_js); + }) + .always(function() { + if (typeof callback === "function") + return callback(); + }); + } + } else { + NETDATA.chartLibraries.c3.enabled = false; + if (typeof callback === "function") + return callback(); + } +}; + +NETDATA.c3ChartUpdate = function(state, data) { + state.c3_instance.destroy(); + return NETDATA.c3ChartCreate(state, data); + + //state.c3_instance.load({ + // rows: data.result, + // unload: true + //}); + + //return true; +}; + +NETDATA.c3ChartCreate = function(state, data) { + + state.element_chart.id = 'c3-' + state.uuid; + // console.log('id = ' + state.element_chart.id); + + state.c3_instance = c3.generate({ + bindto: '#' + state.element_chart.id, + size: { + width: state.chartWidth(), + height: state.chartHeight() + }, + color: { + pattern: state.chartColors() + }, + data: { + x: 'time', + rows: data.result, + type: (state.chart.chart_type === 'line')?'spline':'area-spline' + }, + axis: { + x: { + type: 'timeseries', + tick: { + format: function(x) { + return NETDATA.dateTime.xAxisTimeString(x); + } + } + } + }, + grid: { + x: { + show: true + }, + y: { + show: true + } + }, + point: { + show: false + }, + line: { + connectNull: false + }, + transition: { + duration: 0 + }, + interaction: { + enabled: true + } + }); + + // console.log(state.c3_instance); + + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/_morris.js b/web/gui/src/dashboard.js/charting/_morris.js new file mode 100644 index 0000000..30789e4 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/_morris.js @@ -0,0 +1,81 @@ + +// DEPRECATED: will be removed! + +// morris + +NETDATA.morrisInitialize = function(callback) { + if (typeof netdataNoMorris === 'undefined' || !netdataNoMorris) { + + // morris requires raphael + if (!NETDATA.chartLibraries.raphael.initialized) { + if (NETDATA.chartLibraries.raphael.enabled) { + NETDATA.raphaelInitialize(function() { + NETDATA.morrisInitialize(callback); + }); + } else { + NETDATA.chartLibraries.morris.enabled = false; + if (typeof callback === "function") + return callback(); + } + } else { + NETDATA._loadCSS(NETDATA.morris_css); + + $.ajax({ + url: NETDATA.morris_js, + cache: true, + dataType: "script", + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function() { + NETDATA.registerChartLibrary('morris', NETDATA.morris_js); + }) + .fail(function() { + NETDATA.chartLibraries.morris.enabled = false; + NETDATA.error(100, NETDATA.morris_js); + }) + .always(function() { + if (typeof callback === "function") + return callback(); + }); + } + } else { + NETDATA.chartLibraries.morris.enabled = false; + if (typeof callback === "function") + return callback(); + } +}; + +NETDATA.morrisChartUpdate = function(state, data) { + state.morris_instance.setData(data.result.data); + return true; +}; + +NETDATA.morrisChartCreate = function(state, data) { + + state.morris_options = { + element: state.element_chart.id, + data: data.result.data, + xkey: 'time', + ykeys: data.dimension_names, + labels: data.dimension_names, + lineWidth: 2, + pointSize: 3, + smooth: true, + hideHover: 'auto', + parseTime: true, + continuousLine: false, + behaveLikeLine: false + }; + + if (state.chart.chart_type === 'line') + state.morris_instance = new Morris.Line(state.morris_options); + + else if (state.chart.chart_type === 'area') { + state.morris_options.behaveLikeLine = true; + state.morris_instance = new Morris.Area(state.morris_options); + } + else // stacked + state.morris_instance = new Morris.Area(state.morris_options); + + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/_raphael.js b/web/gui/src/dashboard.js/charting/_raphael.js new file mode 100644 index 0000000..2d89a22 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/_raphael.js @@ -0,0 +1,48 @@ + +// DEPRECATED: will be removed! + +// raphael + +NETDATA.raphaelInitialize = function(callback) { + if (typeof netdataStopRaphael === 'undefined' || !netdataStopRaphael) { + $.ajax({ + url: NETDATA.raphael_js, + cache: true, + dataType: "script", + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function() { + NETDATA.registerChartLibrary('raphael', NETDATA.raphael_js); + }) + .fail(function() { + NETDATA.chartLibraries.raphael.enabled = false; + NETDATA.error(100, NETDATA.raphael_js); + }) + .always(function() { + if (typeof callback === "function") + return callback(); + }); + } else { + NETDATA.chartLibraries.raphael.enabled = false; + if (typeof callback === "function") + return callback(); + } +}; + +NETDATA.raphaelChartUpdate = function(state, data) { + $(state.element_chart).raphael(data.result, { + width: state.chartWidth(), + height: state.chartHeight() + }); + + return false; +}; + +NETDATA.raphaelChartCreate = function(state, data) { + $(state.element_chart).raphael(data.result, { + width: state.chartWidth(), + height: state.chartHeight() + }); + + return false; +}; diff --git a/web/gui/src/dashboard.js/charting/d3.js b/web/gui/src/dashboard.js/charting/d3.js new file mode 100644 index 0000000..6528208 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/d3.js @@ -0,0 +1,43 @@ + +// ---------------------------------------------------------------------------------------------------------------- +// D3 + +NETDATA.d3Initialize = function(callback) { + if (typeof netdataStopD3 === 'undefined' || !netdataStopD3) { + $.ajax({ + url: NETDATA.d3_js, + cache: true, + dataType: "script", + xhrFields: { withCredentials: true } // required for the cookie + }) + .done(function() { + NETDATA.registerChartLibrary('d3', NETDATA.d3_js); + }) + .fail(function() { + NETDATA.chartLibraries.d3.enabled = false; + NETDATA.error(100, NETDATA.d3_js); + }) + .always(function() { + if (typeof callback === "function") + return callback(); + }); + } else { + NETDATA.chartLibraries.d3.enabled = false; + if (typeof callback === "function") + return callback(); + } +}; + +NETDATA.d3ChartUpdate = function(state, data) { + void(state); + void(data); + + return false; +}; + +NETDATA.d3ChartCreate = function(state, data) { + void(state); + void(data); + + return false; +}; diff --git a/web/gui/src/dashboard.js/charting/d3pie.js b/web/gui/src/dashboard.js/charting/d3pie.js new file mode 100644 index 0000000..27cff85 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/d3pie.js @@ -0,0 +1,341 @@ + +// d3pie + +NETDATA.d3pieInitialize = function (callback) { + if (typeof netdataNoD3pie === 'undefined' || !netdataNoD3pie) { + + // d3pie requires D3 + if (!NETDATA.chartLibraries.d3.initialized) { + if (NETDATA.chartLibraries.d3.enabled) { + NETDATA.d3Initialize(function () { + NETDATA.d3pieInitialize(callback); + }); + } else { + NETDATA.chartLibraries.d3pie.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } + } else { + $.ajax({ + url: NETDATA.d3pie_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('d3pie', NETDATA.d3pie_js); + }) + .fail(function () { + NETDATA.chartLibraries.d3pie.enabled = false; + NETDATA.error(100, NETDATA.d3pie_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } + } else { + NETDATA.chartLibraries.d3pie.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.d3pieSetContent = function (state, data, index) { + state.legendFormatValueDecimalsFromMinMax( + data.min, + data.max + ); + + let content = []; + let colors = state.chartColors(); + let len = data.result.labels.length; + for (let i = 1; i < len; i++) { + let label = data.result.labels[i]; + let value = data.result.data[index][label]; + let color = colors[i - 1]; + + if (value !== null && value > 0) { + content.push({ + label: label, + value: value, + color: color + }); + } + } + + if (content.length === 0) { + content.push({ + label: 'no data', + value: 100, + color: '#666666' + }); + } + + state.tmp.d3pie_last_slot = index; + return content; +}; + +NETDATA.d3pieDateRange = function (state, data, index) { + let dt = Math.round((data.before - data.after + 1) / data.points); + let dt_str = NETDATA.seconds4human(dt); + + let before = data.result.data[index].time; + let after = before - (dt * 1000); + + let d1 = NETDATA.dateTime.localeDateString(after); + let t1 = NETDATA.dateTime.localeTimeString(after); + let d2 = NETDATA.dateTime.localeDateString(before); + let t2 = NETDATA.dateTime.localeTimeString(before); + + if (d1 === d2) { + return d1 + ' ' + t1 + ' to ' + t2 + ', ' + dt_str; + } + + return d1 + ' ' + t1 + ' to ' + d2 + ' ' + t2 + ', ' + dt_str; +}; + +NETDATA.d3pieSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.d3pieClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + slot = state.data.result.data.length - slot - 1; + + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.d3pieClearSelection(state, true); + } + + if (state.tmp.d3pie_last_slot === slot) { + // we already show this slot, don't do anything + return true; + } + + if (state.tmp.d3pie_timer === undefined) { + state.tmp.d3pie_timer = NETDATA.timeout.set(function () { + state.tmp.d3pie_timer = undefined; + NETDATA.d3pieChange(state, NETDATA.d3pieSetContent(state, state.data, slot), NETDATA.d3pieDateRange(state, state.data, slot)); + }, 0); + } + + return true; +}; + +NETDATA.d3pieClearSelection = function (state, force) { + if (typeof state.tmp.d3pie_timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.d3pie_timer); + state.tmp.d3pie_timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.d3pieChartUpdate(state, state.data); + } else { + if (state.tmp.d3pie_last_slot !== -1) { + state.tmp.d3pie_last_slot = -1; + NETDATA.d3pieChange(state, [{label: 'no data', value: 1, color: '#666666'}], 'no data available'); + } + } + + return true; +}; + +NETDATA.d3pieChange = function (state, content, footer) { + if (state.d3pie_forced_subtitle === null) { + //state.d3pie_instance.updateProp("header.subtitle.text", state.units_current); + state.d3pie_instance.options.header.subtitle.text = state.units_current; + } + + if (state.d3pie_forced_footer === null) { + //state.d3pie_instance.updateProp("footer.text", footer); + state.d3pie_instance.options.footer.text = footer; + } + + //state.d3pie_instance.updateProp("data.content", content); + state.d3pie_instance.options.data.content = content; + state.d3pie_instance.destroy(); + state.d3pie_instance.recreate(); + return true; +}; + +NETDATA.d3pieChartUpdate = function (state, data) { + return NETDATA.d3pieChange(state, NETDATA.d3pieSetContent(state, data, 0), NETDATA.d3pieDateRange(state, data, 0)); +}; + +NETDATA.d3pieChartCreate = function (state, data) { + + state.element_chart.id = 'd3pie-' + state.uuid; + // console.log('id = ' + state.element_chart.id); + + let content = NETDATA.d3pieSetContent(state, data, 0); + + state.d3pie_forced_title = NETDATA.dataAttribute(state.element, 'd3pie-title', null); + state.d3pie_forced_subtitle = NETDATA.dataAttribute(state.element, 'd3pie-subtitle', null); + state.d3pie_forced_footer = NETDATA.dataAttribute(state.element, 'd3pie-footer', null); + + state.d3pie_options = { + header: { + title: { + text: (state.d3pie_forced_title !== null) ? state.d3pie_forced_title : state.title, + color: NETDATA.dataAttribute(state.element, 'd3pie-title-color', NETDATA.themes.current.d3pie.title), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-title-fontsize', 12), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-title-fontweight', "bold"), + font: NETDATA.dataAttribute(state.element, 'd3pie-title-font', "arial") + }, + subtitle: { + text: (state.d3pie_forced_subtitle !== null) ? state.d3pie_forced_subtitle : state.units_current, + color: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-color', NETDATA.themes.current.d3pie.subtitle), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-fontweight', "normal"), + font: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-font', "arial") + }, + titleSubtitlePadding: 1 + }, + footer: { + text: (state.d3pie_forced_footer !== null) ? state.d3pie_forced_footer : NETDATA.d3pieDateRange(state, data, 0), + color: NETDATA.dataAttribute(state.element, 'd3pie-footer-color', NETDATA.themes.current.d3pie.footer), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-footer-fontsize', 9), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-footer-fontweight', "bold"), + font: NETDATA.dataAttribute(state.element, 'd3pie-footer-font', "arial"), + location: NETDATA.dataAttribute(state.element, 'd3pie-footer-location', "bottom-center") // bottom-left, bottom-center, bottom-right + }, + size: { + canvasHeight: state.chartHeight(), + canvasWidth: state.chartWidth(), + pieInnerRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieinnerradius', "45%"), + pieOuterRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieouterradius', "80%") + }, + data: { + // none, random, value-asc, value-desc, label-asc, label-desc + sortOrder: NETDATA.dataAttribute(state.element, 'd3pie-sortorder', "value-desc"), + smallSegmentGrouping: { + enabled: NETDATA.dataAttributeBoolean(state.element, "d3pie-smallsegmentgrouping-enabled", false), + value: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-value', 1), + // percentage, value + valueType: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-valuetype', "percentage"), + label: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-label', "other"), + color: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-color', NETDATA.themes.current.d3pie.other) + }, + + // REQUIRED! This is where you enter your pie data; it needs to be an array of objects + // of this form: { label: "label", value: 1.5, color: "#000000" } - color is optional + content: content + }, + labels: { + outer: { + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-format', "label-value1"), + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-hidewhenlessthanpercentage', null), + pieDistance: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-piedistance', 15) + }, + inner: { + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-format', "percentage"), + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-hidewhenlessthanpercentage', 2) + }, + mainLabel: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-color', NETDATA.themes.current.d3pie.mainlabel), // or 'segment' for dynamic color + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-fontweight', "normal") + }, + percentage: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-color', NETDATA.themes.current.d3pie.percentage), + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-fontweight', "bold"), + decimalPlaces: 0 + }, + value: { + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-color', NETDATA.themes.current.d3pie.value), + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-font', "arial"), + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-fontsize', 10), + fontWeight: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-fontweight', "bold") + }, + lines: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-labels-lines-enabled', true), + style: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-style', "curved"), + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-color', "segment") // "segment" or a hex color + }, + truncation: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-labels-truncation-enabled', false), + truncateLength: NETDATA.dataAttribute(state.element, 'd3pie-labels-truncation-truncatelength', 30) + }, + formatter: function (context) { + // console.log(context); + if (context.part === 'value') { + return state.legendFormatValue(context.value); + } + if (context.part === 'percentage') { + return context.label + '%'; + } + + return context.label; + } + }, + effects: { + load: { + effect: "none", // none / default + speed: 0 // commented in the d3pie code to speed it up + }, + pullOutSegmentOnClick: { + effect: "bounce", // none / linear / bounce / elastic / back + speed: 400, + size: 5 + }, + highlightSegmentOnMouseover: true, + highlightLuminosity: -0.2 + }, + tooltips: { + enabled: false, + type: "placeholder", // caption|placeholder + string: "", + placeholderParser: null, // function + styles: { + fadeInSpeed: 250, + backgroundColor: NETDATA.themes.current.d3pie.tooltip_bg, + backgroundOpacity: 0.5, + color: NETDATA.themes.current.d3pie.tooltip_fg, + borderRadius: 2, + font: "arial", + fontSize: 12, + padding: 4 + } + }, + misc: { + colors: { + background: 'transparent', // transparent or color # + // segments: state.chartColors(), + segmentStroke: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-segmentstroke', NETDATA.themes.current.d3pie.segment_stroke) + }, + gradient: { + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-misc-gradient-enabled', false), + percentage: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-percentage', 95), + color: NETDATA.dataAttribute(state.element, 'd3pie-misc-gradient-color', NETDATA.themes.current.d3pie.gradient_color) + }, + canvasPadding: { + top: 5, + right: 5, + bottom: 5, + left: 5 + }, + pieCenterOffset: { + x: 0, + y: 0 + }, + cssPrefix: NETDATA.dataAttribute(state.element, 'd3pie-cssprefix', null) + }, + callbacks: { + onload: null, + onMouseoverSegment: null, + onMouseoutSegment: null, + onClickSegment: null + } + }; + + state.d3pie_instance = new d3pie(state.element_chart, state.d3pie_options); + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/dygraph.js b/web/gui/src/dashboard.js/charting/dygraph.js new file mode 100644 index 0000000..a60af18 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/dygraph.js @@ -0,0 +1,977 @@ +// dygraph + +// Codacy declarations +/* global smoothPlotter */ +/* global Dygraph */ + +NETDATA.dygraph = { + smooth: false +}; + +NETDATA.dygraphToolboxPanAndZoom = function (state, after, before) { + if (after < state.netdata_first) { + after = state.netdata_first; + } + + if (before > state.netdata_last) { + before = state.netdata_last; + } + + state.setMode('zoom'); + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_user_action = true; + state.tmp.dygraph_force_zoom = true; + // state.log('toolboxPanAndZoom'); + state.updateChartPanOrZoom(after, before); + NETDATA.globalPanAndZoom.setMaster(state, after, before); +}; + +NETDATA.dygraphSetSelection = function (state, t) { + if (typeof state.tmp.dygraph_instance !== 'undefined') { + let r = state.calculateRowForTime(t); + if (r !== -1) { + state.tmp.dygraph_instance.setSelection(r); + return true; + } else { + state.tmp.dygraph_instance.clearSelection(); + state.legendShowUndefined(); + } + } + + return false; +}; + +NETDATA.dygraphClearSelection = function (state) { + if (typeof state.tmp.dygraph_instance !== 'undefined') { + state.tmp.dygraph_instance.clearSelection(); + } + return true; +}; + +NETDATA.dygraphSmoothInitialize = function (callback) { + $.ajax({ + url: NETDATA.dygraph_smooth_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.dygraph.smooth = true; + smoothPlotter.smoothing = 0.3; + }) + .fail(function () { + NETDATA.dygraph.smooth = false; + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); +}; + +NETDATA.dygraphInitialize = function (callback) { + if (typeof netdataNoDygraphs === 'undefined' || !netdataNoDygraphs) { + $.ajax({ + url: NETDATA.dygraph_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('dygraph', NETDATA.dygraph_js); + }) + .fail(function () { + NETDATA.chartLibraries.dygraph.enabled = false; + NETDATA.error(100, NETDATA.dygraph_js); + }) + .always(function () { + if (NETDATA.chartLibraries.dygraph.enabled && NETDATA.options.current.smooth_plot) { + NETDATA.dygraphSmoothInitialize(callback); + } else if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.dygraph.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.dygraphChartUpdate = function (state, data) { + let dygraph = state.tmp.dygraph_instance; + + if (typeof dygraph === 'undefined') { + return NETDATA.dygraphChartCreate(state, data); + } + + // when the chart is not visible, and hidden + // if there is a window resize, dygraph detects + // its element size as 0x0. + // this will make it re-appear properly + + if (state.tm.last_unhidden > state.tmp.dygraph_last_rendered) { + dygraph.resize(); + } + + let options = { + file: data.result.data, + colors: state.chartColors(), + labels: data.result.labels, + //labelsDivWidth: state.chartWidth() - 70, + includeZero: state.tmp.dygraph_include_zero, + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names) + }; + + if (state.tmp.dygraph_chart_type === 'stacked') { + if (options.includeZero && state.dimensions_visibility.countSelected() < options.visibility.length) { + options.includeZero = 0; + } + } + + if (!NETDATA.chartLibraries.dygraph.isSparkline(state)) { + options.ylabel = state.units_current; // (state.units_desired === 'auto')?"":state.units_current; + } + + if (state.tmp.dygraph_force_zoom) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() forced zoom update'); + } + + options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; + //options.isZoomedIgnoreProgrammaticZoom = true; + state.tmp.dygraph_force_zoom = false; + } else if (state.current.name !== 'auto') { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() loose update'); + } + } else { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartUpdate() strict update'); + } + + options.dateWindow = (state.requested_padding !== null) ? [state.view_after, state.view_before] : null; + //options.isZoomedIgnoreProgrammaticZoom = true; + } + + options.valueRange = state.tmp.dygraph_options.valueRange; + + let oldMax = null, oldMin = null; + if (state.tmp.__commonMin !== null) { + state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; + oldMin = options.valueRange[0] = NETDATA.commonMin.get(state); + } + if (state.tmp.__commonMax !== null) { + state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; + oldMax = options.valueRange[1] = NETDATA.commonMax.get(state); + } + + if (state.tmp.dygraph_smooth_eligible) { + if ((NETDATA.options.current.smooth_plot && state.tmp.dygraph_options.plotter !== smoothPlotter) + || (NETDATA.options.current.smooth_plot === false && state.tmp.dygraph_options.plotter === smoothPlotter)) { + NETDATA.dygraphChartCreate(state, data); + return; + } + } + + if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { + // pan and zoom on snapshots + options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; + //options.isZoomedIgnoreProgrammaticZoom = true; + } + + if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { + if (Array.isArray(options.valueRange) && options.valueRange[0] <= 0) { + options.valueRange[0] = null; + } + } + + dygraph.updateOptions(options); + + let redraw = false; + if (oldMin !== null && oldMin > state.tmp.dygraph_instance.axes_[0].extremeRange[0]) { + state.data.min = state.tmp.dygraph_instance.axes_[0].extremeRange[0]; + options.valueRange[0] = NETDATA.commonMin.get(state); + redraw = true; + } + if (oldMax !== null && oldMax < state.tmp.dygraph_instance.axes_[0].extremeRange[1]) { + state.data.max = state.tmp.dygraph_instance.axes_[0].extremeRange[1]; + options.valueRange[1] = NETDATA.commonMax.get(state); + redraw = true; + } + + if (redraw) { + // state.log('forcing redraw to adapt to common- min/max'); + dygraph.updateOptions(options); + } + + state.tmp.dygraph_last_rendered = Date.now(); + return true; +}; + +NETDATA.dygraphChartCreate = function (state, data) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphChartCreate()'); + } + + state.tmp.dygraph_chart_type = NETDATA.dataAttribute(state.element, 'dygraph-type', state.chart.chart_type); + if (state.tmp.dygraph_chart_type === 'stacked' && data.dimensions === 1) { + state.tmp.dygraph_chart_type = 'area'; + } + if (state.tmp.dygraph_chart_type === 'stacked' && NETDATA.chartLibraries.dygraph.isLogScale(state)) { + state.tmp.dygraph_chart_type = 'area'; + } + + let highlightCircleSize = NETDATA.chartLibraries.dygraph.isSparkline(state) ? 3 : 4; + + let smooth = NETDATA.dygraph.smooth + ? (NETDATA.dataAttributeBoolean(state.element, 'dygraph-smooth', (state.tmp.dygraph_chart_type === 'line' && NETDATA.chartLibraries.dygraph.isSparkline(state) === false))) + : false; + + state.tmp.dygraph_include_zero = NETDATA.dataAttribute(state.element, 'dygraph-includezero', (state.tmp.dygraph_chart_type === 'stacked')); + let drawAxis = NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawaxis', true); + + state.tmp.dygraph_options = { + colors: NETDATA.dataAttribute(state.element, 'dygraph-colors', state.chartColors()), + + // leave a few pixels empty on the right of the chart + rightGap: NETDATA.dataAttribute(state.element, 'dygraph-rightgap', 5), + showRangeSelector: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showrangeselector', false), + showRoller: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showroller', false), + title: NETDATA.dataAttribute(state.element, 'dygraph-title', state.title), + titleHeight: NETDATA.dataAttribute(state.element, 'dygraph-titleheight', 19), + legend: NETDATA.dataAttribute(state.element, 'dygraph-legend', 'always'), // we need this to get selection events + labels: data.result.labels, + labelsDiv: NETDATA.dataAttribute(state.element, 'dygraph-labelsdiv', state.element_legend_childs.hidden), + //labelsDivStyles: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivstyles', { 'fontSize':'1px' }), + //labelsDivWidth: NETDATA.dataAttribute(state.element, 'dygraph-labelsdivwidth', state.chartWidth() - 70), + labelsSeparateLines: NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsseparatelines', true), + labelsShowZeroValues: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-labelsshowzerovalues', true), + labelsKMB: false, + labelsKMG2: false, + showLabelsOnHighlight: NETDATA.dataAttributeBoolean(state.element, 'dygraph-showlabelsonhighlight', true), + hideOverlayOnMouseOut: NETDATA.dataAttributeBoolean(state.element, 'dygraph-hideoverlayonmouseout', true), + includeZero: state.tmp.dygraph_include_zero, + xRangePad: NETDATA.dataAttribute(state.element, 'dygraph-xrangepad', 0), + yRangePad: NETDATA.dataAttribute(state.element, 'dygraph-yrangepad', 1), + valueRange: NETDATA.dataAttribute(state.element, 'dygraph-valuerange', [null, null]), + ylabel: state.units_current, // (state.units_desired === 'auto')?"":state.units_current, + yLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-ylabelwidth', 12), + + // the function to plot the chart + plotter: null, + + // The width of the lines connecting data points. + // This can be used to increase the contrast or some graphs. + strokeWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokewidth', ((state.tmp.dygraph_chart_type === 'stacked') ? 0.1 : ((smooth === true) ? 1.5 : 0.7))), + strokePattern: NETDATA.dataAttribute(state.element, 'dygraph-strokepattern', undefined), + + // The size of the dot to draw on each point in pixels (see drawPoints). + // A dot is always drawn when a point is "isolated", + // i.e. there is a missing point on either side of it. + // This also controls the size of those dots. + drawPoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawpoints', false), + + // Draw points at the edges of gaps in the data. + // This improves visibility of small data segments or other data irregularities. + drawGapEdgePoints: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgapedgepoints', true), + connectSeparatedPoints: NETDATA.chartLibraries.dygraph.isLogScale(state) ? false : NETDATA.dataAttributeBoolean(state.element, 'dygraph-connectseparatedpoints', false), + pointSize: NETDATA.dataAttribute(state.element, 'dygraph-pointsize', 1), + + // enabling this makes the chart with little square lines + stepPlot: NETDATA.dataAttributeBoolean(state.element, 'dygraph-stepplot', false), + + // Draw a border around graph lines to make crossing lines more easily + // distinguishable. Useful for graphs with many lines. + strokeBorderColor: NETDATA.dataAttribute(state.element, 'dygraph-strokebordercolor', NETDATA.themes.current.background), + strokeBorderWidth: NETDATA.dataAttribute(state.element, 'dygraph-strokeborderwidth', (state.tmp.dygraph_chart_type === 'stacked') ? 0.0 : 0.0), + fillGraph: NETDATA.dataAttribute(state.element, 'dygraph-fillgraph', (state.tmp.dygraph_chart_type === 'area' || state.tmp.dygraph_chart_type === 'stacked')), + fillAlpha: NETDATA.dataAttribute(state.element, 'dygraph-fillalpha', + ((state.tmp.dygraph_chart_type === 'stacked') + ? NETDATA.options.current.color_fill_opacity_stacked + : NETDATA.options.current.color_fill_opacity_area) + ), + stackedGraph: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraph', (state.tmp.dygraph_chart_type === 'stacked')), + stackedGraphNaNFill: NETDATA.dataAttribute(state.element, 'dygraph-stackedgraphnanfill', 'none'), + drawAxis: drawAxis, + axisLabelFontSize: NETDATA.dataAttribute(state.element, 'dygraph-axislabelfontsize', 10), + axisLineColor: NETDATA.dataAttribute(state.element, 'dygraph-axislinecolor', NETDATA.themes.current.axis), + axisLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-axislinewidth', 1.0), + drawGrid: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawgrid', true), + gridLinePattern: NETDATA.dataAttribute(state.element, 'dygraph-gridlinepattern', null), + gridLineWidth: NETDATA.dataAttribute(state.element, 'dygraph-gridlinewidth', 1.0), + gridLineColor: NETDATA.dataAttribute(state.element, 'dygraph-gridlinecolor', NETDATA.themes.current.grid), + maxNumberWidth: NETDATA.dataAttribute(state.element, 'dygraph-maxnumberwidth', 8), + sigFigs: NETDATA.dataAttribute(state.element, 'dygraph-sigfigs', null), + digitsAfterDecimal: NETDATA.dataAttribute(state.element, 'dygraph-digitsafterdecimal', 2), + valueFormatter: NETDATA.dataAttribute(state.element, 'dygraph-valueformatter', undefined), + highlightCircleSize: NETDATA.dataAttribute(state.element, 'dygraph-highlightcirclesize', highlightCircleSize), + highlightSeriesOpts: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesopts', null), // TOO SLOW: { strokeWidth: 1.5 }, + highlightSeriesBackgroundAlpha: NETDATA.dataAttribute(state.element, 'dygraph-highlightseriesbackgroundalpha', null), // TOO SLOW: (state.tmp.dygraph_chart_type === 'stacked')?0.7:0.5, + pointClickCallback: NETDATA.dataAttribute(state.element, 'dygraph-pointclickcallback', undefined), + visibility: state.dimensions_visibility.selected2BooleanArray(state.data.dimension_names), + logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? 'y' : undefined, + + axes: { + x: { + pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-xpixelsperlabel', 50), + ticker: Dygraph.dateTicker, + axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-xaxislabelwidth', 60), + drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawxaxis', drawAxis), + axisLabelFormatter: function (d, gran) { + void(gran); + return NETDATA.dateTime.xAxisTimeString(d); + } + }, + y: { + logscale: NETDATA.chartLibraries.dygraph.isLogScale(state) ? true : undefined, + pixelsPerLabel: NETDATA.dataAttribute(state.element, 'dygraph-ypixelsperlabel', 15), + axisLabelWidth: NETDATA.dataAttribute(state.element, 'dygraph-yaxislabelwidth', 50), + drawAxis: NETDATA.dataAttributeBoolean(state.element, 'dygraph-drawyaxis', drawAxis), + axisLabelFormatter: function (y) { + + // unfortunately, we have to call this every single time + state.legendFormatValueDecimalsFromMinMax( + this.axes_[0].extremeRange[0], + this.axes_[0].extremeRange[1] + ); + + let old_units = this.user_attrs_.ylabel; + let v = state.legendFormatValue(y); + let new_units = state.units_current; + + if (state.units_desired === 'auto' && typeof old_units !== 'undefined' && new_units !== old_units && !NETDATA.chartLibraries.dygraph.isSparkline(state)) { + // console.log(this); + // state.log('units discrepancy: old = ' + old_units + ', new = ' + new_units); + let len = this.plugins_.length; + while (len--) { + // console.log(this.plugins_[len]); + if (typeof this.plugins_[len].plugin.ylabel_div_ !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_ !== null + && typeof this.plugins_[len].plugin.ylabel_div_.children !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_.children !== null + && typeof this.plugins_[len].plugin.ylabel_div_.children[0].children !== 'undefined' + && this.plugins_[len].plugin.ylabel_div_.children[0].children !== null + ) { + this.plugins_[len].plugin.ylabel_div_.children[0].children[0].innerHTML = new_units; + this.user_attrs_.ylabel = new_units; + break; + } + } + + if (len < 0) { + state.log('units discrepancy, but cannot find dygraphs div to change: old = ' + old_units + ', new = ' + new_units); + } + } + + return v; + } + } + }, + legendFormatter: function (data) { + if (state.tmp.dygraph_mouse_down) { + return; + } + + let elements = state.element_legend_childs; + + // if the hidden div is not there + // we are not managing the legend + if (elements.hidden === null) { + return; + } + + if (typeof data.x !== 'undefined') { + state.legendSetDate(data.x); + let i = data.series.length; + while (i--) { + let series = data.series[i]; + if (series.isVisible) { + state.legendSetLabelValue(series.label, series.y); + } else { + state.legendSetLabelValue(series.label, null); + } + } + } + + return ''; + }, + drawCallback: function (dygraph, is_initial) { + + // the user has panned the chart and this is called to re-draw the chart + // 1. refresh this chart by adding data to it + // 2. notify all the other charts about the update they need + + // to prevent an infinite loop (feedback), we use + // state.tmp.dygraph_user_action + // - when true, this is initiated by a user + // - when false, this is feedback + + if (state.current.name !== 'auto' && state.tmp.dygraph_user_action) { + state.tmp.dygraph_user_action = false; + + let x_range = dygraph.xAxisRange(); + let after = Math.round(x_range[0]); + let before = Math.round(x_range[1]); + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphDrawCallback(dygraph, ' + is_initial + '): mode ' + state.current.name + ' ' + (after / 1000).toString() + ' - ' + (before / 1000).toString()); + //console.log(state); + } + + if (before <= state.netdata_last && after >= state.netdata_first) { + // update only when we are within the data limits + state.updateChartPanOrZoom(after, before); + } + } + }, + zoomCallback: function (minDate, maxDate, yRanges) { + + // the user has selected a range on the chart + // 1. refresh this chart by adding data to it + // 2. notify all the other charts about the update they need + + void(yRanges); + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphZoomCallback(): ' + state.current.name); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + state.setMode('zoom'); + + // refresh it to the greatest possible zoom level + state.tmp.dygraph_user_action = true; + state.tmp.dygraph_force_zoom = true; + state.updateChartPanOrZoom(minDate, maxDate); + }, + highlightCallback: function (event, x, points, row, seriesName) { + void(seriesName); + + state.pauseChart(); + + // there is a bug in dygraph when the chart is zoomed enough + // the time it thinks is selected is wrong + // here we calculate the time t based on the row number selected + // which is ok + // let t = state.data_after + row * state.data_update_every; + // console.log('row = ' + row + ', x = ' + x + ', t = ' + t + ' ' + ((t === x)?'SAME':(Math.abs(x-t)<=state.data_update_every)?'SIMILAR':'DIFFERENT') + ', rows in db: ' + state.data_points + ' visible(x) = ' + state.timeIsVisible(x) + ' visible(t) = ' + state.timeIsVisible(t) + ' r(x) = ' + state.calculateRowForTime(x) + ' r(t) = ' + state.calculateRowForTime(t) + ' range: ' + state.data_after + ' - ' + state.data_before + ' real: ' + state.data.after + ' - ' + state.data.before + ' every: ' + state.data_update_every); + + if (state.tmp.dygraph_mouse_down !== true) { + NETDATA.globalSelectionSync.sync(state, x); + } + + // fix legend zIndex using the internal structures of dygraph legend module + // this works, but it is a hack! + // state.tmp.dygraph_instance.plugins_[0].plugin.legend_div_.style.zIndex = 10000; + }, + unhighlightCallback: function (event) { + void(event); + + if (state.tmp.dygraph_mouse_down) { + return; + } + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('dygraphUnhighlightCallback()'); + } + + state.unpauseChart(); + NETDATA.globalSelectionSync.stop(); + }, + underlayCallback: function (canvas, area, g) { + + // the chart is about to be drawn + // this function renders global highlighted time-frame + + if (NETDATA.globalChartUnderlay.isActive()) { + let after = NETDATA.globalChartUnderlay.after; + let before = NETDATA.globalChartUnderlay.before; + + if (after < state.view_after) { + after = state.view_after; + } + + if (before > state.view_before) { + before = state.view_before; + } + + if (after < before) { + let bottom_left = g.toDomCoords(after, -20); + let top_right = g.toDomCoords(before, +20); + + let left = bottom_left[0]; + let right = top_right[0]; + + canvas.fillStyle = NETDATA.themes.current.highlight; + canvas.fillRect(left, area.y, right - left, area.h); + } + } + }, + interactionModel: { + mousedown: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mousedown()'); + } + + state.tmp.dygraph_user_action = true; + + if (NETDATA.options.debug.dygraph) { + state.log('dygraphMouseDown()'); + } + + // Right-click should not initiate anything. + if (event.button && event.button === 2) { + return; + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_mouse_down = true; + context.initializeMouseDown(event, dygraph, context); + + //console.log(event); + if (event.button && event.button === 1) { + if (event.shiftKey) { + //console.log('middle mouse button dragging (PAN)'); + + state.setMode('pan'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startPan(event, dygraph, context); + } else if (event.altKey || event.ctrlKey || event.metaKey) { + //console.log('middle mouse button highlight'); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); + Dygraph.startZoom(event, dygraph, context); + } else { + //console.log('middle mouse button selection for zoom (ZOOM)'); + + state.setMode('zoom'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startZoom(event, dygraph, context); + } + } else { + if (event.shiftKey) { + //console.log('left mouse button selection for zoom (ZOOM)'); + + state.setMode('zoom'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startZoom(event, dygraph, context); + } else if (event.altKey || event.ctrlKey || event.metaKey) { + //console.log('left mouse button highlight'); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + state.tmp.dygraph_highlight_after = dygraph.toDataXCoord(event.offsetX); + Dygraph.startZoom(event, dygraph, context); + } else { + //console.log('left mouse button dragging (PAN)'); + + state.setMode('pan'); + // NETDATA.globalSelectionSync.delay(); + state.tmp.dygraph_highlight_after = null; + Dygraph.startPan(event, dygraph, context); + } + } + }, + mousemove: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mousemove()'); + } + + if (state.tmp.dygraph_highlight_after !== null) { + //console.log('highlight selection...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.moveZoom(event, dygraph, context); + event.preventDefault(); + } else if (context.isPanning) { + //console.log('panning...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + //NETDATA.globalSelectionSync.stop(); + //NETDATA.globalSelectionSync.delay(); + state.setMode('pan'); + context.is2DPan = false; + Dygraph.movePan(event, dygraph, context); + } else if (context.isZooming) { + //console.log('zooming...'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + //NETDATA.globalSelectionSync.stop(); + //NETDATA.globalSelectionSync.delay(); + state.setMode('zoom'); + Dygraph.moveZoom(event, dygraph, context); + } + }, + mouseup: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = false; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.mouseup()'); + } + + if (state.tmp.dygraph_highlight_after !== null) { + //console.log('done highlight selection'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + + NETDATA.globalChartUnderlay.set(state + , state.tmp.dygraph_highlight_after + , dygraph.toDataXCoord(event.offsetX) + , state.view_after + , state.view_before + ); + + state.tmp.dygraph_highlight_after = null; + + context.isZooming = false; + dygraph.clearZoomRect_(); + dygraph.drawGraph_(false); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } else if (context.isPanning) { + //console.log('done panning'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.endPan(event, dygraph, context); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } else if (context.isZooming) { + //console.log('done zomming'); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.endZoom(event, dygraph, context); + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } + }, + click: function (event, dygraph, context) { + void(dygraph); + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.click()'); + } + + event.preventDefault(); + }, + dblclick: function (event, dygraph, context) { + void(event); + void(dygraph); + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.dblclick()'); + } + NETDATA.resetAllCharts(state); + }, + wheel: function (event, dygraph, context) { + void(context); + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.wheel()'); + } + + // Take the offset of a mouse event on the dygraph canvas and + // convert it to a pair of percentages from the bottom left. + // (Not top left, bottom is where the lower value is.) + function offsetToPercentage(g, offsetX, offsetY) { + // This is calculating the pixel offset of the leftmost date. + let xOffset = g.toDomCoords(g.xAxisRange()[0], null)[0]; + let yar0 = g.yAxisRange(0); + + // This is calculating the pixel of the highest value. (Top pixel) + let yOffset = g.toDomCoords(null, yar0[1])[1]; + + // x y w and h are relative to the corner of the drawing area, + // so that the upper corner of the drawing area is (0, 0). + let x = offsetX - xOffset; + let y = offsetY - yOffset; + + // This is computing the rightmost pixel, effectively defining the + // width. + let w = g.toDomCoords(g.xAxisRange()[1], null)[0] - xOffset; + + // This is computing the lowest pixel, effectively defining the height. + let h = g.toDomCoords(null, yar0[0])[1] - yOffset; + + // Percentage from the left. + let xPct = w === 0 ? 0 : (x / w); + // Percentage from the top. + let yPct = h === 0 ? 0 : (y / h); + + // The (1-) part below changes it from "% distance down from the top" + // to "% distance up from the bottom". + return [xPct, (1 - yPct)]; + } + + // Adjusts [x, y] toward each other by zoomInPercentage% + // Split it so the left/bottom axis gets xBias/yBias of that change and + // tight/top gets (1-xBias)/(1-yBias) of that change. + // + // If a bias is missing it splits it down the middle. + function zoomRange(g, zoomInPercentage, xBias, yBias) { + xBias = xBias || 0.5; + yBias = yBias || 0.5; + + function adjustAxis(axis, zoomInPercentage, bias) { + let delta = axis[1] - axis[0]; + let increment = delta * zoomInPercentage; + let foo = [increment * bias, increment * (1 - bias)]; + + return [axis[0] + foo[0], axis[1] - foo[1]]; + } + + let yAxes = g.yAxisRanges(); + let newYAxes = []; + for (let i = 0; i < yAxes.length; i++) { + newYAxes[i] = adjustAxis(yAxes[i], zoomInPercentage, yBias); + } + + return adjustAxis(g.xAxisRange(), zoomInPercentage, xBias); + } + + if (event.altKey || event.shiftKey) { + state.tmp.dygraph_user_action = true; + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + // http://dygraphs.com/gallery/interaction-api.js + let normal_def; + if (typeof event.wheelDelta === 'number' && !isNaN(event.wheelDelta)) + // chrome + { + normal_def = event.wheelDelta / 40; + } else + // firefox + { + normal_def = event.deltaY * -1.2; + } + + let normal = (event.detail) ? event.detail * -1 : normal_def; + let percentage = normal / 50; + + if (!(event.offsetX && event.offsetY)) { + event.offsetX = event.layerX - event.target.offsetLeft; + event.offsetY = event.layerY - event.target.offsetTop; + } + + let percentages = offsetToPercentage(dygraph, event.offsetX, event.offsetY); + let xPct = percentages[0]; + let yPct = percentages[1]; + + let new_x_range = zoomRange(dygraph, percentage, xPct, yPct); + let after = new_x_range[0]; + let before = new_x_range[1]; + + let first = state.netdata_first + state.data_update_every; + let last = state.netdata_last + state.data_update_every; + + if (before > last) { + after -= (before - last); + before = last; + } + if (after < first) { + after = first; + } + + state.setMode('zoom'); + state.updateChartPanOrZoom(after, before, function () { + dygraph.updateOptions({dateWindow: [after, before]}); + }); + + event.preventDefault(); + } + }, + touchstart: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = true; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchstart()'); + } + + state.tmp.dygraph_user_action = true; + state.setMode('zoom'); + state.pauseChart(); + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + Dygraph.defaultInteractionModel.touchstart(event, dygraph, context); + + // we overwrite the touch directions at the end, to overwrite + // the internal default of dygraph + context.touchDirections = {x: true, y: false}; + + state.dygraph_last_touch_start = Date.now(); + state.dygraph_last_touch_move = 0; + + if (typeof event.touches[0].pageX === 'number') { + state.dygraph_last_touch_page_x = event.touches[0].pageX; + } else { + state.dygraph_last_touch_page_x = 0; + } + }, + touchmove: function (event, dygraph, context) { + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchmove()'); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.defaultInteractionModel.touchmove(event, dygraph, context); + + state.dygraph_last_touch_move = Date.now(); + }, + touchend: function (event, dygraph, context) { + state.tmp.dygraph_mouse_down = false; + + if (NETDATA.options.debug.dygraph || state.debug) { + state.log('interactionModel.touchend()'); + } + + NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.delay(); + + state.tmp.dygraph_user_action = true; + Dygraph.defaultInteractionModel.touchend(event, dygraph, context); + + // if it didn't move, it is a selection + if (state.dygraph_last_touch_move === 0 && state.dygraph_last_touch_page_x !== 0) { + NETDATA.globalSelectionSync.dontSyncBefore = 0; + NETDATA.globalSelectionSync.setMaster(state); + + // internal api of dygraph + let pct = (state.dygraph_last_touch_page_x - (dygraph.plotter_.area.x + state.element.getBoundingClientRect().left)) / dygraph.plotter_.area.w; + console.log('pct: ' + pct.toString()); + + let t = Math.round(state.view_after + (state.view_before - state.view_after) * pct); + if (NETDATA.dygraphSetSelection(state, t)) { + NETDATA.globalSelectionSync.sync(state, t); + } + } + + // if it was double tap within double click time, reset the charts + let now = Date.now(); + if (typeof state.dygraph_last_touch_end !== 'undefined') { + if (state.dygraph_last_touch_move === 0) { + let dt = now - state.dygraph_last_touch_end; + if (dt <= NETDATA.options.current.double_click_speed) { + NETDATA.resetAllCharts(state); + } + } + } + + // remember the timestamp of the last touch end + state.dygraph_last_touch_end = now; + + // refresh all the charts immediately + NETDATA.options.auto_refresher_stop_until = 0; + } + } + }; + + if (NETDATA.chartLibraries.dygraph.isLogScale(state)) { + if (Array.isArray(state.tmp.dygraph_options.valueRange) && state.tmp.dygraph_options.valueRange[0] <= 0) { + state.tmp.dygraph_options.valueRange[0] = null; + } + } + + if (NETDATA.chartLibraries.dygraph.isSparkline(state)) { + state.tmp.dygraph_options.drawGrid = false; + state.tmp.dygraph_options.drawAxis = false; + state.tmp.dygraph_options.title = undefined; + state.tmp.dygraph_options.ylabel = undefined; + state.tmp.dygraph_options.yLabelWidth = 0; + //state.tmp.dygraph_options.labelsDivWidth = 120; + //state.tmp.dygraph_options.labelsDivStyles.width = '120px'; + state.tmp.dygraph_options.labelsSeparateLines = true; + state.tmp.dygraph_options.rightGap = 0; + state.tmp.dygraph_options.yRangePad = 1; + state.tmp.dygraph_options.axes.x.drawAxis = false; + state.tmp.dygraph_options.axes.y.drawAxis = false; + } + + if (smooth) { + state.tmp.dygraph_smooth_eligible = true; + + if (NETDATA.options.current.smooth_plot) { + state.tmp.dygraph_options.plotter = smoothPlotter; + } + } + else { + state.tmp.dygraph_smooth_eligible = false; + } + + if (netdataSnapshotData !== null && NETDATA.globalPanAndZoom.isActive() && NETDATA.globalPanAndZoom.isMaster(state) === false) { + // pan and zoom on snapshots + state.tmp.dygraph_options.dateWindow = [NETDATA.globalPanAndZoom.force_after_ms, NETDATA.globalPanAndZoom.force_before_ms]; + //state.tmp.dygraph_options.isZoomedIgnoreProgrammaticZoom = true; + } + + state.tmp.dygraph_instance = new Dygraph(state.element_chart, + data.result.data, state.tmp.dygraph_options); + + state.tmp.dygraph_force_zoom = false; + state.tmp.dygraph_user_action = false; + state.tmp.dygraph_last_rendered = Date.now(); + state.tmp.dygraph_highlight_after = null; + + if (state.tmp.dygraph_options.valueRange[0] === null && state.tmp.dygraph_options.valueRange[1] === null) { + if (typeof state.tmp.dygraph_instance.axes_[0].extremeRange !== 'undefined') { + state.tmp.__commonMin = NETDATA.dataAttribute(state.element, 'common-min', null); + state.tmp.__commonMax = NETDATA.dataAttribute(state.element, 'common-max', null); + } else { + state.log('incompatible version of Dygraph detected'); + state.tmp.__commonMin = null; + state.tmp.__commonMax = null; + } + } else { + // if the user gave a valueRange, respect it + state.tmp.__commonMin = null; + state.tmp.__commonMax = null; + } + + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/easy-pie-chart.js b/web/gui/src/dashboard.js/charting/easy-pie-chart.js new file mode 100644 index 0000000..6905a10 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/easy-pie-chart.js @@ -0,0 +1,281 @@ +// ---------------------------------------------------------------------------------------------------------------- + +NETDATA.easypiechartPercentFromValueMinMax = function (state, value, min, max) { + if (typeof value !== 'number') { + value = 0; + } + if (typeof min !== 'number') { + min = 0; + } + if (typeof max !== 'number') { + max = 0; + } + + if (min > max) { + let t = min; + min = max; + max = t; + } + + if (min > value) { + min = value; + } + if (max < value) { + max = value; + } + + state.legendFormatValueDecimalsFromMinMax(min, max); + + if (state.tmp.easyPieChartMin === null && min > 0) { + min = 0; + } + if (state.tmp.easyPieChartMax === null && max < 0) { + max = 0; + } + + let pcent; + + if (min < 0 && max > 0) { + // it is both positive and negative + // zero at the top center of the chart + max = (-min > max) ? -min : max; + pcent = Math.round(value * 100 / max); + } else if (value >= 0 && min >= 0 && max >= 0) { + // clockwise + pcent = Math.round((value - min) * 100 / (max - min)); + if (pcent === 0) { + pcent = 0.1; + } + } else { + // counter clockwise + pcent = Math.round((value - max) * 100 / (max - min)); + if (pcent === 0) { + pcent = -0.1; + } + } + + return pcent; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// easy-pie-chart + +NETDATA.easypiechartInitialize = function (callback) { + if (typeof netdataNoEasyPieChart === 'undefined' || !netdataNoEasyPieChart) { + $.ajax({ + url: NETDATA.easypiechart_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('easypiechart', NETDATA.easypiechart_js); + }) + .fail(function () { + NETDATA.chartLibraries.easypiechart.enabled = false; + NETDATA.error(100, NETDATA.easypiechart_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }) + } else { + NETDATA.chartLibraries.easypiechart.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.easypiechartClearSelection = function (state, force) { + if (typeof state.tmp.easyPieChartEvent !== 'undefined' && typeof state.tmp.easyPieChartEvent.timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.easyPieChartEvent.timer); + state.tmp.easyPieChartEvent.timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.easypiechartChartUpdate(state, state.data); + } + else { + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(null); + state.tmp.easyPieChart_instance.update(0); + } + state.tmp.easyPieChart_instance.enableAnimation(); + + return true; +}; + +NETDATA.easypiechartSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.easypiechartClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.easypiechartClearSelection(state, true); + } + + if (typeof state.tmp.easyPieChartEvent === 'undefined') { + state.tmp.easyPieChartEvent = { + timer: undefined, + value: 0, + pcent: 0 + }; + } + + let value = state.data.result[state.data.result.length - 1 - slot]; + let min = (state.tmp.easyPieChartMin === null) ? NETDATA.commonMin.get(state) : state.tmp.easyPieChartMin; + let max = (state.tmp.easyPieChartMax === null) ? NETDATA.commonMax.get(state) : state.tmp.easyPieChartMax; + let pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + + state.tmp.easyPieChartEvent.value = value; + state.tmp.easyPieChartEvent.pcent = pcent; + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + + if (state.tmp.easyPieChartEvent.timer === undefined) { + state.tmp.easyPieChart_instance.disableAnimation(); + + state.tmp.easyPieChartEvent.timer = NETDATA.timeout.set(function () { + state.tmp.easyPieChartEvent.timer = undefined; + state.tmp.easyPieChart_instance.update(state.tmp.easyPieChartEvent.pcent); + }, 0); + } + + return true; +}; + +NETDATA.easypiechartChartUpdate = function (state, data) { + let value, min, max, pcent; + + if (NETDATA.globalPanAndZoom.isActive() || state.isAutoRefreshable() === false) { + value = null; + pcent = 0; + } + else { + value = data.result[0]; + min = (state.tmp.easyPieChartMin === null) ? NETDATA.commonMin.get(state) : state.tmp.easyPieChartMin; + max = (state.tmp.easyPieChartMax === null) ? NETDATA.commonMax.get(state) : state.tmp.easyPieChartMax; + pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + } + + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + state.tmp.easyPieChart_instance.update(pcent); + return true; +}; + +NETDATA.easypiechartChartCreate = function (state, data) { + let chart = $(state.element_chart); + + let value = data.result[0]; + let min = NETDATA.dataAttribute(state.element, 'easypiechart-min-value', null); + let max = NETDATA.dataAttribute(state.element, 'easypiechart-max-value', null); + + if (min === null) { + min = NETDATA.commonMin.get(state); + state.tmp.easyPieChartMin = null; + } + else { + state.tmp.easyPieChartMin = min; + } + + if (max === null) { + max = NETDATA.commonMax.get(state); + state.tmp.easyPieChartMax = null; + } + else { + state.tmp.easyPieChartMax = max; + } + + let size = state.chartWidth(); + let stroke = Math.floor(size / 22); + if (stroke < 3) { + stroke = 2; + } + + let valuefontsize = Math.floor((size * 2 / 3) / 5); + let valuetop = Math.round((size - valuefontsize - (size / 40)) / 2); + state.tmp.easyPieChartLabel = document.createElement('span'); + state.tmp.easyPieChartLabel.className = 'easyPieChartLabel'; + state.tmp.easyPieChartLabel.innerText = state.legendFormatValue(value); + state.tmp.easyPieChartLabel.style.fontSize = valuefontsize + 'px'; + state.tmp.easyPieChartLabel.style.top = valuetop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartLabel); + + let titlefontsize = Math.round(valuefontsize * 1.6 / 3); + let titletop = Math.round(valuetop - (titlefontsize * 2) - (size / 40)); + state.tmp.easyPieChartTitle = document.createElement('span'); + state.tmp.easyPieChartTitle.className = 'easyPieChartTitle'; + state.tmp.easyPieChartTitle.innerText = state.title; + state.tmp.easyPieChartTitle.style.fontSize = titlefontsize + 'px'; + state.tmp.easyPieChartTitle.style.lineHeight = titlefontsize + 'px'; + state.tmp.easyPieChartTitle.style.top = titletop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartTitle); + + let unitfontsize = Math.round(titlefontsize * 0.9); + let unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40)); + state.tmp.easyPieChartUnits = document.createElement('span'); + state.tmp.easyPieChartUnits.className = 'easyPieChartUnits'; + state.tmp.easyPieChartUnits.innerText = state.units_current; + state.tmp.easyPieChartUnits.style.fontSize = unitfontsize + 'px'; + state.tmp.easyPieChartUnits.style.top = unittop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.easyPieChartUnits); + + let barColor = NETDATA.dataAttribute(state.element, 'easypiechart-barcolor', undefined); + if (typeof barColor === 'undefined' || barColor === null) { + barColor = state.chartCustomColors()[0]; + } else { + // <div ... data-easypiechart-barcolor="(function(percent){return(percent < 50 ? '#5cb85c' : percent < 85 ? '#f0ad4e' : '#cb3935');})" ...></div> + let tmp = eval(barColor); + if (typeof tmp === 'function') { + barColor = tmp; + } + } + + let pcent = NETDATA.easypiechartPercentFromValueMinMax(state, value, min, max); + chart.data('data-percent', pcent); + + chart.easyPieChart({ + barColor: barColor, + trackColor: NETDATA.dataAttribute(state.element, 'easypiechart-trackcolor', NETDATA.themes.current.easypiechart_track), + scaleColor: NETDATA.dataAttribute(state.element, 'easypiechart-scalecolor', NETDATA.themes.current.easypiechart_scale), + scaleLength: NETDATA.dataAttribute(state.element, 'easypiechart-scalelength', 5), + lineCap: NETDATA.dataAttribute(state.element, 'easypiechart-linecap', 'round'), + lineWidth: NETDATA.dataAttribute(state.element, 'easypiechart-linewidth', stroke), + trackWidth: NETDATA.dataAttribute(state.element, 'easypiechart-trackwidth', undefined), + size: NETDATA.dataAttribute(state.element, 'easypiechart-size', size), + rotate: NETDATA.dataAttribute(state.element, 'easypiechart-rotate', 0), + animate: NETDATA.dataAttribute(state.element, 'easypiechart-animate', {duration: 500, enabled: true}), + easing: NETDATA.dataAttribute(state.element, 'easypiechart-easing', undefined) + }); + + // when we just re-create the chart + // do not animate the first update + let animate = true; + if (typeof state.tmp.easyPieChart_instance !== 'undefined') { + animate = false; + } + + state.tmp.easyPieChart_instance = chart.data('easyPieChart'); + if (animate === false) { + state.tmp.easyPieChart_instance.disableAnimation(); + } + state.tmp.easyPieChart_instance.update(pcent); + if (animate === false) { + state.tmp.easyPieChart_instance.enableAnimation(); + } + + state.legendSetUnitsString = function (units) { + if (typeof state.tmp.easyPieChartUnits !== 'undefined' && state.tmp.units !== units) { + state.tmp.easyPieChartUnits.innerText = units; + state.tmp.units = units; + } + }; + state.legendShowUndefined = function () { + if (typeof state.tmp.easyPieChart_instance !== 'undefined') { + NETDATA.easypiechartClearSelection(state); + } + }; + + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/gauge.js b/web/gui/src/dashboard.js/charting/gauge.js new file mode 100644 index 0000000..53ed46f --- /dev/null +++ b/web/gui/src/dashboard.js/charting/gauge.js @@ -0,0 +1,406 @@ +// gauge.js + +NETDATA.gaugeInitialize = function (callback) { + if (typeof netdataNoGauge === 'undefined' || !netdataNoGauge) { + $.ajax({ + url: NETDATA.gauge_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('gauge', NETDATA.gauge_js); + }) + .fail(function () { + NETDATA.chartLibraries.gauge.enabled = false; + NETDATA.error(100, NETDATA.gauge_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }) + } + else { + NETDATA.chartLibraries.gauge.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.gaugeAnimation = function (state, status) { + let speed = 32; + + if (typeof status === 'boolean' && status === false) { + speed = 1000000000; + } else if (typeof status === 'number') { + speed = status; + } + + // console.log('gauge speed ' + speed); + state.tmp.gauge_instance.animationSpeed = speed; + state.tmp.___gaugeOld__.speed = speed; +}; + +NETDATA.gaugeSet = function (state, value, min, max) { + if (typeof value !== 'number') { + value = 0; + } + if (typeof min !== 'number') { + min = 0; + } + if (typeof max !== 'number') { + max = 0; + } + if (value > max) { + max = value; + } + if (value < min) { + min = value; + } + if (min > max) { + let t = min; + min = max; + max = t; + } + else if (min === max) { + max = min + 1; + } + + state.legendFormatValueDecimalsFromMinMax(min, max); + + // gauge.js has an issue if the needle + // is smaller than min or larger than max + // when we set the new values + // the needle will go crazy + + // to prevent it, we always feed it + // with a percentage, so that the needle + // is always between min and max + let pcent = (value - min) * 100 / (max - min); + + // bug fix for gauge.js 1.3.1 + // if the value is the absolute min or max, the chart is broken + if (pcent < 0.001) { + pcent = 0.001; + } + if (pcent > 99.999) { + pcent = 99.999; + } + + state.tmp.gauge_instance.set(pcent); + // console.log('gauge set ' + pcent + ', value ' + value + ', min ' + min + ', max ' + max); + + state.tmp.___gaugeOld__.value = value; + state.tmp.___gaugeOld__.min = min; + state.tmp.___gaugeOld__.max = max; +}; + +NETDATA.gaugeSetLabels = function (state, value, min, max) { + if (state.tmp.___gaugeOld__.valueLabel !== value) { + state.tmp.___gaugeOld__.valueLabel = value; + state.tmp.gaugeChartLabel.innerText = state.legendFormatValue(value); + } + if (state.tmp.___gaugeOld__.minLabel !== min) { + state.tmp.___gaugeOld__.minLabel = min; + state.tmp.gaugeChartMin.innerText = state.legendFormatValue(min); + } + if (state.tmp.___gaugeOld__.maxLabel !== max) { + state.tmp.___gaugeOld__.maxLabel = max; + state.tmp.gaugeChartMax.innerText = state.legendFormatValue(max); + } +}; + +NETDATA.gaugeClearSelection = function (state, force) { + if (typeof state.tmp.gaugeEvent !== 'undefined' && typeof state.tmp.gaugeEvent.timer !== 'undefined') { + NETDATA.timeout.clear(state.tmp.gaugeEvent.timer); + state.tmp.gaugeEvent.timer = undefined; + } + + if (state.isAutoRefreshable() && state.data !== null && force !== true) { + NETDATA.gaugeChartUpdate(state, state.data); + } else { + NETDATA.gaugeAnimation(state, false); + NETDATA.gaugeSetLabels(state, null, null, null); + NETDATA.gaugeSet(state, null, null, null); + } + + NETDATA.gaugeAnimation(state, true); + return true; +}; + +NETDATA.gaugeSetSelection = function (state, t) { + if (state.timeIsVisible(t) !== true) { + return NETDATA.gaugeClearSelection(state, true); + } + + let slot = state.calculateRowForTime(t); + if (slot < 0 || slot >= state.data.result.length) { + return NETDATA.gaugeClearSelection(state, true); + } + + if (typeof state.tmp.gaugeEvent === 'undefined') { + state.tmp.gaugeEvent = { + timer: undefined, + value: 0, + min: 0, + max: 0 + }; + } + + let value = state.data.result[state.data.result.length - 1 - slot]; + let min = (state.tmp.gaugeMin === null) ? NETDATA.commonMin.get(state) : state.tmp.gaugeMin; + let max = (state.tmp.gaugeMax === null) ? NETDATA.commonMax.get(state) : state.tmp.gaugeMax; + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + state.tmp.gaugeEvent.value = value; + state.tmp.gaugeEvent.min = min; + state.tmp.gaugeEvent.max = max; + NETDATA.gaugeSetLabels(state, value, min, max); + + if (state.tmp.gaugeEvent.timer === undefined) { + NETDATA.gaugeAnimation(state, false); + + state.tmp.gaugeEvent.timer = NETDATA.timeout.set(function () { + state.tmp.gaugeEvent.timer = undefined; + NETDATA.gaugeSet(state, state.tmp.gaugeEvent.value, state.tmp.gaugeEvent.min, state.tmp.gaugeEvent.max); + }, 0); + } + + return true; +}; + +NETDATA.gaugeChartUpdate = function (state, data) { + let value, min, max; + + if (NETDATA.globalPanAndZoom.isActive() || state.isAutoRefreshable() === false) { + NETDATA.gaugeSetLabels(state, null, null, null); + state.tmp.gauge_instance.set(0); + } else { + value = data.result[0]; + min = (state.tmp.gaugeMin === null) ? NETDATA.commonMin.get(state) : state.tmp.gaugeMin; + max = (state.tmp.gaugeMax === null) ? NETDATA.commonMax.get(state) : state.tmp.gaugeMax; + if (value < min) { + min = value; + } + if (value > max) { + max = value; + } + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + NETDATA.gaugeSet(state, value, min, max); + NETDATA.gaugeSetLabels(state, value, min, max); + } + + return true; +}; + +NETDATA.gaugeChartCreate = function (state, data) { + // let chart = $(state.element_chart); + + let value = data.result[0]; + let min = NETDATA.dataAttribute(state.element, 'gauge-min-value', null); + let max = NETDATA.dataAttribute(state.element, 'gauge-max-value', null); + // let adjust = NETDATA.dataAttribute(state.element, 'gauge-adjust', null); + let pointerColor = NETDATA.dataAttribute(state.element, 'gauge-pointer-color', NETDATA.themes.current.gauge_pointer); + let strokeColor = NETDATA.dataAttribute(state.element, 'gauge-stroke-color', NETDATA.themes.current.gauge_stroke); + let startColor = NETDATA.dataAttribute(state.element, 'gauge-start-color', state.chartCustomColors()[0]); + let stopColor = NETDATA.dataAttribute(state.element, 'gauge-stop-color', void 0); + let generateGradient = NETDATA.dataAttribute(state.element, 'gauge-generate-gradient', false); + + if (min === null) { + min = NETDATA.commonMin.get(state); + state.tmp.gaugeMin = null; + } else { + state.tmp.gaugeMin = min; + } + + if (max === null) { + max = NETDATA.commonMax.get(state); + state.tmp.gaugeMax = null; + } else { + state.tmp.gaugeMax = max; + } + + // make sure it is zero based + // but only if it has not been set by the user + if (state.tmp.gaugeMin === null && min > 0) { + min = 0; + } + if (state.tmp.gaugeMax === null && max < 0) { + max = 0; + } + + let width = state.chartWidth(), height = state.chartHeight(); //, ratio = 1.5; + // console.log('gauge width: ' + width.toString() + ', height: ' + height.toString()); + //switch(adjust) { + // case 'width': width = height * ratio; break; + // case 'height': + // default: height = width / ratio; break; + //} + //state.element.style.width = width.toString() + 'px'; + //state.element.style.height = height.toString() + 'px'; + + let lum_d = 0.05; + + let options = { + lines: 12, // The number of lines to draw + angle: 0.14, // The span of the gauge arc + lineWidth: 0.57, // The line thickness + radiusScale: 1.0, // Relative radius + pointer: { + length: 0.85, // 0.9 The radius of the inner circle + strokeWidth: 0.045, // The rotation offset + color: pointerColor // Fill color + }, + limitMax: true, // If false, the max value of the gauge will be updated if value surpass max + limitMin: true, // If true, the min value of the gauge will be fixed unless you set it manually + colorStart: startColor, // Colors + colorStop: stopColor, // just experiment with them + strokeColor: strokeColor, // to see which ones work best for you + generateGradient: (generateGradient === true), // gmosx: + gradientType: 0, + highDpiSupport: true // High resolution support + }; + + if (generateGradient.constructor === Array) { + // example options: + // data-gauge-generate-gradient="[0, 50, 100]" + // data-gauge-gradient-percent-color-0="#FFFFFF" + // data-gauge-gradient-percent-color-50="#999900" + // data-gauge-gradient-percent-color-100="#000000" + + options.percentColors = []; + let len = generateGradient.length; + while (len--) { + let pcent = generateGradient[len]; + let color = NETDATA.dataAttribute(state.element, 'gauge-gradient-percent-color-' + pcent.toString(), false); + if (color !== false) { + let a = []; + a[0] = pcent / 100; + a[1] = color; + options.percentColors.unshift(a); + } + } + if (options.percentColors.length === 0) { + delete options.percentColors; + } + } else if (generateGradient === false && NETDATA.themes.current.gauge_gradient) { + //noinspection PointlessArithmeticExpressionJS + options.percentColors = [ + [0.0, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 0))], + [0.1, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 1))], + [0.2, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 2))], + [0.3, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 3))], + [0.4, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 4))], + [0.5, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 5))], + [0.6, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 6))], + [0.7, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 7))], + [0.8, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 8))], + [0.9, NETDATA.colorLuminance(startColor, (lum_d * 10) - (lum_d * 9))], + [1.0, NETDATA.colorLuminance(startColor, 0.0)]]; + } + + state.tmp.gauge_canvas = document.createElement('canvas'); + state.tmp.gauge_canvas.id = 'gauge-' + state.uuid + '-canvas'; + state.tmp.gauge_canvas.className = 'gaugeChart'; + state.tmp.gauge_canvas.width = width; + state.tmp.gauge_canvas.height = height; + state.element_chart.appendChild(state.tmp.gauge_canvas); + + let valuefontsize = Math.floor(height / 5); + let valuetop = Math.round((height - valuefontsize) / 3.2); + state.tmp.gaugeChartLabel = document.createElement('span'); + state.tmp.gaugeChartLabel.className = 'gaugeChartLabel'; + state.tmp.gaugeChartLabel.style.fontSize = valuefontsize + 'px'; + state.tmp.gaugeChartLabel.style.top = valuetop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartLabel); + + let titlefontsize = Math.round(valuefontsize / 2.1); + let titletop = 0; + state.tmp.gaugeChartTitle = document.createElement('span'); + state.tmp.gaugeChartTitle.className = 'gaugeChartTitle'; + state.tmp.gaugeChartTitle.innerText = state.title; + state.tmp.gaugeChartTitle.style.fontSize = titlefontsize + 'px'; + state.tmp.gaugeChartTitle.style.lineHeight = titlefontsize + 'px'; + state.tmp.gaugeChartTitle.style.top = titletop.toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartTitle); + + let unitfontsize = Math.round(titlefontsize * 0.9); + state.tmp.gaugeChartUnits = document.createElement('span'); + state.tmp.gaugeChartUnits.className = 'gaugeChartUnits'; + state.tmp.gaugeChartUnits.innerText = state.units_current; + state.tmp.gaugeChartUnits.style.fontSize = unitfontsize + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartUnits); + + state.tmp.gaugeChartMin = document.createElement('span'); + state.tmp.gaugeChartMin.className = 'gaugeChartMin'; + state.tmp.gaugeChartMin.style.fontSize = Math.round(valuefontsize * 0.75).toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartMin); + + state.tmp.gaugeChartMax = document.createElement('span'); + state.tmp.gaugeChartMax.className = 'gaugeChartMax'; + state.tmp.gaugeChartMax.style.fontSize = Math.round(valuefontsize * 0.75).toString() + 'px'; + state.element_chart.appendChild(state.tmp.gaugeChartMax); + + // when we just re-create the chart + // do not animate the first update + let animate = true; + if (typeof state.tmp.gauge_instance !== 'undefined') { + animate = false; + } + + state.tmp.gauge_instance = new Gauge(state.tmp.gauge_canvas).setOptions(options); // create sexy gauge! + + state.tmp.___gaugeOld__ = { + value: value, + min: min, + max: max, + valueLabel: null, + minLabel: null, + maxLabel: null + }; + + // we will always feed a percentage + state.tmp.gauge_instance.minValue = 0; + state.tmp.gauge_instance.maxValue = 100; + + NETDATA.gaugeAnimation(state, animate); + NETDATA.gaugeSet(state, value, min, max); + NETDATA.gaugeSetLabels(state, value, min, max); + NETDATA.gaugeAnimation(state, true); + + state.legendSetUnitsString = function (units) { + if (typeof state.tmp.gaugeChartUnits !== 'undefined' && state.tmp.units !== units) { + state.tmp.gaugeChartUnits.innerText = units; + state.tmp.___gaugeOld__.valueLabel = null; + state.tmp.___gaugeOld__.minLabel = null; + state.tmp.___gaugeOld__.maxLabel = null; + state.tmp.units = units; + } + }; + state.legendShowUndefined = function () { + if (typeof state.tmp.gauge_instance !== 'undefined') { + NETDATA.gaugeClearSelection(state); + } + }; + + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/google-charts.js b/web/gui/src/dashboard.js/charting/google-charts.js new file mode 100644 index 0000000..432c84a --- /dev/null +++ b/web/gui/src/dashboard.js/charting/google-charts.js @@ -0,0 +1,129 @@ +// google charts + +NETDATA.googleInitialize = function (callback) { + if (typeof netdataNoGoogleCharts === 'undefined' || !netdataNoGoogleCharts) { + $.ajax({ + url: NETDATA.google_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('google', NETDATA.google_js); + google.load('visualization', '1.1', { + 'packages': ['corechart', 'controls'], + 'callback': callback + }); + }) + .fail(function () { + NETDATA.chartLibraries.google.enabled = false; + NETDATA.error(100, NETDATA.google_js); + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.google.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.googleChartUpdate = function (state, data) { + let datatable = new google.visualization.DataTable(data.result); + state.google_instance.draw(datatable, state.google_options); + return true; +}; + +NETDATA.googleChartCreate = function (state, data) { + let datatable = new google.visualization.DataTable(data.result); + + state.google_options = { + colors: state.chartColors(), + + // do not set width, height - the chart resizes itself + //width: state.chartWidth(), + //height: state.chartHeight(), + lineWidth: 1, + title: state.title, + fontSize: 11, + hAxis: { + // title: "Time of Day", + // format:'HH:mm:ss', + viewWindowMode: 'maximized', + slantedText: false, + format: 'HH:mm:ss', + textStyle: { + fontSize: 9 + }, + gridlines: { + color: '#EEE' + } + }, + vAxis: { + title: state.units_current, + viewWindowMode: 'pretty', + minValue: -0.1, + maxValue: 0.1, + direction: 1, + textStyle: { + fontSize: 9 + }, + gridlines: { + color: '#EEE' + } + }, + chartArea: { + width: '65%', + height: '80%' + }, + focusTarget: 'category', + annotation: { + '1': { + style: 'line' + } + }, + pointsVisible: 0, + titlePosition: 'out', + titleTextStyle: { + fontSize: 11 + }, + tooltip: { + isHtml: false, + ignoreBounds: true, + textStyle: { + fontSize: 9 + } + }, + curveType: 'function', + areaOpacity: 0.3, + isStacked: false + }; + + switch (state.chart.chart_type) { + case "area": + state.google_options.vAxis.viewWindowMode = 'maximized'; + state.google_options.areaOpacity = NETDATA.options.current.color_fill_opacity_area; + state.google_instance = new google.visualization.AreaChart(state.element_chart); + break; + + case "stacked": + state.google_options.isStacked = true; + state.google_options.areaOpacity = NETDATA.options.current.color_fill_opacity_stacked; + state.google_options.vAxis.viewWindowMode = 'maximized'; + state.google_options.vAxis.minValue = null; + state.google_options.vAxis.maxValue = null; + state.google_instance = new google.visualization.AreaChart(state.element_chart); + break; + + default: + case "line": + state.google_options.lineWidth = 2; + state.google_instance = new google.visualization.LineChart(state.element_chart); + break; + } + + state.google_instance.draw(datatable, state.google_options); + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/peity.js b/web/gui/src/dashboard.js/charting/peity.js new file mode 100644 index 0000000..012fb9c --- /dev/null +++ b/web/gui/src/dashboard.js/charting/peity.js @@ -0,0 +1,62 @@ + +// peity + +NETDATA.peityInitialize = function (callback) { + if (typeof netdataNoPeitys === 'undefined' || !netdataNoPeitys) { + $.ajax({ + url: NETDATA.peity_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('peity', NETDATA.peity_js); + }) + .fail(function () { + NETDATA.chartLibraries.peity.enabled = false; + NETDATA.error(100, NETDATA.peity_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.peity.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.peityChartUpdate = function (state, data) { + state.peity_instance.innerHTML = data.result; + + if (state.peity_options.stroke !== state.chartCustomColors()[0]) { + state.peity_options.stroke = state.chartCustomColors()[0]; + if (state.chart.chart_type === 'line') { + state.peity_options.fill = NETDATA.themes.current.background; + } else { + state.peity_options.fill = NETDATA.colorLuminance(state.chartCustomColors()[0], NETDATA.chartDefaults.fill_luminance); + } + } + + $(state.peity_instance).peity('line', state.peity_options); + return true; +}; + +NETDATA.peityChartCreate = function (state, data) { + state.peity_instance = document.createElement('div'); + state.element_chart.appendChild(state.peity_instance); + + state.peity_options = { + stroke: NETDATA.themes.current.foreground, + strokeWidth: NETDATA.dataAttribute(state.element, 'peity-strokewidth', 1), + width: state.chartWidth(), + height: state.chartHeight(), + fill: NETDATA.themes.current.foreground + }; + + NETDATA.peityChartUpdate(state, data); + return true; +}; diff --git a/web/gui/src/dashboard.js/charting/sparkline.js b/web/gui/src/dashboard.js/charting/sparkline.js new file mode 100644 index 0000000..5d8a9e6 --- /dev/null +++ b/web/gui/src/dashboard.js/charting/sparkline.js @@ -0,0 +1,155 @@ +// ---------------------------------------------------------------------------------------------------------------- +// sparkline + +NETDATA.sparklineInitialize = function (callback) { + if (typeof netdataNoSparklines === 'undefined' || !netdataNoSparklines) { + $.ajax({ + url: NETDATA.sparkline_js, + cache: true, + dataType: "script", + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function () { + NETDATA.registerChartLibrary('sparkline', NETDATA.sparkline_js); + }) + .fail(function () { + NETDATA.chartLibraries.sparkline.enabled = false; + NETDATA.error(100, NETDATA.sparkline_js); + }) + .always(function () { + if (typeof callback === "function") { + return callback(); + } + }); + } else { + NETDATA.chartLibraries.sparkline.enabled = false; + if (typeof callback === "function") { + return callback(); + } + } +}; + +NETDATA.sparklineChartUpdate = function (state, data) { + state.sparkline_options.width = state.chartWidth(); + state.sparkline_options.height = state.chartHeight(); + + $(state.element_chart).sparkline(data.result, state.sparkline_options); + return true; +}; + +NETDATA.sparklineChartCreate = function (state, data) { + let type = NETDATA.dataAttribute(state.element, 'sparkline-type', 'line'); + let lineColor = NETDATA.dataAttribute(state.element, 'sparkline-linecolor', state.chartCustomColors()[0]); + let fillColor = NETDATA.dataAttribute(state.element, 'sparkline-fillcolor', ((state.chart.chart_type === 'line') ? NETDATA.themes.current.background : NETDATA.colorLuminance(lineColor, NETDATA.chartDefaults.fill_luminance))); + let chartRangeMin = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemin', undefined); + let chartRangeMax = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemax', undefined); + let composite = NETDATA.dataAttribute(state.element, 'sparkline-composite', undefined); + let enableTagOptions = NETDATA.dataAttribute(state.element, 'sparkline-enabletagoptions', undefined); + let tagOptionPrefix = NETDATA.dataAttribute(state.element, 'sparkline-tagoptionprefix', undefined); + let tagValuesAttribute = NETDATA.dataAttribute(state.element, 'sparkline-tagvaluesattribute', undefined); + let disableHiddenCheck = NETDATA.dataAttribute(state.element, 'sparkline-disablehiddencheck', undefined); + let defaultPixelsPerValue = NETDATA.dataAttribute(state.element, 'sparkline-defaultpixelspervalue', undefined); + let spotColor = NETDATA.dataAttribute(state.element, 'sparkline-spotcolor', undefined); + let minSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-minspotcolor', undefined); + let maxSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-maxspotcolor', undefined); + let spotRadius = NETDATA.dataAttribute(state.element, 'sparkline-spotradius', undefined); + let valueSpots = NETDATA.dataAttribute(state.element, 'sparkline-valuespots', undefined); + let highlightSpotColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightspotcolor', undefined); + let highlightLineColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightlinecolor', undefined); + let lineWidth = NETDATA.dataAttribute(state.element, 'sparkline-linewidth', undefined); + let normalRangeMin = NETDATA.dataAttribute(state.element, 'sparkline-normalrangemin', undefined); + let normalRangeMax = NETDATA.dataAttribute(state.element, 'sparkline-normalrangemax', undefined); + let drawNormalOnTop = NETDATA.dataAttribute(state.element, 'sparkline-drawnormalontop', undefined); + let xvalues = NETDATA.dataAttribute(state.element, 'sparkline-xvalues', undefined); + let chartRangeClip = NETDATA.dataAttribute(state.element, 'sparkline-chartrangeclip', undefined); + let chartRangeMinX = NETDATA.dataAttribute(state.element, 'sparkline-chartrangeminx', undefined); + let chartRangeMaxX = NETDATA.dataAttribute(state.element, 'sparkline-chartrangemaxx', undefined); + let disableInteraction = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disableinteraction', false); + let disableTooltips = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disabletooltips', false); + let disableHighlight = NETDATA.dataAttributeBoolean(state.element, 'sparkline-disablehighlight', false); + let highlightLighten = NETDATA.dataAttribute(state.element, 'sparkline-highlightlighten', 1.4); + let highlightColor = NETDATA.dataAttribute(state.element, 'sparkline-highlightcolor', undefined); + let tooltipContainer = NETDATA.dataAttribute(state.element, 'sparkline-tooltipcontainer', undefined); + let tooltipClassname = NETDATA.dataAttribute(state.element, 'sparkline-tooltipclassname', undefined); + let tooltipFormat = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformat', undefined); + let tooltipPrefix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipprefix', undefined); + let tooltipSuffix = NETDATA.dataAttribute(state.element, 'sparkline-tooltipsuffix', ' ' + state.units_current); + let tooltipSkipNull = NETDATA.dataAttributeBoolean(state.element, 'sparkline-tooltipskipnull', true); + let tooltipValueLookups = NETDATA.dataAttribute(state.element, 'sparkline-tooltipvaluelookups', undefined); + let tooltipFormatFieldlist = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformatfieldlist', undefined); + let tooltipFormatFieldlistKey = NETDATA.dataAttribute(state.element, 'sparkline-tooltipformatfieldlistkey', undefined); + let numberFormatter = NETDATA.dataAttribute(state.element, 'sparkline-numberformatter', function (n) { + return n.toFixed(2); + }); + let numberDigitGroupSep = NETDATA.dataAttribute(state.element, 'sparkline-numberdigitgroupsep', undefined); + let numberDecimalMark = NETDATA.dataAttribute(state.element, 'sparkline-numberdecimalmark', undefined); + let numberDigitGroupCount = NETDATA.dataAttribute(state.element, 'sparkline-numberdigitgroupcount', undefined); + let animatedZooms = NETDATA.dataAttributeBoolean(state.element, 'sparkline-animatedzooms', false); + + if (spotColor === 'disable') { + spotColor = ''; + } + if (minSpotColor === 'disable') { + minSpotColor = ''; + } + if (maxSpotColor === 'disable') { + maxSpotColor = ''; + } + + // state.log('sparkline type ' + type + ', lineColor: ' + lineColor + ', fillColor: ' + fillColor); + + state.sparkline_options = { + type: type, + lineColor: lineColor, + fillColor: fillColor, + chartRangeMin: chartRangeMin, + chartRangeMax: chartRangeMax, + composite: composite, + enableTagOptions: enableTagOptions, + tagOptionPrefix: tagOptionPrefix, + tagValuesAttribute: tagValuesAttribute, + disableHiddenCheck: disableHiddenCheck, + defaultPixelsPerValue: defaultPixelsPerValue, + spotColor: spotColor, + minSpotColor: minSpotColor, + maxSpotColor: maxSpotColor, + spotRadius: spotRadius, + valueSpots: valueSpots, + highlightSpotColor: highlightSpotColor, + highlightLineColor: highlightLineColor, + lineWidth: lineWidth, + normalRangeMin: normalRangeMin, + normalRangeMax: normalRangeMax, + drawNormalOnTop: drawNormalOnTop, + xvalues: xvalues, + chartRangeClip: chartRangeClip, + chartRangeMinX: chartRangeMinX, + chartRangeMaxX: chartRangeMaxX, + disableInteraction: disableInteraction, + disableTooltips: disableTooltips, + disableHighlight: disableHighlight, + highlightLighten: highlightLighten, + highlightColor: highlightColor, + tooltipContainer: tooltipContainer, + tooltipClassname: tooltipClassname, + tooltipChartTitle: state.title, + tooltipFormat: tooltipFormat, + tooltipPrefix: tooltipPrefix, + tooltipSuffix: tooltipSuffix, + tooltipSkipNull: tooltipSkipNull, + tooltipValueLookups: tooltipValueLookups, + tooltipFormatFieldlist: tooltipFormatFieldlist, + tooltipFormatFieldlistKey: tooltipFormatFieldlistKey, + numberFormatter: numberFormatter, + numberDigitGroupSep: numberDigitGroupSep, + numberDecimalMark: numberDecimalMark, + numberDigitGroupCount: numberDigitGroupCount, + animatedZooms: animatedZooms, + width: state.chartWidth(), + height: state.chartHeight() + }; + + $(state.element_chart).sparkline(data.result, state.sparkline_options); + + return true; +}; diff --git a/web/gui/src/dashboard.js/colors.js b/web/gui/src/dashboard.js/colors.js new file mode 100644 index 0000000..4b98c01 --- /dev/null +++ b/web/gui/src/dashboard.js/colors.js @@ -0,0 +1,34 @@ +NETDATA.colorHex2Rgb = function (hex) { + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + let shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function (m, r, g, b) { + return r + r + g + g + b + b; + }); + + let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +}; + +NETDATA.colorLuminance = function (hex, lum) { + // validate hex string + hex = String(hex).replace(/[^0-9a-f]/gi, ''); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + lum = lum || 0; + + // convert to decimal and change luminosity + let rgb = "#"; + for (let i = 0; i < 3; i++) { + let c = parseInt(hex.substr(i * 2, 2), 16); + c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); + rgb += ("00" + c).substr(c.length); + } + + return rgb; +}; diff --git a/web/gui/src/dashboard.js/common.js b/web/gui/src/dashboard.js/common.js new file mode 100644 index 0000000..4a97bab --- /dev/null +++ b/web/gui/src/dashboard.js/common.js @@ -0,0 +1,249 @@ + +// Compute common (joint) values over multiple charts. + + +// commonMin & commonMax + +NETDATA.commonMin = { + keys: {}, + latest: {}, + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + get: function (state) { + if (typeof state.tmp.__commonMin === 'undefined') { + // get the commonMin setting + state.tmp.__commonMin = NETDATA.dataAttribute(state.element, 'common-min', null); + } + + let min = state.data.min; + let name = state.tmp.__commonMin; + + if (name === null) { + // we don't need commonMin + //state.log('no need for commonMin'); + return min; + } + + let t = this.keys[name]; + if (typeof t === 'undefined') { + // add our commonMin + this.keys[name] = {}; + t = this.keys[name]; + } + + let uuid = state.uuid; + if (typeof t[uuid] !== 'undefined') { + if (t[uuid] === min) { + //state.log('commonMin ' + state.tmp.__commonMin + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } else if (min < this.latest[name]) { + //state.log('commonMin ' + state.tmp.__commonMin + ' increased: ' + min); + t[uuid] = min; + this.latest[name] = min; + return min; + } + } + + // add our min + t[uuid] = min; + + // find the common min + let m = min; + // for (let i in t) { + // if (t.hasOwnProperty(i) && t[i] < m) m = t[i]; + // } + for (var ti of Object.values(t)) { + if (ti < m) { + m = ti; + } + } + + //state.log('commonMin ' + state.tmp.__commonMin + ' updated: ' + m); + this.latest[name] = m; + return m; + } +}; + +NETDATA.commonMax = { + keys: {}, + latest: {}, + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + get: function (state) { + if (typeof state.tmp.__commonMax === 'undefined') { + // get the commonMax setting + state.tmp.__commonMax = NETDATA.dataAttribute(state.element, 'common-max', null); + } + + let max = state.data.max; + let name = state.tmp.__commonMax; + + if (name === null) { + // we don't need commonMax + //state.log('no need for commonMax'); + return max; + } + + let t = this.keys[name]; + if (typeof t === 'undefined') { + // add our commonMax + this.keys[name] = {}; + t = this.keys[name]; + } + + let uuid = state.uuid; + if (typeof t[uuid] !== 'undefined') { + if (t[uuid] === max) { + //state.log('commonMax ' + state.tmp.__commonMax + ' not changed: ' + this.latest[name]); + return this.latest[name]; + } else if (max > this.latest[name]) { + //state.log('commonMax ' + state.tmp.__commonMax + ' increased: ' + max); + t[uuid] = max; + this.latest[name] = max; + return max; + } + } + + // add our max + t[uuid] = max; + + // find the common max + let m = max; + // for (let i in t) { + // if (t.hasOwnProperty(i) && t[i] > m) m = t[i]; + // } + for (var ti of Object.values(t)) { + if (ti > m) { + m = ti; + } + } + + //state.log('commonMax ' + state.tmp.__commonMax + ' updated: ' + m); + this.latest[name] = m; + return m; + } +}; + +NETDATA.commonColors = { + keys: {}, + + globalReset: function () { + this.keys = {}; + }, + + get: function (state, label) { + let ret = this.refill(state); + + if (typeof ret.assigned[label] === 'undefined') { + ret.assigned[label] = ret.available.shift(); + } + + return ret.assigned[label]; + }, + + refill: function (state) { + let ret, len; + + if (typeof state.tmp.__commonColors === 'undefined') { + ret = this.prepare(state); + } else { + ret = this.keys[state.tmp.__commonColors]; + if (typeof ret === 'undefined') { + ret = this.prepare(state); + } + } + + if (ret.available.length === 0) { + if (ret.copy_theme || ret.custom.length === 0) { + // copy the theme colors + len = NETDATA.themes.current.colors.length; + while (len--) { + ret.available.unshift(NETDATA.themes.current.colors[len]); + } + } + + // copy the custom colors + len = ret.custom.length; + while (len--) { + ret.available.unshift(ret.custom[len]); + } + } + + state.colors_assigned = ret.assigned; + state.colors_available = ret.available; + state.colors_custom = ret.custom; + + return ret; + }, + + __read_custom_colors: function (state, ret) { + // add the user supplied colors + let c = NETDATA.dataAttribute(state.element, 'colors', undefined); + if (typeof c === 'string' && c.length > 0) { + c = c.split(' '); + let len = c.length; + + if (len > 0 && c[len - 1] === 'ONLY') { + len--; + ret.copy_theme = false; + } + + while (len--) { + ret.custom.unshift(c[len]); + } + } + }, + + prepare: function (state) { + let has_custom_colors = false; + + if (typeof state.tmp.__commonColors === 'undefined') { + let defname = state.chart.context; + + // if this chart has data-colors="" + // we should use the chart uuid as the default key (private palette) + // (data-common-colors="NAME" will be used anyways) + let c = NETDATA.dataAttribute(state.element, 'colors', undefined); + if (typeof c === 'string' && c.length > 0) { + defname = state.uuid; + has_custom_colors = true; + } + + // get the commonColors setting + state.tmp.__commonColors = NETDATA.dataAttribute(state.element, 'common-colors', defname); + } + + let name = state.tmp.__commonColors; + let ret = this.keys[name]; + + if (typeof ret === 'undefined') { + // add our commonMax + this.keys[name] = { + assigned: {}, // name-value of dimensions and their colors + available: [], // an array of colors available to be used + custom: [], // the array of colors defined by the user + charts: {}, // the charts linked to this + copy_theme: true + }; + ret = this.keys[name]; + } + + if (typeof ret.charts[state.uuid] === 'undefined') { + ret.charts[state.uuid] = state; + + if (has_custom_colors) { + this.__read_custom_colors(state, ret); + } + } + + return ret; + } +}; diff --git a/web/gui/src/dashboard.js/compatibility.js b/web/gui/src/dashboard.js/compatibility.js new file mode 100644 index 0000000..e1ecfbd --- /dev/null +++ b/web/gui/src/dashboard.js/compatibility.js @@ -0,0 +1,31 @@ +// *** src/dashboard.js/compatibility.js + +// Compatibility fixes. + +// fix IE issue with console +if (!window.console) { + window.console = { + log: function () { + } + }; +} + +// if string.endsWith is not defined, define it +if (typeof String.prototype.endsWith !== 'function') { + String.prototype.endsWith = function (s) { + if (s.length > this.length) { + return false; + } + return this.slice(-s.length) === s; + }; +} + +// if string.startsWith is not defined, define it +if (typeof String.prototype.startsWith !== 'function') { + String.prototype.startsWith = function (s) { + if (s.length > this.length) { + return false; + } + return this.slice(s.length) === s; + }; +} diff --git a/web/gui/src/dashboard.js/dependencies.js b/web/gui/src/dashboard.js/dependencies.js new file mode 100644 index 0000000..fff7818 --- /dev/null +++ b/web/gui/src/dashboard.js/dependencies.js @@ -0,0 +1,21 @@ + +// *** src/dashboard.js/dependencies.js + +// default URLs for all the external files we need +// make them RELATIVE so that the whole thing can also be +// installed under a web server +NETDATA.jQuery = NETDATA.serverStatic + 'lib/jquery-2.2.4.min.js'; +NETDATA.peity_js = NETDATA.serverStatic + 'lib/jquery.peity-3.2.0.min.js'; +NETDATA.sparkline_js = NETDATA.serverStatic + 'lib/jquery.sparkline-2.1.2.min.js'; +NETDATA.easypiechart_js = NETDATA.serverStatic + 'lib/jquery.easypiechart-97b5824.min.js'; +NETDATA.gauge_js = NETDATA.serverStatic + 'lib/gauge-1.3.2.min.js'; +NETDATA.dygraph_js = NETDATA.serverStatic + 'lib/dygraph-c91c859.min.js'; +NETDATA.dygraph_smooth_js = NETDATA.serverStatic + 'lib/dygraph-smooth-plotter-c91c859.js'; +// NETDATA.raphael_js = NETDATA.serverStatic + 'lib/raphael-2.2.4-min.js'; +// NETDATA.c3_js = NETDATA.serverStatic + 'lib/c3-0.4.18.min.js'; +// NETDATA.c3_css = NETDATA.serverStatic + 'css/c3-0.4.18.min.css'; +NETDATA.d3pie_js = NETDATA.serverStatic + 'lib/d3pie-0.2.1-netdata-3.js'; +NETDATA.d3_js = NETDATA.serverStatic + 'lib/d3-4.12.2.min.js'; +// NETDATA.morris_js = NETDATA.serverStatic + 'lib/morris-0.5.1.min.js'; +// NETDATA.morris_css = NETDATA.serverStatic + 'css/morris-0.5.1.css'; +NETDATA.google_js = 'https://www.google.com/jsapi'; diff --git a/web/gui/src/dashboard.js/epilogue.js.inc b/web/gui/src/dashboard.js/epilogue.js.inc new file mode 100644 index 0000000..c612988 --- /dev/null +++ b/web/gui/src/dashboard.js/epilogue.js.inc @@ -0,0 +1 @@ +})(window, document, (typeof jQuery === 'function')?jQuery:undefined); diff --git a/web/gui/src/dashboard.js/error-handling.js b/web/gui/src/dashboard.js/error-handling.js new file mode 100644 index 0000000..abc7c61 --- /dev/null +++ b/web/gui/src/dashboard.js/error-handling.js @@ -0,0 +1,52 @@ +// Error Handling + +NETDATA.errorCodes = { + 100: {message: "Cannot load chart library", alert: true}, + 101: {message: "Cannot load jQuery", alert: true}, + 402: {message: "Chart library not found", alert: false}, + 403: {message: "Chart library not enabled/is failed", alert: false}, + 404: {message: "Chart not found", alert: false}, + 405: {message: "Cannot download charts index from server", alert: true}, + 406: {message: "Invalid charts index downloaded from server", alert: true}, + 407: {message: "Cannot HELLO netdata server", alert: false}, + 408: {message: "Netdata servers sent invalid response to HELLO", alert: false}, + 409: {message: "Cannot ACCESS netdata registry", alert: false}, + 410: {message: "Netdata registry ACCESS failed", alert: false}, + 411: {message: "Netdata registry server send invalid response to DELETE ", alert: false}, + 412: {message: "Netdata registry DELETE failed", alert: false}, + 413: {message: "Netdata registry server send invalid response to SWITCH ", alert: false}, + 414: {message: "Netdata registry SWITCH failed", alert: false}, + 415: {message: "Netdata alarms download failed", alert: false}, + 416: {message: "Netdata alarms log download failed", alert: false}, + 417: {message: "Netdata registry server send invalid response to SEARCH ", alert: false}, + 418: {message: "Netdata registry SEARCH failed", alert: false} +}; + +NETDATA.errorLast = { + code: 0, + message: "", + datetime: 0 +}; + +NETDATA.error = function (code, msg) { + NETDATA.errorLast.code = code; + NETDATA.errorLast.message = msg; + NETDATA.errorLast.datetime = Date.now(); + + console.log("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg); + + let ret = true; + if (typeof netdataErrorCallback === 'function') { + ret = netdataErrorCallback('system', code, msg); + } + + if (ret && NETDATA.errorCodes[code].alert) { + alert("ERROR " + code + ": " + NETDATA.errorCodes[code].message + ": " + msg); + } +}; + +NETDATA.errorReset = function () { + NETDATA.errorLast.code = 0; + NETDATA.errorLast.message = "You are doing fine!"; + NETDATA.errorLast.datetime = 0; +}; diff --git a/web/gui/src/dashboard.js/localstorage.js b/web/gui/src/dashboard.js/localstorage.js new file mode 100644 index 0000000..5bbf5a2 --- /dev/null +++ b/web/gui/src/dashboard.js/localstorage.js @@ -0,0 +1,173 @@ + +// local storage options + +NETDATA.localStorage = { + default: {}, + current: {}, + callback: {} // only used for resetting back to defaults +}; + +NETDATA.localStorageTested = -1; +NETDATA.localStorageTest = function () { + if (NETDATA.localStorageTested !== -1) { + return NETDATA.localStorageTested; + } + + if (typeof Storage !== "undefined" && typeof localStorage === 'object') { + let test = 'test'; + try { + localStorage.setItem(test, test); + localStorage.removeItem(test); + NETDATA.localStorageTested = true; + } catch (e) { + NETDATA.localStorageTested = false; + } + } else { + NETDATA.localStorageTested = false; + } + + return NETDATA.localStorageTested; +}; + +NETDATA.localStorageGet = function (key, def, callback) { + let ret = def; + + if (typeof NETDATA.localStorage.default[key.toString()] === 'undefined') { + NETDATA.localStorage.default[key.toString()] = def; + NETDATA.localStorage.callback[key.toString()] = callback; + } + + if (NETDATA.localStorageTest()) { + try { + // console.log('localStorage: loading "' + key.toString() + '"'); + ret = localStorage.getItem(key.toString()); + // console.log('netdata loaded: ' + key.toString() + ' = ' + ret.toString()); + if (ret === null || ret === 'undefined') { + // console.log('localStorage: cannot load it, saving "' + key.toString() + '" with value "' + JSON.stringify(def) + '"'); + localStorage.setItem(key.toString(), JSON.stringify(def)); + ret = def; + } else { + // console.log('localStorage: got "' + key.toString() + '" with value "' + ret + '"'); + ret = JSON.parse(ret); + // console.log('localStorage: loaded "' + key.toString() + '" as value ' + ret + ' of type ' + typeof(ret)); + } + } catch (error) { + console.log('localStorage: failed to read "' + key.toString() + '", using default: "' + def.toString() + '"'); + ret = def; + } + } + + if (typeof ret === 'undefined' || ret === 'undefined') { + console.log('localStorage: LOADED UNDEFINED "' + key.toString() + '" as value ' + ret + ' of type ' + typeof(ret)); + ret = def; + } + + NETDATA.localStorage.current[key.toString()] = ret; + return ret; +}; + +NETDATA.localStorageSet = function (key, value, callback) { + if (typeof value === 'undefined' || value === 'undefined') { + console.log('localStorage: ATTEMPT TO SET UNDEFINED "' + key.toString() + '" as value ' + value + ' of type ' + typeof(value)); + } + + if (typeof NETDATA.localStorage.default[key.toString()] === 'undefined') { + NETDATA.localStorage.default[key.toString()] = value; + NETDATA.localStorage.current[key.toString()] = value; + NETDATA.localStorage.callback[key.toString()] = callback; + } + + if (NETDATA.localStorageTest()) { + // console.log('localStorage: saving "' + key.toString() + '" with value "' + JSON.stringify(value) + '"'); + try { + localStorage.setItem(key.toString(), JSON.stringify(value)); + } catch (e) { + console.log('localStorage: failed to save "' + key.toString() + '" with value: "' + value.toString() + '"'); + } + } + + NETDATA.localStorage.current[key.toString()] = value; + return value; +}; + +NETDATA.localStorageGetRecursive = function (obj, prefix, callback) { + let keys = Object.keys(obj); + let len = keys.length; + while (len--) { + let i = keys[len]; + + if (typeof obj[i] === 'object') { + //console.log('object ' + prefix + '.' + i.toString()); + NETDATA.localStorageGetRecursive(obj[i], prefix + '.' + i.toString(), callback); + continue; + } + + obj[i] = NETDATA.localStorageGet(prefix + '.' + i.toString(), obj[i], callback); + } +}; + +NETDATA.setOption = function (key, value) { + if (key.toString() === 'setOptionCallback') { + if (typeof NETDATA.options.current.setOptionCallback === 'function') { + NETDATA.options.current[key.toString()] = value; + NETDATA.options.current.setOptionCallback(); + } + } else if (NETDATA.options.current[key.toString()] !== value) { + let name = 'options.' + key.toString(); + + if (typeof NETDATA.localStorage.default[name.toString()] === 'undefined') { + console.log('localStorage: setOption() on unsaved option: "' + name.toString() + '", value: ' + value); + } + + //console.log(NETDATA.localStorage); + //console.log('setOption: setting "' + key.toString() + '" to "' + value + '" of type ' + typeof(value) + ' original type ' + typeof(NETDATA.options.current[key.toString()])); + //console.log(NETDATA.options); + NETDATA.options.current[key.toString()] = NETDATA.localStorageSet(name.toString(), value, null); + + if (typeof NETDATA.options.current.setOptionCallback === 'function') { + NETDATA.options.current.setOptionCallback(); + } + } + + return true; +}; + +NETDATA.getOption = function (key) { + return NETDATA.options.current[key.toString()]; +}; + +// read settings from local storage +NETDATA.localStorageGetRecursive(NETDATA.options.current, 'options', null); + +// always start with this option enabled. +NETDATA.setOption('stop_updates_when_focus_is_lost', true); + +NETDATA.resetOptions = function () { + let keys = Object.keys(NETDATA.localStorage.default); + let len = keys.length; + + while (len--) { + let i = keys[len]; + let a = i.split('.'); + + if (a[0] === 'options') { + if (a[1] === 'setOptionCallback') { + continue; + } + if (typeof NETDATA.localStorage.default[i] === 'undefined') { + continue; + } + if (NETDATA.options.current[i] === NETDATA.localStorage.default[i]) { + continue; + } + + NETDATA.setOption(a[1], NETDATA.localStorage.default[i]); + } else if (a[0] === 'chart_heights') { + if (typeof NETDATA.localStorage.callback[i] === 'function' && typeof NETDATA.localStorage.default[i] !== 'undefined') { + NETDATA.localStorage.callback[i](NETDATA.localStorage.default[i]); + } + } + } + + NETDATA.dateTime.init(NETDATA.options.current.timezone); +}; diff --git a/web/gui/src/dashboard.js/main.js b/web/gui/src/dashboard.js/main.js new file mode 100644 index 0000000..1d050d6 --- /dev/null +++ b/web/gui/src/dashboard.js/main.js @@ -0,0 +1,4276 @@ + +// *** src/dashboard.js/main.js + +// Codacy declarations +/* global clipboard */ + +if (NETDATA.options.debug.main_loop) { + console.log('welcome to NETDATA'); +} + +NETDATA.onresizeCallback = null; +NETDATA.onresize = function () { + NETDATA.options.last_page_resize = Date.now(); + NETDATA.onscroll(); + + if (typeof NETDATA.onresizeCallback === 'function') { + NETDATA.onresizeCallback(); + } +}; + +NETDATA.abortAllRefreshes = function () { + let targets = NETDATA.options.targets; + let len = targets.length; + + while (len--) { + if (targets[len].fetching_data) { + if (typeof targets[len].xhr !== 'undefined') { + targets[len].xhr.abort(); + targets[len].running = false; + targets[len].fetching_data = false; + } + } + } +}; + +NETDATA.onscrollStartDelay = function () { + NETDATA.options.last_page_scroll = Date.now(); + + NETDATA.options.on_scroll_refresher_stop_until = + NETDATA.options.last_page_scroll + + (NETDATA.options.current.async_on_scroll ? 1000 : 0); +}; + +NETDATA.onscrollEndDelay = function () { + NETDATA.options.on_scroll_refresher_stop_until = + Date.now() + + (NETDATA.options.current.async_on_scroll ? NETDATA.options.current.onscroll_worker_duration_threshold : 0); +}; + +NETDATA.onscroll_updater_timeout_id = undefined; +NETDATA.onscrollUpdater = function () { + NETDATA.globalSelectionSync.stop(); + + if (NETDATA.options.abort_ajax_on_scroll) { + NETDATA.abortAllRefreshes(); + } + + // when the user scrolls he sees that we have + // hidden all the not-visible charts + // using this little function we try to switch + // the charts back to visible quickly + + if (!NETDATA.intersectionObserver.enabled()) { + if (!NETDATA.options.current.parallel_refresher) { + let targets = NETDATA.options.targets; + let len = targets.length; + + while (len--) { + if (!targets[len].running) { + targets[len].isVisible(); + } + } + } + } + + NETDATA.onscrollEndDelay(); +}; + +NETDATA.scrollUp = false; +NETDATA.scrollY = window.scrollY; +NETDATA.onscroll = function () { + //console.log('onscroll() begin'); + + NETDATA.onscrollStartDelay(); + NETDATA.chartRefresherReschedule(); + + NETDATA.scrollUp = (window.scrollY > NETDATA.scrollY); + NETDATA.scrollY = window.scrollY; + + if (NETDATA.onscroll_updater_timeout_id) { + NETDATA.timeout.clear(NETDATA.onscroll_updater_timeout_id); + } + + NETDATA.onscroll_updater_timeout_id = NETDATA.timeout.set(NETDATA.onscrollUpdater, 0); + //console.log('onscroll() end'); +}; + +NETDATA.supportsPassiveEvents = function () { + if (NETDATA.options.passive_events === null) { + let supportsPassive = false; + try { + let opts = Object.defineProperty({}, 'passive', { + get: function () { + supportsPassive = true; + } + }); + window.addEventListener("test", null, opts); + } catch (e) { + console.log('browser does not support passive events'); + } + + NETDATA.options.passive_events = supportsPassive; + } + + // console.log('passive ' + NETDATA.options.passive_events); + return NETDATA.options.passive_events; +}; + +window.addEventListener('resize', NETDATA.onresize, NETDATA.supportsPassiveEvents() ? {passive: true} : false); +window.addEventListener('scroll', NETDATA.onscroll, NETDATA.supportsPassiveEvents() ? {passive: true} : false); +// window.onresize = NETDATA.onresize; +// window.onscroll = NETDATA.onscroll; + +// ---------------------------------------------------------------------------------------------------------------- +// Global Pan and Zoom on charts + +// Using this structure are synchronize all the charts, so that +// when you pan or zoom one, all others are automatically refreshed +// to the same timespan. + +NETDATA.globalPanAndZoom = { + seq: 0, // timestamp ms + // every time a chart is panned or zoomed + // we set the timestamp here + // then we use it as a sequence number + // to find if other charts are synchronized + // to this time-range + + master: null, // the master chart (state), to which all others + // are synchronized + + force_before_ms: null, // the timespan to sync all other charts + force_after_ms: null, + + callback: null, + + globalReset: function () { + this.clearMaster(); + this.seq = 0; + this.master = null; + this.force_after_ms = null; + this.force_before_ms = null; + this.callback = null; + }, + + delay: function () { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.delay()'); + } + + NETDATA.options.auto_refresher_stop_until = Date.now() + NETDATA.options.current.global_pan_sync_time; + }, + + // set a new master + setMaster: function (state, after, before) { + this.delay(); + + if (!NETDATA.options.current.sync_pan_and_zoom) { + return; + } + + if (this.master === null) { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.setMaster(' + state.id + ', ' + after + ', ' + before + ') SET MASTER'); + } + } else if (this.master !== state) { + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.setMaster(' + state.id + ', ' + after + ', ' + before + ') CHANGED MASTER'); + } + + this.master.resetChart(true, true); + } + + let now = Date.now(); + this.master = state; + this.seq = now; + this.force_after_ms = after; + this.force_before_ms = before; + + if (typeof this.callback === 'function') { + this.callback(true, after, before); + } + }, + + // clear the master + clearMaster: function () { + // if (NETDATA.options.debug.globalPanAndZoom === true) + // console.log('globalPanAndZoom.clearMaster()'); + if (NETDATA.options.debug.globalPanAndZoom) { + console.log('globalPanAndZoom.clearMaster()'); + } + + if (this.master !== null) { + let st = this.master; + this.master = null; + st.resetChart(); + } + + this.master = null; + this.seq = 0; + this.force_after_ms = null; + this.force_before_ms = null; + NETDATA.options.auto_refresher_stop_until = 0; + + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + }, + + // is the given state the master of the global + // pan and zoom sync? + isMaster: function (state) { + return (this.master === state); + }, + + // are we currently have a global pan and zoom sync? + isActive: function () { + return (this.master !== null && this.force_before_ms !== null && this.force_after_ms !== null && this.seq !== 0); + }, + + // check if a chart, other than the master + // needs to be refreshed, due to the global pan and zoom + shouldBeAutoRefreshed: function (state) { + if (this.master === null || this.seq === 0) { + return false; + } + + //if (state.needsRecreation()) + // return true; + + return (state.tm.pan_and_zoom_seq !== this.seq); + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// global chart underlay (time-frame highlighting) + +NETDATA.globalChartUnderlay = { + callback: null, // what to call when a highlighted range is setup + after: null, // highlight after this time + before: null, // highlight before this time + view_after: null, // the charts after_ms viewport when the highlight was setup + view_before: null, // the charts before_ms viewport, when the highlight was setup + state: null, // the chart the highlight was setup + + isActive: function () { + return (this.after !== null && this.before !== null); + }, + + hasViewport: function () { + return (this.state !== null && this.view_after !== null && this.view_before !== null); + }, + + init: function (state, after, before, view_after, view_before) { + this.state = (typeof state !== 'undefined') ? state : null; + this.after = (typeof after !== 'undefined' && after !== null && after > 0) ? after : null; + this.before = (typeof before !== 'undefined' && before !== null && before > 0) ? before : null; + this.view_after = (typeof view_after !== 'undefined' && view_after !== null && view_after > 0) ? view_after : null; + this.view_before = (typeof view_before !== 'undefined' && view_before !== null && view_before > 0) ? view_before : null; + }, + + setup: function () { + if (this.isActive()) { + if (this.state === null) { + this.state = NETDATA.options.targets[0]; + } + + if (typeof this.callback === 'function') { + this.callback(true, this.after, this.before); + } + } else { + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + } + }, + + set: function (state, after, before, view_after, view_before) { + if (after > before) { + let t = after; + after = before; + before = t; + } + + this.init(state, after, before, view_after, view_before); + + // if (this.hasViewport() === true) + // NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before); + if (this.hasViewport()) { + NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before); + } + + this.setup(); + }, + + clear: function () { + this.after = null; + this.before = null; + this.state = null; + this.view_after = null; + this.view_before = null; + + if (typeof this.callback === 'function') { + this.callback(false, 0, 0); + } + }, + + focus: function () { + if (this.isActive() && this.hasViewport()) { + if (this.state === null) { + this.state = NETDATA.options.targets[0]; + } + + if (NETDATA.globalPanAndZoom.isMaster(this.state)) { + NETDATA.globalPanAndZoom.clearMaster(); + } + + NETDATA.globalPanAndZoom.setMaster(this.state, this.view_after, this.view_before, true); + } + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// dimensions selection + +// TODO +// move color assignment to dimensions, here + +let dimensionStatus = function (parent, label, name_div, value_div, color) { + this.enabled = false; + this.parent = parent; + this.label = label; + this.name_div = null; + this.value_div = null; + this.color = NETDATA.themes.current.foreground; + this.selected = (parent.unselected_count === 0); + + this.setOptions(name_div, value_div, color); +}; + +dimensionStatus.prototype.invalidate = function () { + this.name_div = null; + this.value_div = null; + this.enabled = false; +}; + +dimensionStatus.prototype.setOptions = function (name_div, value_div, color) { + this.color = color; + + if (this.name_div !== name_div) { + this.name_div = name_div; + this.name_div.title = this.label; + this.name_div.style.setProperty('color', this.color, 'important'); + if (!this.selected) { + this.name_div.className = 'netdata-legend-name not-selected'; + } else { + this.name_div.className = 'netdata-legend-name selected'; + } + } + + if (this.value_div !== value_div) { + this.value_div = value_div; + this.value_div.title = this.label; + this.value_div.style.setProperty('color', this.color, 'important'); + if (!this.selected) { + this.value_div.className = 'netdata-legend-value not-selected'; + } else { + this.value_div.className = 'netdata-legend-value selected'; + } + } + + this.enabled = true; + this.setHandler(); +}; + +dimensionStatus.prototype.setHandler = function () { + if (!this.enabled) { + return; + } + + let ds = this; + + // this.name_div.onmousedown = this.value_div.onmousedown = function(e) { + this.name_div.onclick = this.value_div.onclick = function (e) { + e.preventDefault(); + if (ds.isSelected()) { + // this is selected + if (e.shiftKey || e.ctrlKey) { + // control or shift key is pressed -> unselect this (except is none will remain selected, in which case select all) + ds.unselect(); + + if (ds.parent.countSelected() === 0) { + ds.parent.selectAll(); + } + } else { + // no key is pressed -> select only this (except if it is the only selected already, in which case select all) + if (ds.parent.countSelected() === 1) { + ds.parent.selectAll(); + } else { + ds.parent.selectNone(); + ds.select(); + } + } + } + else { + // this is not selected + if (e.shiftKey || e.ctrlKey) { + // control or shift key is pressed -> select this too + ds.select(); + } else { + // no key is pressed -> select only this + ds.parent.selectNone(); + ds.select(); + } + } + + ds.parent.state.redrawChart(); + } +}; + +dimensionStatus.prototype.select = function () { + if (!this.enabled) { + return; + } + + this.name_div.className = 'netdata-legend-name selected'; + this.value_div.className = 'netdata-legend-value selected'; + this.selected = true; +}; + +dimensionStatus.prototype.unselect = function () { + if (!this.enabled) { + return; + } + + this.name_div.className = 'netdata-legend-name not-selected'; + this.value_div.className = 'netdata-legend-value hidden'; + this.selected = false; +}; + +dimensionStatus.prototype.isSelected = function () { + // return(this.enabled === true && this.selected === true); + return this.enabled && this.selected; +}; + +// ---------------------------------------------------------------------------------------------------------------- + +let dimensionsVisibility = function (state) { + this.state = state; + this.len = 0; + this.dimensions = {}; + this.selected_count = 0; + this.unselected_count = 0; +}; + +dimensionsVisibility.prototype.dimensionAdd = function (label, name_div, value_div, color) { + if (typeof this.dimensions[label] === 'undefined') { + this.len++; + this.dimensions[label] = new dimensionStatus(this, label, name_div, value_div, color); + } else { + this.dimensions[label].setOptions(name_div, value_div, color); + } + + return this.dimensions[label]; +}; + +dimensionsVisibility.prototype.dimensionGet = function (label) { + return this.dimensions[label]; +}; + +dimensionsVisibility.prototype.invalidateAll = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].invalidate(); + } +}; + +dimensionsVisibility.prototype.selectAll = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].select(); + } +}; + +dimensionsVisibility.prototype.countSelected = function () { + let selected = 0; + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + if (this.dimensions[keys[len]].isSelected()) { + selected++; + } + } + + return selected; +}; + +dimensionsVisibility.prototype.selectNone = function () { + let keys = Object.keys(this.dimensions); + let len = keys.length; + while (len--) { + this.dimensions[keys[len]].unselect(); + } +}; + +dimensionsVisibility.prototype.selected2BooleanArray = function (array) { + let ret = []; + this.selected_count = 0; + this.unselected_count = 0; + + let len = array.length; + while (len--) { + let ds = this.dimensions[array[len]]; + if (typeof ds === 'undefined') { + // console.log(array[i] + ' is not found'); + ret.unshift(false); + } else if (ds.isSelected()) { + ret.unshift(true); + this.selected_count++; + } else { + ret.unshift(false); + this.unselected_count++; + } + } + + if (this.selected_count === 0 && this.unselected_count !== 0) { + this.selectAll(); + return this.selected2BooleanArray(array); + } + + return ret; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// date/time conversion + +NETDATA.dateTime = { + using_timezone: false, + + // these are the old netdata functions + // we fallback to these, if the new ones fail + + localeDateStringNative: function (d) { + return d.toLocaleDateString(); + }, + + localeTimeStringNative: function (d) { + return d.toLocaleTimeString(); + }, + + xAxisTimeStringNative: function (d) { + return NETDATA.zeropad(d.getHours()) + ":" + + NETDATA.zeropad(d.getMinutes()) + ":" + + NETDATA.zeropad(d.getSeconds()); + }, + + // initialize the new date/time conversion + // functions. + // if this fails, we fallback to the above + init: function (timezone) { + //console.log('init with timezone: ' + timezone); + + // detect browser timezone + try { + NETDATA.options.browser_timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + } catch (e) { + console.log('failed to detect browser timezone: ' + e.toString()); + NETDATA.options.browser_timezone = 'cannot-detect-it'; + } + + let ret = false; + + try { + let dateOptions = { + localeMatcher: 'best fit', + formatMatcher: 'best fit', + weekday: 'short', + year: 'numeric', + month: 'short', + day: '2-digit' + }; + + let timeOptions = { + localeMatcher: 'best fit', + hour12: false, + formatMatcher: 'best fit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + + let xAxisOptions = { + localeMatcher: 'best fit', + hour12: false, + formatMatcher: 'best fit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit' + }; + + if (typeof timezone === 'string' && timezone !== '' && timezone !== 'default') { + dateOptions.timeZone = timezone; + timeOptions.timeZone = timezone; + timeOptions.timeZoneName = 'short'; + xAxisOptions.timeZone = timezone; + this.using_timezone = true; + } else { + timezone = 'default'; + this.using_timezone = false; + } + + this.dateFormat = new Intl.DateTimeFormat(navigator.language, dateOptions); + this.timeFormat = new Intl.DateTimeFormat(navigator.language, timeOptions); + this.xAxisFormat = new Intl.DateTimeFormat(navigator.language, xAxisOptions); + + this.localeDateString = function (d) { + return this.dateFormat.format(d); + }; + + this.localeTimeString = function (d) { + return this.timeFormat.format(d); + }; + + this.xAxisTimeString = function (d) { + return this.xAxisFormat.format(d); + }; + + //let d = new Date(); + //let t = this.dateFormat.format(d) + ' ' + this.timeFormat.format(d) + ' ' + this.xAxisFormat.format(d); + + ret = true; + } catch (e) { + console.log('Cannot setup Date/Time formatting: ' + e.toString()); + + timezone = 'default'; + this.localeDateString = this.localeDateStringNative; + this.localeTimeString = this.localeTimeStringNative; + this.xAxisTimeString = this.xAxisTimeStringNative; + this.using_timezone = false; + + ret = false; + } + + // save it + //console.log('init setOption timezone: ' + timezone); + NETDATA.setOption('timezone', timezone); + + return ret; + } +}; +NETDATA.dateTime.init(NETDATA.options.current.timezone); + +// ---------------------------------------------------------------------------------------------------------------- +// global selection sync + +NETDATA.globalSelectionSync = { + state: null, + dontSyncBefore: 0, + last_t: 0, + slaves: [], + timeoutId: undefined, + + globalReset: function () { + this.stop(); + this.state = null; + this.dontSyncBefore = 0; + this.last_t = 0; + this.slaves = []; + this.timeoutId = undefined; + }, + + active: function () { + return (this.state !== null); + }, + + // return true if global selection sync can be enabled now + enabled: function () { + // console.log('enabled()'); + // can we globally apply selection sync? + if (!NETDATA.options.current.sync_selection) { + return false; + } + + return (this.dontSyncBefore <= Date.now()); + }, + + // set the global selection sync master + setMaster: function (state) { + if (!this.enabled()) { + this.stop(); + return; + } + + if (this.state === state) { + return; + } + + if (this.state !== null) { + this.stop(); + } + + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.setMaster(' + state.id + ')'); + } + + state.selected = true; + this.state = state; + this.last_t = 0; + + // find all slaves + let targets = NETDATA.intersectionObserver.targets(); + this.slaves = []; + let len = targets.length; + while (len--) { + let st = targets[len]; + if (this.state !== st && st.globalSelectionSyncIsEligible()) { + this.slaves.push(st); + } + } + + // this.delay(100); + }, + + // stop global selection sync + stop: function () { + if (this.state !== null) { + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.stop()'); + } + + let len = this.slaves.length; + while (len--) { + this.slaves[len].clearSelection(); + } + + this.state.clearSelection(); + + this.last_t = 0; + this.slaves = []; + this.state = null; + } + }, + + // delay global selection sync for some time + delay: function (ms) { + if (NETDATA.options.current.sync_selection) { + // if (NETDATA.options.debug.globalSelectionSync === true) { + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.delay()'); + } + + if (typeof ms === 'number') { + this.dontSyncBefore = Date.now() + ms; + } else { + this.dontSyncBefore = Date.now() + NETDATA.options.current.sync_selection_delay; + } + } + }, + + __syncSlaves: function () { + // if (NETDATA.globalSelectionSync.enabled() === true) { + if (NETDATA.globalSelectionSync.enabled()) { + // if (NETDATA.options.debug.globalSelectionSync === true) + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.__syncSlaves()'); + } + + let t = NETDATA.globalSelectionSync.last_t; + let len = NETDATA.globalSelectionSync.slaves.length; + while (len--) { + NETDATA.globalSelectionSync.slaves[len].setSelection(t); + } + + this.timeoutId = undefined; + } + }, + + // sync all the visible charts to the given time + // this is to be called from the chart libraries + sync: function (state, t) { + // if (NETDATA.options.current.sync_selection === true) { + if (NETDATA.options.current.sync_selection) { + // if (NETDATA.options.debug.globalSelectionSync === true) + if (NETDATA.options.debug.globalSelectionSync) { + console.log('globalSelectionSync.sync(' + state.id + ', ' + t.toString() + ')'); + } + + this.setMaster(state); + + if (t === this.last_t) { + return; + } + + this.last_t = t; + + if (state.foreignElementSelection !== null) { + state.foreignElementSelection.innerText = NETDATA.dateTime.localeDateString(t) + ' ' + NETDATA.dateTime.localeTimeString(t); + } + + if (this.timeoutId) { + NETDATA.timeout.clear(this.timeoutId); + } + + this.timeoutId = NETDATA.timeout.set(this.__syncSlaves, 0); + } + } +}; + +NETDATA.intersectionObserver = { + observer: null, + visible_targets: [], + + options: { + root: null, + rootMargin: "0px", + threshold: null + }, + + enabled: function () { + return this.observer !== null; + }, + + globalReset: function () { + if (this.observer !== null) { + this.visible_targets = []; + this.observer.disconnect(); + this.init(); + } + }, + + targets: function () { + if (this.enabled() && this.visible_targets.length > 0) { + return this.visible_targets; + } else { + return NETDATA.options.targets; + } + }, + + switchChartVisibility: function () { + let old = this.__visibilityRatioOld; + + if (old !== this.__visibilityRatio) { + if (old === 0 && this.__visibilityRatio > 0) { + this.unhideChart(); + } else if (old > 0 && this.__visibilityRatio === 0) { + this.hideChart(); + } + + this.__visibilityRatioOld = this.__visibilityRatio; + } + }, + + handler: function (entries, observer) { + entries.forEach(function (entry) { + let state = NETDATA.chartState(entry.target); + + let idx; + if (entry.intersectionRatio > 0) { + idx = NETDATA.intersectionObserver.visible_targets.indexOf(state); + if (idx === -1) { + if (NETDATA.scrollUp) { + NETDATA.intersectionObserver.visible_targets.push(state); + } else { + NETDATA.intersectionObserver.visible_targets.unshift(state); + } + } + else if (state.__visibilityRatio === 0) { + state.log("was not visible until now, but was already in visible_targets"); + } + } else { + idx = NETDATA.intersectionObserver.visible_targets.indexOf(state); + if (idx !== -1) { + NETDATA.intersectionObserver.visible_targets.splice(idx, 1); + } else if (state.__visibilityRatio > 0) { + state.log("was visible, but not found in visible_targets"); + } + } + + state.__visibilityRatio = entry.intersectionRatio; + + if (!NETDATA.options.current.async_on_scroll) { + if (window.requestIdleCallback) { + window.requestIdleCallback(function () { + NETDATA.intersectionObserver.switchChartVisibility.call(state); + }, {timeout: 100}); + } else { + NETDATA.intersectionObserver.switchChartVisibility.call(state); + } + } + }); + }, + + observe: function (state) { + if (this.enabled()) { + state.__visibilityRatioOld = 0; + state.__visibilityRatio = 0; + this.observer.observe(state.element); + + state.isVisible = function () { + if (!NETDATA.options.current.update_only_visible) { + return true; + } + + NETDATA.intersectionObserver.switchChartVisibility.call(this); + + return this.__visibilityRatio > 0; + } + } + }, + + init: function () { + if (typeof netdataIntersectionObserver === 'undefined' || netdataIntersectionObserver) { + try { + this.observer = new IntersectionObserver(this.handler, this.options); + } catch (e) { + console.log("IntersectionObserver is not supported on this browser"); + this.observer = null; + } + } + //else { + // console.log("IntersectionObserver is disabled"); + //} + } +}; +NETDATA.intersectionObserver.init(); + +// ---------------------------------------------------------------------------------------------------------------- +// Our state object, where all per-chart values are stored + +let chartState = function (element) { + this.element = element; + + // IMPORTANT: + // all private functions should use 'that', instead of 'this' + // Alternatively, you can use arrow functions (related issue #4514) + let that = this; + + // ============================================================================================================ + // ERROR HANDLING + + /* error() - private + * show an error instead of the chart + */ + let error = (msg) => { + let ret = true; + + if (typeof netdataErrorCallback === 'function') { + ret = netdataErrorCallback('chart', this.id, msg); + } + + if (ret) { + this.element.innerHTML = this.id + ': ' + msg; + this.enabled = false; + this.current = this.pan; + } + }; + + // console logging + this.log = function (msg) { + console.log(this.id + ' (' + this.library_name + ' ' + this.uuid + '): ' + msg); + }; + + this.debugLog = function (msg) { + if (this.debug) { + this.log(msg); + } + }; + + // ============================================================================================================ + // EARLY INITIALIZATION + + // These are variables that should exist even if the chart is never to be rendered. + // Be careful what you add here - there may be thousands of charts on the page. + + // GUID - a unique identifier for the chart + this.uuid = NETDATA.guid(); + + // string - the name of chart + this.id = NETDATA.dataAttribute(this.element, 'netdata', undefined); + if (typeof this.id === 'undefined') { + error("netdata elements need data-netdata"); + return; + } + + // string - the key for localStorage settings + this.settings_id = NETDATA.dataAttribute(this.element, 'id', null); + + // the user given dimensions of the element + this.width = NETDATA.dataAttribute(this.element, 'width', NETDATA.chartDefaults.width); + this.height = NETDATA.dataAttribute(this.element, 'height', NETDATA.chartDefaults.height); + this.height_original = this.height; + + if (this.settings_id !== null) { + this.height = NETDATA.localStorageGet('chart_heights.' + this.settings_id, this.height, function (height) { + // this is the callback that will be called + // if and when the user resets all localStorage variables + // to their defaults + + resizeChartToHeight(height); + }); + } + + // the chart library requested by the user + this.library_name = NETDATA.dataAttribute(this.element, 'chart-library', NETDATA.chartDefaults.library); + + // check the requested library is available + // we don't initialize it here - it will be initialized when + // this chart will be first used + if (typeof NETDATA.chartLibraries[this.library_name] === 'undefined') { + NETDATA.error(402, this.library_name); + error('chart library "' + this.library_name + '" is not found'); + this.enabled = false; + } else if (!NETDATA.chartLibraries[this.library_name].enabled) { + NETDATA.error(403, this.library_name); + error('chart library "' + this.library_name + '" is not enabled'); + this.enabled = false; + } else { + this.library = NETDATA.chartLibraries[this.library_name]; + } + + this.auto = { + name: 'auto', + autorefresh: true, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + this.pan = { + name: 'pan', + autorefresh: false, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + this.zoom = { + name: 'zoom', + autorefresh: false, + force_update_at: 0, // the timestamp to force the update at + force_before_ms: null, + force_after_ms: null + }; + + // this is a pointer to one of the sub-classes below + // auto, pan, zoom + this.current = this.auto; + + this.running = false; // boolean - true when the chart is being refreshed now + this.enabled = true; // boolean - is the chart enabled for refresh? + + this.force_update_every = null; // number - overwrite the visualization update frequency of the chart + + this.tmp = {}; + + this.foreignElementBefore = null; + this.foreignElementAfter = null; + this.foreignElementDuration = null; + this.foreignElementUpdateEvery = null; + this.foreignElementSelection = null; + + // ============================================================================================================ + // PRIVATE FUNCTIONS + + // reset the runtime status variables to their defaults + const runtimeInit = () => { + this.paused = false; // boolean - is the chart paused for any reason? + this.selected = false; // boolean - is the chart shown a selection? + + this.chart_created = false; // boolean - is the library.create() been called? + this.dom_created = false; // boolean - is the chart DOM been created? + this.fetching_data = false; // boolean - true while we fetch data via ajax + + this.updates_counter = 0; // numeric - the number of refreshes made so far + this.updates_since_last_unhide = 0; // numeric - the number of refreshes made since the last time the chart was unhidden + this.updates_since_last_creation = 0; // numeric - the number of refreshes made since the last time the chart was created + + this.tm = { + last_initialized: 0, // milliseconds - the timestamp it was last initialized + last_dom_created: 0, // milliseconds - the timestamp its DOM was last created + last_mode_switch: 0, // milliseconds - the timestamp it switched modes + + last_info_downloaded: 0, // milliseconds - the timestamp we downloaded the chart + last_updated: 0, // the timestamp the chart last updated with data + pan_and_zoom_seq: 0, // the sequence number of the global synchronization + // between chart. + // Used with NETDATA.globalPanAndZoom.seq + last_visible_check: 0, // the time we last checked if it is visible + last_resized: 0, // the time the chart was resized + last_hidden: 0, // the time the chart was hidden + last_unhidden: 0, // the time the chart was unhidden + last_autorefreshed: 0 // the time the chart was last refreshed + }; + + this.data = null; // the last data as downloaded from the netdata server + this.data_url = 'invalid://'; // string - the last url used to update the chart + this.data_points = 0; // number - the number of points returned from netdata + this.data_after = 0; // milliseconds - the first timestamp of the data + this.data_before = 0; // milliseconds - the last timestamp of the data + this.data_update_every = 0; // milliseconds - the frequency to update the data + + this.tmp = {}; // members that can be destroyed to save memory + }; + + // initialize all the variables that are required for the chart to be rendered + const lateInitialization = () => { + if (typeof this.host !== 'undefined') { + return; + } + + // string - the netdata server URL, without any path + this.host = NETDATA.dataAttribute(this.element, 'host', NETDATA.serverDefault); + + // make sure the host does not end with / + // all netdata API requests use absolute paths + while (this.host.slice(-1) === '/') { + this.host = this.host.substring(0, this.host.length - 1); + } + + // string - the grouping method requested by the user + this.method = NETDATA.dataAttribute(this.element, 'method', NETDATA.chartDefaults.method); + this.gtime = NETDATA.dataAttribute(this.element, 'gtime', 0); + + // the time-range requested by the user + this.after = NETDATA.dataAttribute(this.element, 'after', NETDATA.chartDefaults.after); + this.before = NETDATA.dataAttribute(this.element, 'before', NETDATA.chartDefaults.before); + + // the pixels per point requested by the user + this.pixels_per_point = NETDATA.dataAttribute(this.element, 'pixels-per-point', 1); + this.points = NETDATA.dataAttribute(this.element, 'points', null); + + // the forced update_every + this.force_update_every = NETDATA.dataAttribute(this.element, 'update-every', null); + if (typeof this.force_update_every !== 'number' || this.force_update_every <= 1) { + if (this.force_update_every !== null) { + this.log('ignoring invalid value of property data-update-every'); + } + + this.force_update_every = null; + } else { + this.force_update_every *= 1000; + } + + // the dimensions requested by the user + this.dimensions = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'dimensions', null)); + + this.title = NETDATA.dataAttribute(this.element, 'title', null); // the title of the chart + this.units = NETDATA.dataAttribute(this.element, 'units', null); // the units of the chart dimensions + this.units_desired = NETDATA.dataAttribute(this.element, 'desired-units', NETDATA.options.current.units); // the units of the chart dimensions + this.units_current = this.units; + this.units_common = NETDATA.dataAttribute(this.element, 'common-units', null); + + // additional options to pass to netdata + this.append_options = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'append-options', null)); + + // override options to pass to netdata + this.override_options = NETDATA.encodeURIComponent(NETDATA.dataAttribute(this.element, 'override-options', null)); + + this.debug = NETDATA.dataAttributeBoolean(this.element, 'debug', false); + + this.value_decimal_detail = -1; + let d = NETDATA.dataAttribute(this.element, 'decimal-digits', -1); + if (typeof d === 'number') { + this.value_decimal_detail = d; + } else if (typeof d !== 'undefined') { + this.log('ignoring decimal-digits value: ' + d.toString()); + } + + // if we need to report the rendering speed + // find the element that needs to be updated + let refresh_dt_element_name = NETDATA.dataAttribute(this.element, 'dt-element-name', null); // string - the element to print refresh_dt_ms + + if (refresh_dt_element_name !== null) { + this.refresh_dt_element = document.getElementById(refresh_dt_element_name) || null; + } + else { + this.refresh_dt_element = null; + } + + this.dimensions_visibility = new dimensionsVisibility(that); + + this.netdata_first = 0; // milliseconds - the first timestamp in netdata + this.netdata_last = 0; // milliseconds - the last timestamp in netdata + this.requested_after = null; // milliseconds - the timestamp of the request after param + this.requested_before = null; // milliseconds - the timestamp of the request before param + this.requested_padding = null; + this.view_after = 0; + this.view_before = 0; + + this.refresh_dt_ms = 0; // milliseconds - the time the last refresh took + + // how many retries we have made to load chart data from the server + this.retries_on_data_failures = 0; + + // color management + this.colors = null; + this.colors_assigned = null; + this.colors_available = null; + this.colors_custom = null; + + this.element_message = null; // the element already created by the user + this.element_chart = null; // the element with the chart + this.element_legend = null; // the element with the legend of the chart (if created by us) + this.element_legend_childs = { + content: null, + hidden: null, + title_date: null, + title_time: null, + title_units: null, + perfect_scroller: null, // the container to apply perfect scroller to + series: null + }; + + this.chart_url = null; // string - the url to download chart info + this.chart = null; // object - the chart as downloaded from the server + + const getForeignElementById = (opt) => { + let id = NETDATA.dataAttribute(this.element, opt, null); + if (id === null) { + //this.log('option "' + opt + '" is undefined'); + return null; + } + + let el = document.getElementById(id); + if (typeof el === 'undefined') { + this.log('cannot find an element with name "' + id.toString() + '"'); + return null; + } + + return el; + }; + + this.foreignElementBefore = getForeignElementById('show-before-at'); + this.foreignElementAfter = getForeignElementById('show-after-at'); + this.foreignElementDuration = getForeignElementById('show-duration-at'); + this.foreignElementUpdateEvery = getForeignElementById('show-update-every-at'); + this.foreignElementSelection = getForeignElementById('show-selection-at'); + }; + + const destroyDOM = () => { + if (!this.enabled) { + return; + } + + if (this.debug) { + this.log('destroyDOM()'); + } + + // this.element.className = 'netdata-message icon'; + // this.element.innerHTML = '<i class="fas fa-sync"></i> netdata'; + this.element.innerHTML = ''; + this.element_message = null; + this.element_legend = null; + this.element_chart = null; + this.element_legend_childs.series = null; + + this.chart_created = false; + this.dom_created = false; + + this.tm.last_resized = 0; + this.tm.last_dom_created = 0; + }; + + let createDOM = () => { + if (!this.enabled) { + return; + } + lateInitialization(); + + destroyDOM(); + + if (this.debug) { + this.log('createDOM()'); + } + + this.element_message = document.createElement('div'); + this.element_message.className = 'netdata-message icon hidden'; + this.element.appendChild(this.element_message); + + this.dom_created = true; + this.chart_created = false; + + this.tm.last_dom_created = this.tm.last_resized = Date.now(); + + showLoading(); + }; + + const initDOM = () => { + this.element.className = this.library.container_class(that); + + if (typeof(this.width) === 'string') { + this.element.style.width = this.width; + } else if (typeof(this.width) === 'number') { + this.element.style.width = this.width.toString() + 'px'; + } + + if (typeof(this.library.aspect_ratio) === 'undefined') { + if (typeof(this.height) === 'string') { + this.element.style.height = this.height; + } else if (typeof(this.height) === 'number') { + this.element.style.height = this.height.toString() + 'px'; + } + } + + if (NETDATA.chartDefaults.min_width !== null) { + this.element.style.min_width = NETDATA.chartDefaults.min_width; + } + }; + + const invisibleSearchableText = () => { + return '<span style="position:absolute; opacity: 0; width: 0px;">' + this.id + '</span>'; + }; + + /* init() private + * initialize state variables + * destroy all (possibly) created state elements + * create the basic DOM for a chart + */ + const init = (opt) => { + if (!this.enabled) { + return; + } + + runtimeInit(); + this.element.innerHTML = invisibleSearchableText(); + + this.tm.last_initialized = Date.now(); + this.setMode('auto'); + + if (opt !== 'fast') { + if (this.isVisible(true) || opt === 'force') { + createDOM(); + } + } + }; + + const maxMessageFontSize = () => { + let screenHeight = screen.height; + let el = this.element; + + // normally we want a font size, as tall as the element + let h = el.clientHeight; + + // but give it some air, 20% let's say, or 5 pixels min + let lost = Math.max(h * 0.2, 5); + h -= lost; + + // center the text, vertically + let paddingTop = (lost - 5) / 2; + + // but check the width too + // it should fit 10 characters in it + let w = el.clientWidth / 10; + if (h > w) { + paddingTop += (h - w) / 2; + h = w; + } + + // and don't make it too huge + // 5% of the screen size is good + if (h > screenHeight / 20) { + paddingTop += (h - (screenHeight / 20)) / 2; + h = screenHeight / 20; + } + + // set it + this.element_message.style.fontSize = h.toString() + 'px'; + this.element_message.style.paddingTop = paddingTop.toString() + 'px'; + }; + + const showMessageIcon = (icon) => { + this.element_message.innerHTML = icon; + maxMessageFontSize(); + $(this.element_message).removeClass('hidden'); + this.tmp.___messageHidden___ = undefined; + }; + + const hideMessage = () => { + if (typeof this.tmp.___messageHidden___ === 'undefined') { + this.tmp.___messageHidden___ = true; + $(this.element_message).addClass('hidden'); + } + }; + + const showRendering = () => { + let icon; + if (this.chart !== null) { + if (this.chart.chart_type === 'line') { + icon = NETDATA.icons.lineChart; + } else { + icon = NETDATA.icons.areaChart; + } + } + else { + icon = NETDATA.icons.noChart; + } + + showMessageIcon(icon + ' netdata' + invisibleSearchableText()); + }; + + const showLoading = () => { + if (!this.chart_created) { + showMessageIcon(NETDATA.icons.loading + ' netdata'); + return true; + } + return false; + }; + + const isHidden = () => { + return (typeof this.tmp.___chartIsHidden___ !== 'undefined'); + }; + + // hide the chart, when it is not visible - called from isVisible() + this.hideChart = function () { + // hide it, if it is not already hidden + if (isHidden()) { + return; + } + + if (this.chart_created) { + if (NETDATA.options.current.show_help) { + if (this.element_legend_childs.toolbox !== null) { + if (this.debug) { + this.log('hideChart(): hidding legend popovers'); + } + + $(this.element_legend_childs.toolbox_left).popover('hide'); + $(this.element_legend_childs.toolbox_reset).popover('hide'); + $(this.element_legend_childs.toolbox_right).popover('hide'); + $(this.element_legend_childs.toolbox_zoomin).popover('hide'); + $(this.element_legend_childs.toolbox_zoomout).popover('hide'); + } + + if (this.element_legend_childs.resize_handler !== null) { + $(this.element_legend_childs.resize_handler).popover('hide'); + } + + if (this.element_legend_childs.content !== null) { + $(this.element_legend_childs.content).popover('hide'); + } + } + + if (NETDATA.options.current.destroy_on_hide) { + if (this.debug) { + this.log('hideChart(): initializing chart'); + } + + // we should destroy it + init('force'); + } else { + if (this.debug) { + this.log('hideChart(): hiding chart'); + } + + showRendering(); + this.element_chart.style.display = 'none'; + this.element.style.willChange = 'auto'; + if (this.element_legend !== null) { + this.element_legend.style.display = 'none'; + } + if (this.element_legend_childs.toolbox !== null) { + this.element_legend_childs.toolbox.style.display = 'none'; + } + if (this.element_legend_childs.resize_handler !== null) { + this.element_legend_childs.resize_handler.style.display = 'none'; + } + + this.tm.last_hidden = Date.now(); + + // de-allocate data + // This works, but I not sure there are no corner cases somewhere + // so it is commented - if the user has memory issues he can + // set Destroy on Hide for all charts + // this.data = null; + } + } + + this.tmp.___chartIsHidden___ = true; + }; + + // unhide the chart, when it is visible - called from isVisible() + this.unhideChart = function () { + if (!isHidden()) { + return; + } + + this.tmp.___chartIsHidden___ = undefined; + this.updates_since_last_unhide = 0; + + if (!this.chart_created) { + if (this.debug) { + this.log('unhideChart(): initializing chart'); + } + + // we need to re-initialize it, to show our background + // logo in bootstrap tabs, until the chart loads + init('force'); + } else { + if (this.debug) { + this.log('unhideChart(): unhiding chart'); + } + + this.element.style.willChange = 'transform'; + this.tm.last_unhidden = Date.now(); + this.element_chart.style.display = ''; + if (this.element_legend !== null) { + this.element_legend.style.display = ''; + } + if (this.element_legend_childs.toolbox !== null) { + this.element_legend_childs.toolbox.style.display = ''; + } + if (this.element_legend_childs.resize_handler !== null) { + this.element_legend_childs.resize_handler.style.display = ''; + } + resizeChart(); + hideMessage(); + } + + if (this.__redraw_on_unhide) { + if (this.debug) { + this.log("redrawing chart on unhide"); + } + + this.__redraw_on_unhide = undefined; + this.redrawChart(); + } + }; + + const canBeRendered = (uncached_visibility) => { + if (this.debug) { + this.log('canBeRendered() called'); + } + + if (!NETDATA.options.current.update_only_visible) { + return true; + } + + let ret = ( + ( + NETDATA.options.page_is_visible || + NETDATA.options.current.stop_updates_when_focus_is_lost === false || + this.updates_since_last_unhide === 0 + ) + && isHidden() === false && this.isVisible(uncached_visibility) + ); + + if (this.debug) { + this.log('canBeRendered(): ' + ret); + } + + return ret; + }; + + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers + const callChartLibraryUpdateSafely = (data) => { + let status; + + // we should not do this here + // if we prevent rendering the chart then: + // 1. globalSelectionSync will be wrong + // 2. globalPanAndZoom will be wrong + //if (canBeRendered(true) === false) + // return false; + + if (NETDATA.options.fake_chart_rendering) { + return true; + } + + this.updates_counter++; + this.updates_since_last_unhide++; + this.updates_since_last_creation++; + + if (NETDATA.options.debug.chart_errors) { + status = this.library.update(that, data); + } else { + try { + status = this.library.update(that, data); + } catch (err) { + status = false; + } + } + + if (!status) { + error('chart failed to be updated as ' + this.library_name); + return false; + } + + return true; + }; + + // https://github.com/petkaantonov/bluebird/wiki/Optimization-killers + const callChartLibraryCreateSafely = (data) => { + let status; + + // we should not do this here + // if we prevent rendering the chart then: + // 1. globalSelectionSync will be wrong + // 2. globalPanAndZoom will be wrong + //if (canBeRendered(true) === false) + // return false; + + if (NETDATA.options.fake_chart_rendering) { + return true; + } + + this.updates_counter++; + this.updates_since_last_unhide++; + this.updates_since_last_creation++; + + if (NETDATA.options.debug.chart_errors) { + status = this.library.create(that, data); + } else { + try { + status = this.library.create(that, data); + } catch (err) { + status = false; + } + } + + if (!status) { + error('chart failed to be created as ' + this.library_name); + return false; + } + + this.chart_created = true; + this.updates_since_last_creation = 0; + return true; + }; + + // ---------------------------------------------------------------------------------------------------------------- + // Chart Resize + + // resizeChart() - private + // to be called just before the chart library to make sure that + // a properly sized dom is available + const resizeChart = () => { + if (this.tm.last_resized < NETDATA.options.last_page_resize) { + if (!this.chart_created) { + return; + } + + if (this.needsRecreation()) { + if (this.debug) { + this.log('resizeChart(): initializing chart'); + } + + init('force'); + } else if (typeof this.library.resize === 'function') { + if (this.debug) { + this.log('resizeChart(): resizing chart'); + } + + this.library.resize(that); + + if (this.element_legend_childs.perfect_scroller !== null) { + Ps.update(this.element_legend_childs.perfect_scroller); + } + + maxMessageFontSize(); + } + + this.tm.last_resized = Date.now(); + } + }; + + // this is the actual chart resize algorithm + // it will: + // - resize the entire container + // - update the internal states + // - resize the chart as the div changes height + // - update the scrollbar of the legend + const resizeChartToHeight = (h) => { + // console.log(h); + this.element.style.height = h; + + if (this.settings_id !== null) { + NETDATA.localStorageSet('chart_heights.' + this.settings_id, h); + } + + let now = Date.now(); + NETDATA.options.last_page_scroll = now; + NETDATA.options.auto_refresher_stop_until = now + NETDATA.options.current.stop_updates_while_resizing; + + // force a resize + this.tm.last_resized = 0; + resizeChart(); + }; + + this.resizeForPrint = function () { + if (typeof this.element_legend_childs !== 'undefined' && this.element_legend_childs.perfect_scroller !== null) { + let current = this.element.clientHeight; + let optimal = current + + this.element_legend_childs.perfect_scroller.scrollHeight + - this.element_legend_childs.perfect_scroller.clientHeight; + + if (optimal > current) { + // this.log('resized'); + this.element.style.height = optimal + 'px'; + this.library.resize(this); + } + } + }; + + this.resizeHandler = function (e) { + e.preventDefault(); + + if (typeof this.event_resize === 'undefined' + || this.event_resize.chart_original_w === 'undefined' + || this.event_resize.chart_original_h === 'undefined') { + this.event_resize = { + chart_original_w: this.element.clientWidth, + chart_original_h: this.element.clientHeight, + last: 0 + }; + } + + if (e.type === 'touchstart') { + this.event_resize.mouse_start_x = e.touches.item(0).pageX; + this.event_resize.mouse_start_y = e.touches.item(0).pageY; + } else { + this.event_resize.mouse_start_x = e.clientX; + this.event_resize.mouse_start_y = e.clientY; + } + + this.event_resize.chart_start_w = this.element.clientWidth; + this.event_resize.chart_start_h = this.element.clientHeight; + this.event_resize.chart_last_w = this.element.clientWidth; + this.event_resize.chart_last_h = this.element.clientHeight; + + let now = Date.now(); + if (now - this.event_resize.last <= NETDATA.options.current.double_click_speed && this.element_legend_childs.perfect_scroller !== null) { + // double click / double tap event + + // console.dir(this.element_legend_childs.content); + // console.dir(this.element_legend_childs.perfect_scroller); + + // the optimal height of the chart + // showing the entire legend + let optimal = this.event_resize.chart_last_h + + this.element_legend_childs.perfect_scroller.scrollHeight + - this.element_legend_childs.perfect_scroller.clientHeight; + + // if we are not optimal, be optimal + if (this.event_resize.chart_last_h !== optimal) { + // this.log('resize to optimal, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(optimal.toString() + 'px'); + } + + // else if the current height is not the original/saved height + // reset to the original/saved height + else if (this.event_resize.chart_last_h !== this.event_resize.chart_original_h) { + // this.log('resize to original, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(this.event_resize.chart_original_h.toString() + 'px'); + } + + // else if the current height is not the internal default height + // reset to the internal default height + else if ((this.event_resize.chart_last_h.toString() + 'px') !== this.height_original) { + // this.log('resize to internal default, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString()); + resizeChartToHeight(this.height_original.toString()); + } + + // else if the current height is not the firstchild's clientheight + // resize to it + else if (typeof this.element_legend_childs.perfect_scroller.firstChild !== 'undefined') { + let parent_rect = this.element.getBoundingClientRect(); + let content_rect = this.element_legend_childs.perfect_scroller.firstElementChild.getBoundingClientRect(); + let wanted = content_rect.top - parent_rect.top + this.element_legend_childs.perfect_scroller.firstChild.clientHeight + 18; // 15 = toolbox + 3 space + + // console.log(parent_rect); + // console.log(content_rect); + // console.log(wanted); + + // this.log('resize to firstChild, current = ' + this.event_resize.chart_last_h.toString() + 'px, original = ' + this.event_resize.chart_original_h.toString() + 'px, optimal = ' + optimal.toString() + 'px, internal = ' + this.height_original.toString() + 'px, firstChild = ' + wanted.toString() + 'px' ); + if (this.event_resize.chart_last_h !== wanted) { + resizeChartToHeight(wanted.toString() + 'px'); + } + } + } else { + this.event_resize.last = now; + + // process movement event + document.onmousemove = + document.ontouchmove = + this.element_legend_childs.resize_handler.onmousemove = + this.element_legend_childs.resize_handler.ontouchmove = + function (e) { + let y = null; + + switch (e.type) { + case 'mousemove': + y = e.clientY; + break; + case 'touchmove': + y = e.touches.item(e.touches - 1).pageY; + break; + } + + if (y !== null) { + let newH = that.event_resize.chart_start_h + y - that.event_resize.mouse_start_y; + + if (newH >= 70 && newH !== that.event_resize.chart_last_h) { + resizeChartToHeight(newH.toString() + 'px'); + that.event_resize.chart_last_h = newH; + } + } + }; + + // process end event + document.onmouseup = + document.ontouchend = + this.element_legend_childs.resize_handler.onmouseup = + this.element_legend_childs.resize_handler.ontouchend = + function (e) { + void(e); + + // remove all the hooks + document.onmouseup = + document.onmousemove = + document.ontouchmove = + document.ontouchend = + that.element_legend_childs.resize_handler.onmousemove = + that.element_legend_childs.resize_handler.ontouchmove = + that.element_legend_childs.resize_handler.onmouseout = + that.element_legend_childs.resize_handler.onmouseup = + that.element_legend_childs.resize_handler.ontouchend = + null; + + // allow auto-refreshes + NETDATA.options.auto_refresher_stop_until = 0; + }; + } + }; + + const noDataToShow = () => { + showMessageIcon(NETDATA.icons.noData + ' empty'); + this.legendUpdateDOM(); + this.tm.last_autorefreshed = Date.now(); + // this.data_update_every = 30 * 1000; + //this.element_chart.style.display = 'none'; + //if (this.element_legend !== null) this.element_legend.style.display = 'none'; + //this.tmp.___chartIsHidden___ = true; + }; + + // ============================================================================================================ + // PUBLIC FUNCTIONS + + this.error = function (msg) { + error(msg); + }; + + this.setMode = function (m) { + if (this.current !== null && this.current.name === m) { + return; + } + + if (m === 'auto') { + this.current = this.auto; + } else if (m === 'pan') { + this.current = this.pan; + } else if (m === 'zoom') { + this.current = this.zoom; + } else { + this.current = this.auto; + } + + this.current.force_update_at = 0; + this.current.force_before_ms = null; + this.current.force_after_ms = null; + + this.tm.last_mode_switch = Date.now(); + }; + + // ---------------------------------------------------------------------------------------------------------------- + // global selection sync for slaves + + // can the chart participate to the global selection sync as a slave? + this.globalSelectionSyncIsEligible = function () { + return ( + this.enabled && + this.library !== null && + typeof this.library.setSelection === 'function' && + this.isVisible() && + this.chart_created + ); + }; + + this.setSelection = function (t) { + if (typeof this.library.setSelection === 'function') { + // this.selected = this.library.setSelection(this, t) === true; + this.selected = this.library.setSelection(this, t); + } else { + this.selected = true; + } + + if (this.selected && this.debug) { + this.log('selection set to ' + t.toString()); + } + + if (this.foreignElementSelection !== null) { + this.foreignElementSelection.innerText = NETDATA.dateTime.localeDateString(t) + ' ' + NETDATA.dateTime.localeTimeString(t); + } + + return this.selected; + }; + + this.clearSelection = function () { + if (this.selected) { + if (typeof this.library.clearSelection === 'function') { + this.selected = (this.library.clearSelection(this) !== true); + } else { + this.selected = false; + } + + if (this.selected === false && this.debug) { + this.log('selection cleared'); + } + + if (this.foreignElementSelection !== null) { + this.foreignElementSelection.innerText = ''; + } + + this.legendReset(); + } + + return this.selected; + }; + + // ---------------------------------------------------------------------------------------------------------------- + + // find if a timestamp (ms) is shown in the current chart + this.timeIsVisible = function (t) { + return (t >= this.data_after && t <= this.data_before); + }; + + this.calculateRowForTime = function (t) { + if (!this.timeIsVisible(t)) { + return -1; + } + return Math.floor((t - this.data_after) / this.data_update_every); + }; + + // ---------------------------------------------------------------------------------------------------------------- + + this.pauseChart = function () { + if (!this.paused) { + if (this.debug) { + this.log('pauseChart()'); + } + + this.paused = true; + } + }; + + this.unpauseChart = function () { + if (this.paused) { + if (this.debug) { + this.log('unpauseChart()'); + } + + this.paused = false; + } + }; + + this.resetChart = function (dontClearMaster, dontUpdate) { + if (this.debug) { + this.log('resetChart(' + dontClearMaster + ', ' + dontUpdate + ') called'); + } + + if (typeof dontClearMaster === 'undefined') { + dontClearMaster = false; + } + + if (typeof dontUpdate === 'undefined') { + dontUpdate = false; + } + + if (dontClearMaster !== true && NETDATA.globalPanAndZoom.isMaster(this)) { + if (this.debug) { + this.log('resetChart() diverting to clearMaster().'); + } + // this will call us back with master === true + NETDATA.globalPanAndZoom.clearMaster(); + return; + } + + this.clearSelection(); + + this.tm.pan_and_zoom_seq = 0; + + this.setMode('auto'); + this.current.force_update_at = 0; + this.current.force_before_ms = null; + this.current.force_after_ms = null; + this.tm.last_autorefreshed = 0; + this.paused = false; + this.selected = false; + this.enabled = true; + // this.debug = false; + + // do not update the chart here + // or the chart will flip-flop when it is the master + // of a selection sync and another chart becomes + // the new master + + if (dontUpdate !== true && this.isVisible()) { + this.updateChart(); + } + }; + + this.updateChartPanOrZoom = function (after, before, callback) { + let logme = 'updateChartPanOrZoom(' + after + ', ' + before + '): '; + let ret = true; + + NETDATA.globalPanAndZoom.delay(); + NETDATA.globalSelectionSync.delay(); + + if (this.debug) { + this.log(logme); + } + + if (before < after) { + if (this.debug) { + this.log(logme + 'flipped parameters, rejecting it.'); + } + return false; + } + + if (typeof this.fixed_min_duration === 'undefined') { + this.fixed_min_duration = Math.round((this.chartWidth() / 30) * this.chart.update_every * 1000); + } + + let min_duration = this.fixed_min_duration; + let current_duration = Math.round(this.view_before - this.view_after); + + // round the numbers + after = Math.round(after); + before = Math.round(before); + + // align them to update_every + // stretching them further away + after -= after % this.data_update_every; + before += this.data_update_every - (before % this.data_update_every); + + // the final wanted duration + let wanted_duration = before - after; + + // to allow panning, accept just a point below our minimum + if ((current_duration - this.data_update_every) < min_duration) { + min_duration = current_duration - this.data_update_every; + } + + // we do it, but we adjust to minimum size and return false + // when the wanted size is below the current and the minimum + // and we zoom + if (wanted_duration < current_duration && wanted_duration < min_duration) { + if (this.debug) { + this.log(logme + 'too small: min_duration: ' + (min_duration / 1000).toString() + ', wanted: ' + (wanted_duration / 1000).toString()); + } + + min_duration = this.fixed_min_duration; + + let dt = (min_duration - wanted_duration) / 2; + before += dt; + after -= dt; + wanted_duration = before - after; + ret = false; + } + + let tolerance = this.data_update_every * 2; + let movement = Math.abs(before - this.view_before); + + if (Math.abs(current_duration - wanted_duration) <= tolerance && movement <= tolerance && ret) { + if (this.debug) { + this.log(logme + 'REJECTING UPDATE: current/min duration: ' + (current_duration / 1000).toString() + '/' + (this.fixed_min_duration / 1000).toString() + ', wanted duration: ' + (wanted_duration / 1000).toString() + ', duration diff: ' + (Math.round(Math.abs(current_duration - wanted_duration) / 1000)).toString() + ', movement: ' + (movement / 1000).toString() + ', tolerance: ' + (tolerance / 1000).toString() + ', returning: ' + false); + } + return false; + } + + if (this.current.name === 'auto') { + this.log(logme + 'caller called me with mode: ' + this.current.name); + this.setMode('pan'); + } + + if (this.debug) { + this.log(logme + 'ACCEPTING UPDATE: current/min duration: ' + (current_duration / 1000).toString() + '/' + (this.fixed_min_duration / 1000).toString() + ', wanted duration: ' + (wanted_duration / 1000).toString() + ', duration diff: ' + (Math.round(Math.abs(current_duration - wanted_duration) / 1000)).toString() + ', movement: ' + (movement / 1000).toString() + ', tolerance: ' + (tolerance / 1000).toString() + ', returning: ' + ret); + } + + this.current.force_update_at = Date.now() + NETDATA.options.current.pan_and_zoom_delay; + this.current.force_after_ms = after; + this.current.force_before_ms = before; + NETDATA.globalPanAndZoom.setMaster(this, after, before); + + if (ret && typeof callback === 'function') { + callback(); + } + + return ret; + }; + + this.updateChartPanOrZoomAsyncTimeOutId = undefined; + this.updateChartPanOrZoomAsync = function (after, before, callback) { + NETDATA.globalPanAndZoom.delay(); + NETDATA.globalSelectionSync.delay(); + + if (!NETDATA.globalPanAndZoom.isMaster(this)) { + this.pauseChart(); + NETDATA.globalPanAndZoom.setMaster(this, after, before); + // NETDATA.globalSelectionSync.stop(); + NETDATA.globalSelectionSync.setMaster(this); + } + + if (this.updateChartPanOrZoomAsyncTimeOutId) { + NETDATA.timeout.clear(this.updateChartPanOrZoomAsyncTimeOutId); + } + + NETDATA.timeout.set(function () { + that.updateChartPanOrZoomAsyncTimeOutId = undefined; + that.updateChartPanOrZoom(after, before, callback); + }, 0); + }; + + let _unitsConversionLastUnits = undefined; + let _unitsConversionLastUnitsDesired = undefined; + let _unitsConversionLastMin = undefined; + let _unitsConversionLastMax = undefined; + let _unitsConversion = function (value) { + return value; + }; + this.unitsConversionSetup = function (min, max) { + if (this.units !== _unitsConversionLastUnits + || this.units_desired !== _unitsConversionLastUnitsDesired + || min !== _unitsConversionLastMin + || max !== _unitsConversionLastMax) { + + _unitsConversionLastUnits = this.units; + _unitsConversionLastUnitsDesired = this.units_desired; + _unitsConversionLastMin = min; + _unitsConversionLastMax = max; + + _unitsConversion = NETDATA.unitsConversion.get(this.uuid, min, max, this.units, this.units_desired, this.units_common, function (units) { + // console.log('switching units from ' + that.units.toString() + ' to ' + units.toString()); + that.units_current = units; + that.legendSetUnitsString(that.units_current); + }); + } + }; + + let _legendFormatValueChartDecimalsLastMin = undefined; + let _legendFormatValueChartDecimalsLastMax = undefined; + let _legendFormatValueChartDecimals = -1; + let _intlNumberFormat = null; + this.legendFormatValueDecimalsFromMinMax = function (min, max) { + if (min === _legendFormatValueChartDecimalsLastMin && max === _legendFormatValueChartDecimalsLastMax) { + return; + } + + this.unitsConversionSetup(min, max); + if (_unitsConversion !== null) { + min = _unitsConversion(min); + max = _unitsConversion(max); + + if (typeof min !== 'number' || typeof max !== 'number') { + return; + } + } + + _legendFormatValueChartDecimalsLastMin = min; + _legendFormatValueChartDecimalsLastMax = max; + + let old = _legendFormatValueChartDecimals; + + if (this.data !== null && this.data.min === this.data.max) + // it is a fixed number, let the visualizer decide based on the value + { + _legendFormatValueChartDecimals = -1; + } else if (this.value_decimal_detail !== -1) + // there is an override + { + _legendFormatValueChartDecimals = this.value_decimal_detail; + } else { + // ok, let's calculate the proper number of decimal points + let delta; + + if (min === max) { + delta = Math.abs(min); + } else { + delta = Math.abs(max - min); + } + + if (delta > 1000) { + _legendFormatValueChartDecimals = 0; + } else if (delta > 10) { + _legendFormatValueChartDecimals = 1; + } else if (delta > 1) { + _legendFormatValueChartDecimals = 2; + } else if (delta > 0.1) { + _legendFormatValueChartDecimals = 2; + } else if (delta > 0.01) { + _legendFormatValueChartDecimals = 4; + } else if (delta > 0.001) { + _legendFormatValueChartDecimals = 5; + } else if (delta > 0.0001) { + _legendFormatValueChartDecimals = 6; + } else { + _legendFormatValueChartDecimals = 7; + } + } + + if (_legendFormatValueChartDecimals !== old) { + if (_legendFormatValueChartDecimals < 0) { + _intlNumberFormat = null; + } else { + _intlNumberFormat = NETDATA.fastNumberFormat.get( + _legendFormatValueChartDecimals, + _legendFormatValueChartDecimals + ); + } + } + }; + + this.legendFormatValue = function (value) { + if (typeof value !== 'number') { + return '-'; + } + + value = _unitsConversion(value); + + if (typeof value !== 'number') { + return value; + } + + if (_intlNumberFormat !== null) { + return _intlNumberFormat.format(value); + } + + let dmin, dmax; + if (this.value_decimal_detail !== -1) { + dmin = dmax = this.value_decimal_detail; + } else { + dmin = 0; + let abs = (value < 0) ? -value : value; + if (abs > 1000) { + dmax = 0; + } else if (abs > 10) { + dmax = 1; + } else if (abs > 1) { + dmax = 2; + } else if (abs > 0.1) { + dmax = 2; + } else if (abs > 0.01) { + dmax = 4; + } else if (abs > 0.001) { + dmax = 5; + } else if (abs > 0.0001) { + dmax = 6; + } else { + dmax = 7; + } + } + + return NETDATA.fastNumberFormat.get(dmin, dmax).format(value); + }; + + this.legendSetLabelValue = function (label, value) { + let series = this.element_legend_childs.series[label]; + if (typeof series === 'undefined') { + return; + } + if (series.value === null && series.user === null) { + return; + } + + /* + // this slows down firefox and edge significantly + // since it requires to use innerHTML(), instead of innerText() + + // if the value has not changed, skip DOM update + //if (series.last === value) return; + + let s, r; + if (typeof value === 'number') { + let v = Math.abs(value); + s = r = this.legendFormatValue(value); + + if (typeof series.last === 'number') { + if (v > series.last) s += '<i class="fas fa-angle-up" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + else if (v < series.last) s += '<i class="fas fa-angle-down" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + else s += '<i class="fas fa-angle-left" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + } + else s += '<i class="fas fa-angle-right" style="width: 8px; text-align: center; overflow: hidden; vertical-align: middle;"></i>'; + + series.last = v; + } + else { + if (value === null) + s = r = ''; + else + s = r = value; + + series.last = value; + } + */ + + let s = this.legendFormatValue(value); + + // caching: do not update the update to show the same value again + if (s === series.last_shown_value) { + return; + } + series.last_shown_value = s; + + if (series.value !== null) { + series.value.innerText = s; + } + if (series.user !== null) { + series.user.innerText = s; + } + }; + + this.legendSetDateString = function (date) { + if (this.element_legend_childs.title_date !== null && date !== this.tmp.__last_shown_legend_date) { + this.element_legend_childs.title_date.innerText = date; + this.tmp.__last_shown_legend_date = date; + } + }; + + this.legendSetTimeString = function (time) { + if (this.element_legend_childs.title_time !== null && time !== this.tmp.__last_shown_legend_time) { + this.element_legend_childs.title_time.innerText = time; + this.tmp.__last_shown_legend_time = time; + } + }; + + this.legendSetUnitsString = function (units) { + if (this.element_legend_childs.title_units !== null && units !== this.tmp.__last_shown_legend_units) { + this.element_legend_childs.title_units.innerText = units; + this.tmp.__last_shown_legend_units = units; + } + }; + + this.legendSetDateLast = { + ms: 0, + date: undefined, + time: undefined + }; + + this.legendSetDate = function (ms) { + if (typeof ms !== 'number') { + this.legendShowUndefined(); + return; + } + + if (this.legendSetDateLast.ms !== ms) { + let d = new Date(ms); + this.legendSetDateLast.ms = ms; + this.legendSetDateLast.date = NETDATA.dateTime.localeDateString(d); + this.legendSetDateLast.time = NETDATA.dateTime.localeTimeString(d); + } + + this.legendSetDateString(this.legendSetDateLast.date); + this.legendSetTimeString(this.legendSetDateLast.time); + this.legendSetUnitsString(this.units_current) + }; + + this.legendShowUndefined = function () { + this.legendSetDateString(this.legendPluginModuleString(false)); + this.legendSetTimeString(this.chart.context.toString()); + // this.legendSetUnitsString(' '); + + if (this.data && this.element_legend_childs.series !== null) { + let labels = this.data.dimension_names; + let i = labels.length; + while (i--) { + let label = labels[i]; + + if (typeof label === 'undefined' || typeof this.element_legend_childs.series[label] === 'undefined') { + continue; + } + this.legendSetLabelValue(label, null); + } + } + }; + + this.legendShowLatestValues = function () { + if (this.chart === null) { + return; + } + if (this.selected) { + return; + } + + if (this.data === null || this.element_legend_childs.series === null) { + this.legendShowUndefined(); + return; + } + + let show_undefined = true; + if (Math.abs(this.netdata_last - this.view_before) <= this.data_update_every) { + show_undefined = false; + } + + if (show_undefined) { + this.legendShowUndefined(); + return; + } + + this.legendSetDate(this.view_before); + + let labels = this.data.dimension_names; + let i = labels.length; + while (i--) { + let label = labels[i]; + + if (typeof label === 'undefined') { + continue; + } + if (typeof this.element_legend_childs.series[label] === 'undefined') { + continue; + } + + this.legendSetLabelValue(label, this.data.view_latest_values[i]); + } + }; + + this.legendReset = function () { + this.legendShowLatestValues(); + }; + + // this should be called just ONCE per dimension per chart + this.__chartDimensionColor = function (label) { + let c = NETDATA.commonColors.get(this, label); + + // it is important to maintain a list of colors + // for this chart only, since the chart library + // uses this to assign colors to dimensions in the same + // order the dimension are given to it + this.colors.push(c); + + return c; + }; + + this.chartPrepareColorPalette = function () { + NETDATA.commonColors.refill(this); + }; + + // get the ordered list of chart colors + // this includes user defined colors + this.chartCustomColors = function () { + this.chartPrepareColorPalette(); + + let colors; + if (this.colors_custom.length) { + colors = this.colors_custom; + } else { + colors = this.colors; + } + + if (this.debug) { + this.log("chartCustomColors() returns:"); + this.log(colors); + } + + return colors; + }; + + // get the ordered list of chart ASSIGNED colors + // (this returns only the colors that have been + // assigned to dimensions, prepended with any + // custom colors defined) + this.chartColors = function () { + this.chartPrepareColorPalette(); + + if (this.debug) { + this.log("chartColors() returns:"); + this.log(this.colors); + } + + return this.colors; + }; + + this.legendPluginModuleString = function (withContext) { + let str = ' '; + let context = ''; + + if (typeof this.chart !== 'undefined') { + if (withContext && typeof this.chart.context === 'string') { + context = this.chart.context; + } + + if (typeof this.chart.plugin === 'string' && this.chart.plugin !== '') { + str = this.chart.plugin; + + if (str.endsWith(".plugin")) { + str = str.substring(0, str.length - 7); + } + + if (typeof this.chart.module === 'string' && this.chart.module !== '') { + str += ':' + this.chart.module; + } + + if (withContext && context !== '') { + str += ', ' + context; + } + } + else if (withContext && context !== '') { + str = context; + } + } + + return str; + }; + + this.legendResolutionTooltip = function () { + if (!this.chart) { + return ''; + } + + let collected = this.chart.update_every; + let viewed = (this.data) ? this.data.view_update_every : collected; + + if (collected === viewed) { + return "resolution " + NETDATA.seconds4human(collected); + } + + return "resolution " + NETDATA.seconds4human(viewed) + ", collected every " + NETDATA.seconds4human(collected); + }; + + this.legendUpdateDOM = function () { + let needed = false, dim, keys, len; + + // check that the legend DOM is up to date for the downloaded dimensions + if (typeof this.element_legend_childs.series !== 'object' || this.element_legend_childs.series === null) { + // this.log('the legend does not have any series - requesting legend update'); + needed = true; + } else if (this.data === null) { + // this.log('the chart does not have any data - requesting legend update'); + needed = true; + } else if (typeof this.element_legend_childs.series.labels_key === 'undefined') { + needed = true; + } else { + let labels = this.data.dimension_names.toString(); + if (labels !== this.element_legend_childs.series.labels_key) { + needed = true; + + if (this.debug) { + this.log('NEW LABELS: "' + labels + '" NOT EQUAL OLD LABELS: "' + this.element_legend_childs.series.labels_key + '"'); + } + } + } + + if (!needed) { + // make sure colors available + this.chartPrepareColorPalette(); + + // do we have to update the current values? + // we do this, only when the visible chart is current + if (Math.abs(this.netdata_last - this.view_before) <= this.data_update_every) { + if (this.debug) { + this.log('chart is in latest position... updating values on legend...'); + } + + //let labels = this.data.dimension_names; + //let i = labels.length; + //while (i--) + // this.legendSetLabelValue(labels[i], this.data.view_latest_values[i]); + } + return; + } + + if (this.colors === null) { + // this is the first time we update the chart + // let's assign colors to all dimensions + if (this.library.track_colors()) { + this.colors = []; + keys = Object.keys(this.chart.dimensions); + len = keys.length; + for (let i = 0; i < len; i++) { + NETDATA.commonColors.get(this, this.chart.dimensions[keys[i]].name); + } + } + } + + // we will re-generate the colors for the chart + // based on the dimensions this result has data for + this.colors = []; + + if (this.debug) { + this.log('updating Legend DOM'); + } + + // mark all dimensions as invalid + this.dimensions_visibility.invalidateAll(); + + const genLabel = function (state, parent, dim, name, count) { + let color = state.__chartDimensionColor(name); + + let user_element = null; + let user_id = NETDATA.dataAttribute(state.element, 'show-value-of-' + name.toLowerCase() + '-at', null); + if (user_id === null) { + user_id = NETDATA.dataAttribute(state.element, 'show-value-of-' + dim.toLowerCase() + '-at', null); + } + if (user_id !== null) { + user_element = document.getElementById(user_id) || null; + if (user_element === null) { + state.log('Cannot find element with id: ' + user_id); + } + } + + state.element_legend_childs.series[name] = { + name: document.createElement('span'), + value: document.createElement('span'), + user: user_element, + last: null, + last_shown_value: null + }; + + let label = state.element_legend_childs.series[name]; + + // create the dimension visibility tracking for this label + state.dimensions_visibility.dimensionAdd(name, label.name, label.value, color); + + let rgb = NETDATA.colorHex2Rgb(color); + label.name.innerHTML = '<table class="netdata-legend-name-table-' + + state.chart.chart_type + + '" style="background-color: ' + + 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + NETDATA.options.current['color_fill_opacity_' + state.chart.chart_type] + ') !important' + + '"><tr class="netdata-legend-name-tr"><td class="netdata-legend-name-td"></td></tr></table>'; + + let text = document.createTextNode(' ' + name); + label.name.appendChild(text); + + if (count > 0) { + parent.appendChild(document.createElement('br')); + } + + parent.appendChild(label.name); + parent.appendChild(label.value); + }; + + let content = document.createElement('div'); + + if (this.element_chart === null) { + this.element_chart = document.createElement('div'); + this.element_chart.id = this.library_name + '-' + this.uuid + '-chart'; + this.element.appendChild(this.element_chart); + + if (this.hasLegend()) { + this.element_chart.className = 'netdata-chart-with-legend-right netdata-' + this.library_name + '-chart-with-legend-right'; + } else { + this.element_chart.className = ' netdata-chart netdata-' + this.library_name + '-chart'; + } + } + + if (this.hasLegend()) { + if (this.element_legend === null) { + this.element_legend = document.createElement('div'); + this.element_legend.className = 'netdata-chart-legend netdata-' + this.library_name + '-legend'; + this.element.appendChild(this.element_legend); + } else { + this.element_legend.innerHTML = ''; + } + + this.element_legend_childs = { + content: content, + resize_handler: null, + toolbox: null, + toolbox_left: null, + toolbox_right: null, + toolbox_reset: null, + toolbox_zoomin: null, + toolbox_zoomout: null, + toolbox_volume: null, + title_date: document.createElement('span'), + title_time: document.createElement('span'), + title_units: document.createElement('span'), + perfect_scroller: document.createElement('div'), + series: {} + }; + + if (NETDATA.options.current.legend_toolbox && this.library.toolboxPanAndZoom !== null) { + this.element_legend_childs.toolbox = document.createElement('div'); + this.element_legend_childs.toolbox_left = document.createElement('div'); + this.element_legend_childs.toolbox_right = document.createElement('div'); + this.element_legend_childs.toolbox_reset = document.createElement('div'); + this.element_legend_childs.toolbox_zoomin = document.createElement('div'); + this.element_legend_childs.toolbox_zoomout = document.createElement('div'); + this.element_legend_childs.toolbox_volume = document.createElement('div'); + + const getPanAndZoomStep = function (event) { + if (event.ctrlKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_control; + } else if (event.shiftKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_shift; + } else if (event.altKey) { + return NETDATA.options.current.pan_and_zoom_factor * NETDATA.options.current.pan_and_zoom_factor_multiplier_alt; + } else { + return NETDATA.options.current.pan_and_zoom_factor; + } + }; + + this.element_legend_childs.toolbox.className += ' netdata-legend-toolbox'; + this.element.appendChild(this.element_legend_childs.toolbox); + + this.element_legend_childs.toolbox_left.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_left.innerHTML = NETDATA.icons.left; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_left); + this.element_legend_childs.toolbox_left.onclick = function (e) { + e.preventDefault(); + + let step = (that.view_before - that.view_after) * getPanAndZoomStep(e); + let before = that.view_before - step; + let after = that.view_after - step; + if (after >= that.netdata_first) { + that.library.toolboxPanAndZoom(that, after, before); + } + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_left).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Pan Left', + content: 'Pan the chart to the left. You can also <b>drag it</b> with your mouse or your finger (on touch devices).<br/><small>Help can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_reset.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_reset.innerHTML = NETDATA.icons.reset; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_reset); + this.element_legend_childs.toolbox_reset.onclick = function (e) { + e.preventDefault(); + NETDATA.resetAllCharts(that); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_reset).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Reset', + content: 'Reset all the charts to their default auto-refreshing state. You can also <b>double click</b> the chart contents with your mouse or your finger (on touch devices).<br/><small>Help can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_right.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_right.innerHTML = NETDATA.icons.right; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_right); + this.element_legend_childs.toolbox_right.onclick = function (e) { + e.preventDefault(); + let step = (that.view_before - that.view_after) * getPanAndZoomStep(e); + let before = that.view_before + step; + let after = that.view_after + step; + if (before <= that.netdata_last) { + that.library.toolboxPanAndZoom(that, after, before); + } + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_right).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Pan Right', + content: 'Pan the chart to the right. You can also <b>drag it</b> with your mouse or your finger (on touch devices).<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_zoomin.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_zoomin.innerHTML = NETDATA.icons.zoomIn; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_zoomin); + this.element_legend_childs.toolbox_zoomin.onclick = function (e) { + e.preventDefault(); + let dt = ((that.view_before - that.view_after) * (getPanAndZoomStep(e) * 0.8) / 2); + let before = that.view_before - dt; + let after = that.view_after + dt; + that.library.toolboxPanAndZoom(that, after, before); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_zoomin).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Zoom In', + content: 'Zoom in the chart. You can also press SHIFT and select an area of the chart, or press SHIFT or ALT and use the mouse wheel or 2-finger touchpad scroll to zoom in or out.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + this.element_legend_childs.toolbox_zoomout.className += ' netdata-legend-toolbox-button'; + this.element_legend_childs.toolbox_zoomout.innerHTML = NETDATA.icons.zoomOut; + this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_zoomout); + this.element_legend_childs.toolbox_zoomout.onclick = function (e) { + e.preventDefault(); + let dt = (((that.view_before - that.view_after) / (1.0 - (getPanAndZoomStep(e) * 0.8)) - (that.view_before - that.view_after)) / 2); + let before = that.view_before + dt; + let after = that.view_after - dt; + + that.library.toolboxPanAndZoom(that, after, before); + }; + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.toolbox_zoomout).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Zoom Out', + content: 'Zoom out the chart. You can also press SHIFT or ALT and use the mouse wheel, or 2-finger touchpad scroll to zoom in or out.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + //this.element_legend_childs.toolbox_volume.className += ' netdata-legend-toolbox-button'; + //this.element_legend_childs.toolbox_volume.innerHTML = '<i class="fas fa-sort-amount-down"></i>'; + //this.element_legend_childs.toolbox_volume.title = 'Visible Volume'; + //this.element_legend_childs.toolbox.appendChild(this.element_legend_childs.toolbox_volume); + //this.element_legend_childs.toolbox_volume.onclick = function(e) { + //e.preventDefault(); + //alert('clicked toolbox_volume on ' + that.id); + //} + } + + if (NETDATA.options.current.resize_charts) { + this.element_legend_childs.resize_handler = document.createElement('div'); + + this.element_legend_childs.resize_handler.className += " netdata-legend-resize-handler"; + this.element_legend_childs.resize_handler.innerHTML = NETDATA.icons.resize; + this.element.appendChild(this.element_legend_childs.resize_handler); + if (NETDATA.options.current.show_help) { + $(this.element_legend_childs.resize_handler).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + title: 'Chart Resize', + content: 'Drag this point with your mouse or your finger (on touch devices), to resize the chart vertically. You can also <b>double click it</b> or <b>double tap it</b> to reset between 2 states: the default and the one that fits all the values.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + + // mousedown event + this.element_legend_childs.resize_handler.onmousedown = + function (e) { + that.resizeHandler(e); + }; + + // touchstart event + this.element_legend_childs.resize_handler.addEventListener('touchstart', function (e) { + that.resizeHandler(e); + }, false); + } + + if (this.chart) { + this.element_legend_childs.title_date.title = this.legendPluginModuleString(true); + this.element_legend_childs.title_time.title = this.legendResolutionTooltip(); + } + + this.element_legend_childs.title_date.className += " netdata-legend-title-date"; + this.element_legend.appendChild(this.element_legend_childs.title_date); + this.tmp.__last_shown_legend_date = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.title_time.className += " netdata-legend-title-time"; + this.element_legend.appendChild(this.element_legend_childs.title_time); + this.tmp.__last_shown_legend_time = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.title_units.className += " netdata-legend-title-units"; + this.element_legend_childs.title_units.innerText = this.units_current; + this.element_legend.appendChild(this.element_legend_childs.title_units); + this.tmp.__last_shown_legend_units = undefined; + + this.element_legend.appendChild(document.createElement('br')); + + this.element_legend_childs.perfect_scroller.className = 'netdata-legend-series'; + this.element_legend.appendChild(this.element_legend_childs.perfect_scroller); + + content.className = 'netdata-legend-series-content'; + this.element_legend_childs.perfect_scroller.appendChild(content); + + this.element_legend_childs.content = content; + + if (NETDATA.options.current.show_help) { + $(content).popover({ + container: "body", + animation: false, + html: true, + trigger: 'hover', + placement: 'bottom', + title: 'Chart Legend', + delay: { + show: NETDATA.options.current.show_help_delay_show_ms, + hide: NETDATA.options.current.show_help_delay_hide_ms + }, + content: 'You can click or tap on the values or the labels to select dimensions. By pressing SHIFT or CONTROL, you can enable or disable multiple dimensions.<br/><small>Help, can be disabled from the settings.</small>' + }); + } + } else { + this.element_legend_childs = { + content: content, + resize_handler: null, + toolbox: null, + toolbox_left: null, + toolbox_right: null, + toolbox_reset: null, + toolbox_zoomin: null, + toolbox_zoomout: null, + toolbox_volume: null, + title_date: null, + title_time: null, + title_units: null, + perfect_scroller: null, + series: {} + }; + } + + if (this.data) { + this.element_legend_childs.series.labels_key = this.data.dimension_names.toString(); + if (this.debug) { + this.log('labels from data: "' + this.element_legend_childs.series.labels_key + '"'); + } + + for (let i = 0, len = this.data.dimension_names.length; i < len; i++) { + genLabel(this, content, this.data.dimension_ids[i], this.data.dimension_names[i], i); + } + } else { + let tmp = []; + keys = Object.keys(this.chart.dimensions); + for (let i = 0, len = keys.length; i < len; i++) { + dim = keys[i]; + tmp.push(this.chart.dimensions[dim].name); + genLabel(this, content, dim, this.chart.dimensions[dim].name, i); + } + this.element_legend_childs.series.labels_key = tmp.toString(); + if (this.debug) { + this.log('labels from chart: "' + this.element_legend_childs.series.labels_key + '"'); + } + } + + // create a hidden div to be used for hidding + // the original legend of the chart library + let el = document.createElement('div'); + if (this.element_legend !== null) { + this.element_legend.appendChild(el); + } + el.style.display = 'none'; + + this.element_legend_childs.hidden = document.createElement('div'); + el.appendChild(this.element_legend_childs.hidden); + + if (this.element_legend_childs.perfect_scroller !== null) { + Ps.initialize(this.element_legend_childs.perfect_scroller, { + wheelSpeed: 0.2, + wheelPropagation: true, + swipePropagation: true, + minScrollbarLength: null, + maxScrollbarLength: null, + useBothWheelAxes: false, + suppressScrollX: true, + suppressScrollY: false, + scrollXMarginOffset: 0, + scrollYMarginOffset: 0, + theme: 'default' + }); + Ps.update(this.element_legend_childs.perfect_scroller); + } + + this.legendShowLatestValues(); + }; + + this.hasLegend = function () { + if (typeof this.tmp.___hasLegendCache___ !== 'undefined') { + return this.tmp.___hasLegendCache___; + } + + let leg = false; + if (this.library && this.library.legend(this) === 'right-side') { + leg = true; + } + + this.tmp.___hasLegendCache___ = leg; + return leg; + }; + + this.legendWidth = function () { + return (this.hasLegend()) ? 140 : 0; + }; + + this.legendHeight = function () { + return $(this.element).height(); + }; + + this.chartWidth = function () { + return $(this.element).width() - this.legendWidth(); + }; + + this.chartHeight = function () { + return $(this.element).height(); + }; + + this.chartPixelsPerPoint = function () { + // force an options provided detail + let px = this.pixels_per_point; + + if (this.library && px < this.library.pixels_per_point(this)) { + px = this.library.pixels_per_point(this); + } + + if (px < NETDATA.options.current.pixels_per_point) { + px = NETDATA.options.current.pixels_per_point; + } + + return px; + }; + + this.needsRecreation = function () { + let ret = ( + this.chart_created && + this.library && + this.library.autoresize() === false && + this.tm.last_resized < NETDATA.options.last_page_resize + ); + + if (this.debug) { + this.log('needsRecreation(): ' + ret.toString() + ', chart_created = ' + this.chart_created.toString()); + } + + return ret; + }; + + this.chartDataUniqueID = function () { + return this.id + ',' + this.library_name + ',' + this.dimensions + ',' + this.chartURLOptions(); + }; + + this.chartURLOptions = function () { + let ret = ''; + + if (this.override_options !== null) { + ret = this.override_options.toString(); + } else { + ret = this.library.options(this); + } + + if (this.append_options !== null) { + ret += '%7C' + this.append_options.toString(); + } + + ret += '%7C' + 'jsonwrap'; + + if (NETDATA.options.current.eliminate_zero_dimensions) { + ret += '%7C' + 'nonzero'; + } + + return ret; + }; + + this.chartURL = function () { + let after, before, points_multiplier = 1; + if (NETDATA.globalPanAndZoom.isActive()) { + if (this.current.force_before_ms !== null && this.current.force_after_ms !== null) { + this.tm.pan_and_zoom_seq = 0; + + before = Math.round(this.current.force_before_ms / 1000); + after = Math.round(this.current.force_after_ms / 1000); + this.view_after = after * 1000; + this.view_before = before * 1000; + + if (NETDATA.options.current.pan_and_zoom_data_padding) { + this.requested_padding = Math.round((before - after) / 2); + after -= this.requested_padding; + before += this.requested_padding; + this.requested_padding *= 1000; + points_multiplier = 2; + } + + this.current.force_before_ms = null; + this.current.force_after_ms = null; + } else { + this.tm.pan_and_zoom_seq = NETDATA.globalPanAndZoom.seq; + + after = Math.round(NETDATA.globalPanAndZoom.force_after_ms / 1000); + before = Math.round(NETDATA.globalPanAndZoom.force_before_ms / 1000); + this.view_after = after * 1000; + this.view_before = before * 1000; + + this.requested_padding = null; + points_multiplier = 1; + } + } else { + this.tm.pan_and_zoom_seq = 0; + + before = this.before; + after = this.after; + this.view_after = after * 1000; + this.view_before = before * 1000; + + this.requested_padding = null; + points_multiplier = 1; + } + + this.requested_after = after * 1000; + this.requested_before = before * 1000; + + let data_points; + if (NETDATA.options.force_data_points !== 0) { + data_points = NETDATA.options.force_data_points; + this.data_points = data_points; + } else { + this.data_points = this.points || Math.round(this.chartWidth() / this.chartPixelsPerPoint()); + data_points = this.data_points * points_multiplier; + } + + // build the data URL + this.data_url = this.host + this.chart.data_url; + this.data_url += "&format=" + this.library.format(); + this.data_url += "&points=" + (data_points).toString(); + this.data_url += "&group=" + this.method; + this.data_url += ">ime=" + this.gtime; + this.data_url += "&options=" + this.chartURLOptions(); + + if (after) { + this.data_url += "&after=" + after.toString(); + } + + if (before) { + this.data_url += "&before=" + before.toString(); + } + + if (this.dimensions) { + this.data_url += "&dimensions=" + this.dimensions; + } + + if (NETDATA.options.debug.chart_data_url || this.debug) { + this.log('chartURL(): ' + this.data_url + ' WxH:' + this.chartWidth() + 'x' + this.chartHeight() + ' points: ' + data_points.toString() + ' library: ' + this.library_name); + } + }; + + this.redrawChart = function () { + if (this.data !== null) { + this.updateChartWithData(this.data); + } + }; + + this.updateChartWithData = function (data) { + if (this.debug) { + this.log('updateChartWithData() called.'); + } + + // this may force the chart to be re-created + resizeChart(); + + this.data = data; + + let started = Date.now(); + let view_update_every = data.view_update_every * 1000; + + if (this.data_update_every !== view_update_every) { + if (this.element_legend_childs.title_time) { + this.element_legend_childs.title_time.title = this.legendResolutionTooltip(); + } + } + + // if the result is JSON, find the latest update-every + this.data_update_every = view_update_every; + this.data_after = data.after * 1000; + this.data_before = data.before * 1000; + this.netdata_first = data.first_entry * 1000; + this.netdata_last = data.last_entry * 1000; + this.data_points = data.points; + + data.state = this; + + if (NETDATA.options.current.pan_and_zoom_data_padding && this.requested_padding !== null) { + if (this.view_after < this.data_after) { + // console.log('adjusting view_after from ' + this.view_after + ' to ' + this.data_after); + this.view_after = this.data_after; + } + + if (this.view_before > this.data_before) { + // console.log('adjusting view_before from ' + this.view_before + ' to ' + this.data_before); + this.view_before = this.data_before; + } + } else { + this.view_after = this.data_after; + this.view_before = this.data_before; + } + + if (this.debug) { + this.log('UPDATE No ' + this.updates_counter + ' COMPLETED'); + + if (this.current.force_after_ms) { + this.log('STATUS: forced : ' + (this.current.force_after_ms / 1000).toString() + ' - ' + (this.current.force_before_ms / 1000).toString()); + } else { + this.log('STATUS: forced : unset'); + } + + this.log('STATUS: requested : ' + (this.requested_after / 1000).toString() + ' - ' + (this.requested_before / 1000).toString()); + this.log('STATUS: downloaded: ' + (this.data_after / 1000).toString() + ' - ' + (this.data_before / 1000).toString()); + this.log('STATUS: rendered : ' + (this.view_after / 1000).toString() + ' - ' + (this.view_before / 1000).toString()); + this.log('STATUS: points : ' + (this.data_points).toString()); + } + + if (this.data_points === 0) { + noDataToShow(); + return; + } + + if (this.updates_since_last_creation >= this.library.max_updates_to_recreate()) { + if (this.debug) { + this.log('max updates of ' + this.updates_since_last_creation.toString() + ' reached. Forcing re-generation.'); + } + + init('force'); + return; + } + + // check and update the legend + this.legendUpdateDOM(); + + if (this.chart_created && typeof this.library.update === 'function') { + if (this.debug) { + this.log('updating chart...'); + } + + if (!callChartLibraryUpdateSafely(data)) { + return; + } + } else { + if (this.debug) { + this.log('creating chart...'); + } + + if (!callChartLibraryCreateSafely(data)) { + return; + } + } + + if (this.isVisible()) { + hideMessage(); + this.legendShowLatestValues(); + } else { + this.__redraw_on_unhide = true; + + if (this.debug) { + this.log("drawn while not visible"); + } + } + + if (this.selected) { + NETDATA.globalSelectionSync.stop(); + } + + // update the performance counters + let now = Date.now(); + this.tm.last_updated = now; + + // don't update last_autorefreshed if this chart is + // forced to be updated with global PanAndZoom + if (NETDATA.globalPanAndZoom.isActive()) { + this.tm.last_autorefreshed = 0; + } else { + if (NETDATA.options.current.parallel_refresher && NETDATA.options.current.concurrent_refreshes && typeof this.force_update_every !== 'number') { + this.tm.last_autorefreshed = now - (now % this.data_update_every); + } else { + this.tm.last_autorefreshed = now; + } + } + + this.refresh_dt_ms = now - started; + NETDATA.options.auto_refresher_fast_weight += this.refresh_dt_ms; + + if (this.refresh_dt_element !== null) { + this.refresh_dt_element.innerText = this.refresh_dt_ms.toString(); + } + + if (this.foreignElementBefore !== null) { + this.foreignElementBefore.innerText = NETDATA.dateTime.localeDateString(this.view_before) + ' ' + NETDATA.dateTime.localeTimeString(this.view_before); + } + + if (this.foreignElementAfter !== null) { + this.foreignElementAfter.innerText = NETDATA.dateTime.localeDateString(this.view_after) + ' ' + NETDATA.dateTime.localeTimeString(this.view_after); + } + + if (this.foreignElementDuration !== null) { + this.foreignElementDuration.innerText = NETDATA.seconds4human(Math.floor((this.view_before - this.view_after) / 1000) + 1); + } + + if (this.foreignElementUpdateEvery !== null) { + this.foreignElementUpdateEvery.innerText = NETDATA.seconds4human(Math.floor(this.data_update_every / 1000)); + } + }; + + this.getSnapshotData = function (key) { + if (this.debug) { + this.log('updating from snapshot: ' + key); + } + + if (typeof netdataSnapshotData.data[key] === 'undefined') { + this.log('snapshot does not include data for key "' + key + '"'); + return null; + } + + if (typeof netdataSnapshotData.data[key] !== 'string') { + this.log('snapshot data for key "' + key + '" is not string'); + return null; + } + + let uncompressed; + try { + uncompressed = netdataSnapshotData.uncompress(netdataSnapshotData.data[key]); + + if (uncompressed === null) { + this.log('uncompressed snapshot data for key ' + key + ' is null'); + return null; + } + + if (typeof uncompressed === 'undefined') { + this.log('uncompressed snapshot data for key ' + key + ' is undefined'); + return null; + } + } catch (e) { + this.log('decompression of snapshot data for key ' + key + ' failed'); + console.log(e); + uncompressed = null; + } + + if (typeof uncompressed !== 'string') { + this.log('uncompressed snapshot data for key ' + key + ' is not string'); + return null; + } + + let data; + try { + data = JSON.parse(uncompressed); + } catch (e) { + this.log('parsing snapshot data for key ' + key + ' failed'); + console.log(e); + data = null; + } + + return data; + }; + + this.updateChart = function (callback) { + if (this.debug) { + this.log('updateChart()'); + } + + if (this.fetching_data) { + if (this.debug) { + this.log('updateChart(): I am already updating...'); + } + + if (typeof callback === 'function') { + return callback(false, 'already running'); + } + + return; + } + + // due to late initialization of charts and libraries + // we need to check this too + if (!this.enabled) { + if (this.debug) { + this.log('updateChart(): I am not enabled'); + } + + if (typeof callback === 'function') { + return callback(false, 'not enabled'); + } + + return; + } + + if (!canBeRendered()) { + if (this.debug) { + this.log('updateChart(): cannot be rendered'); + } + + if (typeof callback === 'function') { + return callback(false, 'cannot be rendered'); + } + + return; + } + + if (that.dom_created !== true) { + if (this.debug) { + this.log('updateChart(): creating DOM'); + } + + createDOM(); + } + + if (this.chart === null) { + if (this.debug) { + this.log('updateChart(): getting chart'); + } + + return this.getChart(function () { + return that.updateChart(callback); + }); + } + + if (!this.library.initialized) { + if (this.library.enabled) { + if (this.debug) { + this.log('updateChart(): initializing chart library'); + } + + return this.library.initialize(function () { + return that.updateChart(callback); + }); + } else { + error('chart library "' + this.library_name + '" is not available.'); + + if (typeof callback === 'function') { + return callback(false, 'library not available'); + } + + return; + } + } + + this.clearSelection(); + this.chartURL(); + + NETDATA.statistics.refreshes_total++; + NETDATA.statistics.refreshes_active++; + + if (NETDATA.statistics.refreshes_active > NETDATA.statistics.refreshes_active_max) { + NETDATA.statistics.refreshes_active_max = NETDATA.statistics.refreshes_active; + } + + let ok = false; + this.fetching_data = true; + + if (netdataSnapshotData !== null) { + let key = this.chartDataUniqueID(); + let data = this.getSnapshotData(key); + if (data !== null) { + ok = true; + data = NETDATA.xss.checkData('/api/v1/data', data, this.library.xssRegexIgnore); + this.updateChartWithData(data); + } else { + ok = false; + error('cannot get data from snapshot for key: "' + key + '"'); + that.tm.last_autorefreshed = Date.now(); + } + + NETDATA.statistics.refreshes_active--; + this.fetching_data = false; + + if (typeof callback === 'function') { + callback(ok, 'snapshot'); + } + + return; + } + + if (this.debug) { + this.log('updating from ' + this.data_url); + } + + this.xhr = $.ajax({ + url: this.data_url, + cache: false, + async: true, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkData('/api/v1/data', data, that.library.xssRegexIgnore); + + that.xhr = undefined; + that.retries_on_data_failures = 0; + ok = true; + + if (that.debug) { + that.log('data received. updating chart.'); + } + + that.updateChartWithData(data); + }) + .fail(function (msg) { + that.xhr = undefined; + + if (msg.statusText !== 'abort') { + that.retries_on_data_failures++; + if (that.retries_on_data_failures > NETDATA.options.current.retries_on_data_failures) { + // that.log('failed ' + that.retries_on_data_failures.toString() + ' times - giving up'); + that.retries_on_data_failures = 0; + error('data download failed for url: ' + that.data_url); + } + else { + that.tm.last_autorefreshed = Date.now(); + // that.log('failed ' + that.retries_on_data_failures.toString() + ' times, but I will retry'); + } + } + }) + .always(function () { + that.xhr = undefined; + + NETDATA.statistics.refreshes_active--; + that.fetching_data = false; + + if (typeof callback === 'function') { + return callback(ok, 'download'); + } + }); + }; + + const __isVisible = function () { + let ret = true; + + if (NETDATA.options.current.update_only_visible !== false) { + // tolerance is the number of pixels a chart can be off-screen + // to consider it as visible and refresh it as if was visible + let tolerance = 0; + + that.tm.last_visible_check = Date.now(); + + let rect = that.element.getBoundingClientRect(); + + let screenTop = window.scrollY; + let screenBottom = screenTop + window.innerHeight; + + let chartTop = rect.top + screenTop; + let chartBottom = chartTop + rect.height; + + ret = !(rect.width === 0 || rect.height === 0 || chartBottom + tolerance < screenTop || chartTop - tolerance > screenBottom); + } + + if (that.debug) { + that.log('__isVisible(): ' + ret); + } + + return ret; + }; + + this.isVisible = function (nocache) { + // this.log('last_visible_check: ' + this.tm.last_visible_check + ', last_page_scroll: ' + NETDATA.options.last_page_scroll); + + // caching - we do not evaluate the charts visibility + // if the page has not been scrolled since the last check + if ((typeof nocache !== 'undefined' && nocache) + || typeof this.tmp.___isVisible___ === 'undefined' + || this.tm.last_visible_check <= NETDATA.options.last_page_scroll) { + this.tmp.___isVisible___ = __isVisible(); + if (this.tmp.___isVisible___) { + this.unhideChart(); + } else { + this.hideChart(); + } + } + + if (this.debug) { + this.log('isVisible(' + nocache + '): ' + this.tmp.___isVisible___); + } + + return this.tmp.___isVisible___; + }; + + this.isAutoRefreshable = function () { + return (this.current.autorefresh); + }; + + this.canBeAutoRefreshed = function () { + if (!this.enabled) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> not enabled'); + } + + return false; + } + + if (this.running) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> already running'); + } + + return false; + } + + if (this.library === null || this.library.enabled === false) { + error('charting library "' + this.library_name + '" is not available'); + if (this.debug) { + this.log('canBeAutoRefreshed() -> chart library ' + this.library_name + ' is not available'); + } + + return false; + } + + if (!this.isVisible()) { + if (NETDATA.options.debug.visibility || this.debug) { + this.log('canBeAutoRefreshed() -> not visible'); + } + + return false; + } + + let now = Date.now(); + + if (this.current.force_update_at !== 0 && this.current.force_update_at < now) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> timed force update - allowing this update'); + } + + this.current.force_update_at = 0; + return true; + } + + if (!this.isAutoRefreshable()) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> not auto-refreshable'); + } + + return false; + } + + // allow the first update, even if the page is not visible + if (NETDATA.options.page_is_visible === false && this.updates_counter && this.updates_since_last_unhide) { + if (NETDATA.options.debug.focus || this.debug) { + this.log('canBeAutoRefreshed() -> not the first update, and page does not have focus'); + } + + return false; + } + + if (this.needsRecreation()) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> needs re-creation.'); + } + + return true; + } + + if (NETDATA.options.auto_refresher_stop_until >= now) { + if (this.debug) { + this.log('canBeAutoRefreshed() -> stopped until is in future.'); + } + + return false; + } + + // options valid only for autoRefresh() + if (NETDATA.globalPanAndZoom.isActive()) { + if (NETDATA.globalPanAndZoom.shouldBeAutoRefreshed(this)) { + if (this.debug) { + this.log('canBeAutoRefreshed(): global panning: I need an update.'); + } + + return true; + } + else { + if (this.debug) { + this.log('canBeAutoRefreshed(): global panning: I am already up to date.'); + } + + return false; + } + } + + if (this.selected) { + if (this.debug) { + this.log('canBeAutoRefreshed(): I have a selection in place.'); + } + + return false; + } + + if (this.paused) { + if (this.debug) { + this.log('canBeAutoRefreshed(): I am paused.'); + } + + return false; + } + + let data_update_every = this.data_update_every; + if (typeof this.force_update_every === 'number') { + data_update_every = this.force_update_every; + } + + if (now - this.tm.last_autorefreshed >= data_update_every) { + if (this.debug) { + this.log('canBeAutoRefreshed(): It is time to update me. Now: ' + now.toString() + ', last_autorefreshed: ' + this.tm.last_autorefreshed + ', data_update_every: ' + data_update_every + ', delta: ' + (now - this.tm.last_autorefreshed).toString()); + } + + return true; + } + + return false; + }; + + this.autoRefresh = function (callback) { + let state = that; + + if (state.canBeAutoRefreshed() && state.running === false) { + state.running = true; + state.updateChart(function () { + state.running = false; + + if (typeof callback === 'function') { + return callback(); + } + }); + } else { + if (typeof callback === 'function') { + return callback(); + } + } + }; + + this.__defaultsFromDownloadedChart = function (chart) { + this.chart = chart; + this.chart_url = chart.url; + this.data_update_every = chart.update_every * 1000; + this.data_points = Math.round(this.chartWidth() / this.chartPixelsPerPoint()); + this.tm.last_info_downloaded = Date.now(); + + if (this.title === null) { + this.title = chart.title; + } + + if (this.units === null) { + this.units = chart.units; + this.units_current = this.units; + } + }; + + // fetch the chart description from the netdata server + this.getChart = function (callback) { + this.chart = NETDATA.chartRegistry.get(this.host, this.id); + if (this.chart) { + this.__defaultsFromDownloadedChart(this.chart); + + if (typeof callback === 'function') { + return callback(); + } + } else if (netdataSnapshotData !== null) { + // console.log(this); + // console.log(NETDATA.chartRegistry); + NETDATA.error(404, 'host: ' + this.host + ', chart: ' + this.id); + error('chart not found in snapshot'); + + if (typeof callback === 'function') { + return callback(); + } + } else { + this.chart_url = "/api/v1/chart?chart=" + this.id; + + if (this.debug) { + this.log('downloading ' + this.chart_url); + } + + $.ajax({ + url: this.host + this.chart_url, + cache: false, + async: true, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (chart) { + chart = NETDATA.xss.checkOptional('/api/v1/chart', chart); + + chart.url = that.chart_url; + that.__defaultsFromDownloadedChart(chart); + NETDATA.chartRegistry.add(that.host, that.id, chart); + }) + .fail(function () { + NETDATA.error(404, that.chart_url); + error('chart not found on url "' + that.chart_url + '"'); + }) + .always(function () { + if (typeof callback === 'function') { + return callback(); + } + }); + } + }; + + // ============================================================================================================ + // INITIALIZATION + + initDOM(); + init('fast'); +}; + +NETDATA.resetAllCharts = function (state) { + // first clear the global selection sync + // to make sure no chart is in selected state + NETDATA.globalSelectionSync.stop(); + + // there are 2 possibilities here + // a. state is the global Pan and Zoom master + // b. state is not the global Pan and Zoom master + + // let master = true; + // if (NETDATA.globalPanAndZoom.isMaster(state) === false) { + // master = false; + // } + const master = NETDATA.globalPanAndZoom.isMaster(state) + + // clear the global Pan and Zoom + // this will also refresh the master + // and unblock any charts currently mirroring the master + NETDATA.globalPanAndZoom.clearMaster(); + + // if we were not the master, reset our status too + // this is required because most probably the mouse + // is over this chart, blocking it from auto-refreshing + if (master === false && (state.paused || state.selected)) { + state.resetChart(); + } +}; + +// get or create a chart state, given a DOM element +NETDATA.chartState = function (element) { + let self = $(element); + + let state = self.data('netdata-state-object') || null; + if (state === null) { + state = new chartState(element); + self.data('netdata-state-object', state); + } + return state; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// Library functions + +// Load a script without jquery +// This is used to load jquery - after it is loaded, we use jquery +NETDATA._loadjQuery = function (callback) { + if (typeof jQuery === 'undefined') { + if (NETDATA.options.debug.main_loop) { + console.log('loading ' + NETDATA.jQuery); + } + + let script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = true; + script.src = NETDATA.jQuery; + + // script.onabort = onError; + script.onerror = function () { + NETDATA.error(101, NETDATA.jQuery); + }; + if (typeof callback === "function") { + script.onload = function () { + $ = jQuery; + return callback(); + }; + } + + let s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(script, s); + } + else if (typeof callback === "function") { + $ = jQuery; + return callback(); + } +}; + +NETDATA._loadCSS = function (filename) { + // don't use jQuery here + // styles are loaded before jQuery + // to eliminate showing an unstyled page to the user + + let fileref = document.createElement("link"); + fileref.setAttribute("rel", "stylesheet"); + fileref.setAttribute("type", "text/css"); + fileref.setAttribute("href", filename); + + if (typeof fileref !== 'undefined') { + document.getElementsByTagName("head")[0].appendChild(fileref); + } +}; + +// user function to signal us the DOM has been +// updated. +NETDATA.updatedDom = function () { + NETDATA.options.updated_dom = true; +}; + +NETDATA.ready = function (callback) { + NETDATA.options.pauseCallback = callback; +}; + +NETDATA.pause = function (callback) { + if (typeof callback === 'function') { + if (NETDATA.options.pause) { + return callback(); + } else { + NETDATA.options.pauseCallback = callback; + } + } +}; + +NETDATA.unpause = function () { + NETDATA.options.pauseCallback = null; + NETDATA.options.updated_dom = true; + NETDATA.options.pause = false; +}; + +// ---------------------------------------------------------------------------------------------------------------- + +// this is purely sequential charts refresher +// it is meant to be autonomous +NETDATA.chartRefresherNoParallel = function (index, callback) { + let targets = NETDATA.intersectionObserver.targets(); + + if (NETDATA.options.debug.main_loop) { + console.log('NETDATA.chartRefresherNoParallel(' + index + ')'); + } + + if (NETDATA.options.updated_dom) { + // the dom has been updated + // get the dom parts again + NETDATA.parseDom(callback); + return; + } + if (index >= targets.length) { + if (NETDATA.options.debug.main_loop) { + console.log('waiting to restart main loop...'); + } + + NETDATA.options.auto_refresher_fast_weight = 0; + callback(); + } else { + let state = targets[index]; + + if (NETDATA.options.auto_refresher_fast_weight < NETDATA.options.current.fast_render_timeframe) { + if (NETDATA.options.debug.main_loop) { + console.log('fast rendering...'); + } + + if (state.isVisible()) { + NETDATA.timeout.set(function () { + state.autoRefresh(function () { + NETDATA.chartRefresherNoParallel(++index, callback); + }); + }, 0); + } else { + NETDATA.chartRefresherNoParallel(++index, callback); + } + } else { + if (NETDATA.options.debug.main_loop) { + console.log('waiting for next refresh...'); + } + NETDATA.options.auto_refresher_fast_weight = 0; + + NETDATA.timeout.set(function () { + state.autoRefresh(function () { + NETDATA.chartRefresherNoParallel(++index, callback); + }); + }, NETDATA.options.current.idle_between_charts); + } + } +}; + +NETDATA.chartRefresherWaitTime = function () { + return NETDATA.options.current.idle_parallel_loops; +}; + +// the default refresher +NETDATA.chartRefresherLastRun = 0; +NETDATA.chartRefresherRunsAfterParseDom = 0; +NETDATA.chartRefresherTimeoutId = undefined; + +NETDATA.chartRefresherReschedule = function () { + if (NETDATA.options.current.async_on_scroll) { + if (NETDATA.chartRefresherTimeoutId) { + NETDATA.timeout.clear(NETDATA.chartRefresherTimeoutId); + } + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set(NETDATA.chartRefresher, NETDATA.options.current.onscroll_worker_duration_threshold); + //console.log('chartRefresherReschedule()'); + } +}; + +NETDATA.chartRefresher = function () { + // console.log('chartRefresher() begin ' + (Date.now() - NETDATA.chartRefresherLastRun).toString() + ' ms since last run'); + + if (NETDATA.options.page_is_visible === false + && NETDATA.options.current.stop_updates_when_focus_is_lost + && NETDATA.chartRefresherLastRun > NETDATA.options.last_page_resize + && NETDATA.chartRefresherLastRun > NETDATA.options.last_page_scroll + && NETDATA.chartRefresherRunsAfterParseDom > 10 + ) { + setTimeout( + NETDATA.chartRefresher, + NETDATA.options.current.idle_lost_focus + ); + + // console.log('chartRefresher() page without focus, will run in ' + NETDATA.options.current.idle_lost_focus.toString() + ' ms, ' + NETDATA.chartRefresherRunsAfterParseDom.toString()); + return; + } + NETDATA.chartRefresherRunsAfterParseDom++; + + let now = Date.now(); + NETDATA.chartRefresherLastRun = now; + + if (now < NETDATA.options.on_scroll_refresher_stop_until) { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end1 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (now < NETDATA.options.auto_refresher_stop_until) { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end2 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (NETDATA.options.pause) { + // console.log('auto-refresher is paused'); + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + // console.log('chartRefresher() end3 will run in ' + NETDATA.chartRefresherWaitTime().toString() + ' ms'); + return; + } + + if (typeof NETDATA.options.pauseCallback === 'function') { + // console.log('auto-refresher is calling pauseCallback'); + + NETDATA.options.pause = true; + NETDATA.options.pauseCallback(); + NETDATA.chartRefresher(); + + // console.log('chartRefresher() end4 (nested)'); + return; + } + + if (!NETDATA.options.current.parallel_refresher) { + // console.log('auto-refresher is calling chartRefresherNoParallel(0)'); + NETDATA.chartRefresherNoParallel(0, function () { + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.options.current.idle_between_loops + ); + }); + // console.log('chartRefresher() end5 (no parallel, nested)'); + return; + } + + if (NETDATA.options.updated_dom) { + // the dom has been updated + // get the dom parts again + // console.log('auto-refresher is calling parseDom()'); + NETDATA.parseDom(NETDATA.chartRefresher); + // console.log('chartRefresher() end6 (parseDom)'); + return; + } + + if (!NETDATA.globalSelectionSync.active()) { + let parallel = []; + let targets = NETDATA.intersectionObserver.targets(); + let len = targets.length; + let state; + while (len--) { + state = targets[len]; + if (state.running || state.isVisible() === false) { + continue; + } + + if (!state.library.initialized) { + if (state.library.enabled) { + state.library.initialize(NETDATA.chartRefresher); + //console.log('chartRefresher() end6 (library init)'); + return; + } + else { + state.error('chart library "' + state.library_name + '" is not enabled.'); + } + } + + if (NETDATA.scrollUp) { + parallel.unshift(state); + } else { + parallel.push(state); + } + } + + len = parallel.length; + while (len--) { + state = parallel[len]; + // console.log('auto-refresher executing in parallel for ' + parallel.length.toString() + ' charts'); + // this will execute the jobs in parallel + + if (!state.running) { + NETDATA.timeout.set(state.autoRefresh, 0); + } + } + //else { + // console.log('auto-refresher nothing to do'); + //} + } + + // run the next refresh iteration + NETDATA.chartRefresherTimeoutId = NETDATA.timeout.set( + NETDATA.chartRefresher, + NETDATA.chartRefresherWaitTime() + ); + + //console.log('chartRefresher() completed in ' + (Date.now() - now).toString() + ' ms'); +}; + +NETDATA.parseDom = function (callback) { + //console.log('parseDom()'); + + NETDATA.options.last_page_scroll = Date.now(); + NETDATA.options.updated_dom = false; + NETDATA.chartRefresherRunsAfterParseDom = 0; + + let targets = $('div[data-netdata]'); //.filter(':visible'); + + if (NETDATA.options.debug.main_loop) { + console.log('DOM updated - there are ' + targets.length + ' charts on page.'); + } + + NETDATA.intersectionObserver.globalReset(); + NETDATA.options.targets = []; + let len = targets.length; + while (len--) { + // the initialization will take care of sizing + // and the "loading..." message + let state = NETDATA.chartState(targets[len]); + NETDATA.options.targets.push(state); + NETDATA.intersectionObserver.observe(state); + } + + if (NETDATA.globalChartUnderlay.isActive()) { + NETDATA.globalChartUnderlay.setup(); + } else { + NETDATA.globalChartUnderlay.clear(); + } + + if (typeof callback === 'function') { + return callback(); + } +}; + +// this is the main function - where everything starts +NETDATA.started = false; +NETDATA.start = function () { + // this should be called only once + + if (NETDATA.started) { + console.log('netdata is already started'); + return; + } + + NETDATA.started = true; + NETDATA.options.page_is_visible = true; + + $(window).blur(function () { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = false; + if (NETDATA.options.debug.focus) { + console.log('Lost Focus!'); + } + } + }); + + $(window).focus(function () { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = true; + if (NETDATA.options.debug.focus) { + console.log('Focus restored!'); + } + } + }); + + if (typeof document.hasFocus === 'function' && !document.hasFocus()) { + if (NETDATA.options.current.stop_updates_when_focus_is_lost) { + NETDATA.options.page_is_visible = false; + if (NETDATA.options.debug.focus) { + console.log('Document has no focus!'); + } + } + } + + // bootstrap tab switching + $('a[data-toggle="tab"]').on('shown.bs.tab', NETDATA.onscroll); + + // bootstrap modal switching + let $modal = $('.modal'); + $modal.on('hidden.bs.modal', NETDATA.onscroll); + $modal.on('shown.bs.modal', NETDATA.onscroll); + + // bootstrap collapse switching + let $collapse = $('.collapse'); + $collapse.on('hidden.bs.collapse', NETDATA.onscroll); + $collapse.on('shown.bs.collapse', NETDATA.onscroll); + + NETDATA.parseDom(NETDATA.chartRefresher); + + // Alarms initialization + setTimeout(NETDATA.alarms.init, 1000); + + // Registry initialization + setTimeout(NETDATA.registry.init, netdataRegistryAfterMs); + + if (typeof netdataCallback === 'function') { + netdataCallback(); + } +}; + +NETDATA.globalReset = function () { + NETDATA.intersectionObserver.globalReset(); + NETDATA.globalSelectionSync.globalReset(); + NETDATA.globalPanAndZoom.globalReset(); + NETDATA.chartRegistry.globalReset(); + NETDATA.commonMin.globalReset(); + NETDATA.commonMax.globalReset(); + NETDATA.commonColors.globalReset(); + NETDATA.unitsConversion.globalReset(); + NETDATA.options.targets = []; + NETDATA.parseDom(); + NETDATA.unpause(); +}; diff --git a/web/gui/src/dashboard.js/options.js b/web/gui/src/dashboard.js/options.js new file mode 100644 index 0000000..68132e7 --- /dev/null +++ b/web/gui/src/dashboard.js/options.js @@ -0,0 +1,225 @@ + +NETDATA.icons = { + left: '<i class="fas fa-backward"></i>', + reset: '<i class="fas fa-play"></i>', + right: '<i class="fas fa-forward"></i>', + zoomIn: '<i class="fas fa-plus"></i>', + zoomOut: '<i class="fas fa-minus"></i>', + resize: '<i class="fas fa-sort"></i>', + lineChart: '<i class="fas fa-chart-line"></i>', + areaChart: '<i class="fas fa-chart-area"></i>', + noChart: '<i class="fas fa-chart-area"></i>', + loading: '<i class="fas fa-sync-alt"></i>', + noData: '<i class="fas fa-exclamation-triangle"></i>' +}; + +if (typeof netdataIcons === 'object') { + // for (let icon in NETDATA.icons) { + // if (NETDATA.icons.hasOwnProperty(icon) && typeof(netdataIcons[icon]) === 'string') + // NETDATA.icons[icon] = netdataIcons[icon]; + // } + for (var icon of Object.keys(NETDATA.icons)) { + if (typeof(netdataIcons[icon]) === 'string') { + NETDATA.icons[icon] = netdataIcons[icon] + } + } +} + +if (typeof netdataSnapshotData === 'undefined') { + netdataSnapshotData = null; +} + +if (typeof netdataShowHelp === 'undefined') { + netdataShowHelp = true; +} + +if (typeof netdataShowAlarms === 'undefined') { + netdataShowAlarms = false; +} + +if (typeof netdataRegistryAfterMs !== 'number' || netdataRegistryAfterMs < 0) { + netdataRegistryAfterMs = 0; // 1500; +} + +if (typeof netdataRegistry === 'undefined') { + // backward compatibility + netdataRegistry = (typeof netdataNoRegistry !== 'undefined' && netdataNoRegistry === false); +} + +if (netdataRegistry === false && typeof netdataRegistryCallback === 'function') { + netdataRegistry = true; +} + +// ---------------------------------------------------------------------------------------------------------------- +// the defaults for all charts + +// if the user does not specify any of these, the following will be used + +NETDATA.chartDefaults = { + width: '100%', // the chart width - can be null + height: '100%', // the chart height - can be null + min_width: null, // the chart minimum width - can be null + library: 'dygraph', // the graphing library to use + method: 'average', // the grouping method + before: 0, // panning + after: -600, // panning + pixels_per_point: 1, // the detail of the chart + fill_luminance: 0.8 // luminance of colors in solid areas +}; + +// ---------------------------------------------------------------------------------------------------------------- +// global options + +NETDATA.options = { + pauseCallback: null, // a callback when we are really paused + + pause: false, // when enabled we don't auto-refresh the charts + + targets: [], // an array of all the state objects that are + // currently active (independently of their + // viewport visibility) + + updated_dom: true, // when true, the DOM has been updated with + // new elements we have to check. + + auto_refresher_fast_weight: 0, // this is the current time in ms, spent + // rendering charts continuously. + // used with .current.fast_render_timeframe + + page_is_visible: true, // when true, this page is visible + + auto_refresher_stop_until: 0, // timestamp in ms - used internally, to stop the + // auto-refresher for some time (when a chart is + // performing pan or zoom, we need to stop refreshing + // all other charts, to have the maximum speed for + // rendering the chart that is panned or zoomed). + // Used with .current.global_pan_sync_time + + on_scroll_refresher_stop_until: 0, // timestamp in ms - used to stop evaluating + // charts for some time, after a page scroll + + last_page_resize: Date.now(), // the timestamp of the last resize request + + last_page_scroll: 0, // the timestamp the last time the page was scrolled + + browser_timezone: 'unknown', // timezone detected by javascript + server_timezone: 'unknown', // timezone reported by the server + + force_data_points: 0, // force the number of points to be returned for charts + fake_chart_rendering: false, // when set to true, the dashboard will download data but will not render the charts + + passive_events: null, // true if the browser supports passive events + + // the current profile + // we may have many... + current: { + units: 'auto', // can be 'auto' or 'original' + temperature: 'celsius', // can be 'celsius' or 'fahrenheit' + seconds_as_time: true, // show seconds as DDd:HH:MM:SS ? + timezone: 'default', // the timezone to use, or 'default' + user_set_server_timezone: 'default', // as set by the user on the dashboard + + legend_toolbox: true, // show the legend toolbox on charts + resize_charts: true, // show the resize handler on charts + + pixels_per_point: isSlowDevice() ? 5 : 1, // the minimum pixels per point for all charts + // increase this to speed javascript up + // each chart library has its own limit too + // the max of this and the chart library is used + // the final is calculated every time, so a change + // here will have immediate effect on the next chart + // update + + idle_between_charts: 100, // ms - how much time to wait between chart updates + + fast_render_timeframe: 200, // ms - render continuously until this time of continuous + // rendering has been reached + // this setting is used to make it render e.g. 10 + // charts at once, sleep idle_between_charts time + // and continue for another 10 charts. + + idle_between_loops: 500, // ms - if all charts have been updated, wait this + // time before starting again. + + idle_parallel_loops: 100, // ms - the time between parallel refresher updates + + idle_lost_focus: 500, // ms - when the window does not have focus, check + // if focus has been regained, every this time + + global_pan_sync_time: 300, // ms - when you pan or zoom a chart, the background + // auto-refreshing of charts is paused for this amount + // of time + + sync_selection_delay: 400, // ms - when you pan or zoom a chart, wait this amount + // of time before setting up synchronized selections + // on hover. + + sync_selection: true, // enable or disable selection sync + + pan_and_zoom_delay: 50, // when panning or zooming, how ofter to update the chart + + sync_pan_and_zoom: true, // enable or disable pan and zoom sync + + pan_and_zoom_data_padding: true, // fetch more data for the master chart when panning or zooming + + update_only_visible: true, // enable or disable visibility management / used for printing + + parallel_refresher: !isSlowDevice(), // enable parallel refresh of charts + + concurrent_refreshes: true, // when parallel_refresher is enabled, sync also the charts + + destroy_on_hide: isSlowDevice(), // destroy charts when they are not visible + + show_help: netdataShowHelp, // when enabled the charts will show some help + show_help_delay_show_ms: 500, + show_help_delay_hide_ms: 0, + + eliminate_zero_dimensions: true, // do not show dimensions with just zeros + + stop_updates_when_focus_is_lost: true, // boolean - shall we stop auto-refreshes when document does not have user focus + stop_updates_while_resizing: 1000, // ms - time to stop auto-refreshes while resizing the charts + + double_click_speed: 500, // ms - time between clicks / taps to detect double click/tap + + smooth_plot: !isSlowDevice(), // enable smooth plot, where possible + + color_fill_opacity_line: 1.0, + color_fill_opacity_area: 0.2, + color_fill_opacity_stacked: 0.8, + + pan_and_zoom_factor: 0.25, // the increment when panning and zooming with the toolbox + pan_and_zoom_factor_multiplier_control: 2.0, + pan_and_zoom_factor_multiplier_shift: 3.0, + pan_and_zoom_factor_multiplier_alt: 4.0, + + abort_ajax_on_scroll: false, // kill pending ajax page scroll + async_on_scroll: false, // sync/async onscroll handler + onscroll_worker_duration_threshold: 30, // time in ms, for async scroll handler + + retries_on_data_failures: 3, // how many retries to make if we can't fetch chart data from the server + + setOptionCallback: function () { + } + }, + + debug: { + show_boxes: false, + main_loop: false, + focus: false, + visibility: false, + chart_data_url: false, + chart_errors: true, // remember to set it to false before merging + chart_timing: false, + chart_calls: false, + libraries: false, + dygraph: false, + globalSelectionSync: false, + globalPanAndZoom: false + } +}; + +NETDATA.statistics = { + refreshes_total: 0, + refreshes_active: 0, + refreshes_active_max: 0 +}; diff --git a/web/gui/src/dashboard.js/prologue.js.inc b/web/gui/src/dashboard.js/prologue.js.inc new file mode 100644 index 0000000..afa1f0e --- /dev/null +++ b/web/gui/src/dashboard.js/prologue.js.inc @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +// DO NOT EDIT: This file is automatically generated from the source files in src/ + +// ---------------------------------------------------------------------------- +// You can set the following variables before loading this script: + +// 'use strict'; + +/*global netdataNoDygraphs *//* boolean, disable dygraph charts + * (default: false) */ +/*global netdataNoSparklines *//* boolean, disable sparkline charts + * (default: false) */ +/*global netdataNoPeitys *//* boolean, disable peity charts + * (default: false) */ +/*global netdataNoGoogleCharts *//* boolean, disable google charts + * (default: false) */ +/*global netdataNoMorris *//* boolean, disable morris charts + * (default: false) */ +/*global netdataNoEasyPieChart *//* boolean, disable easypiechart charts + * (default: false) */ +/*global netdataNoGauge *//* boolean, disable gauge.js charts + * (default: false) */ +/*global netdataNoD3 *//* boolean, disable d3 charts + * (default: false) */ +/*global netdataNoC3 *//* boolean, disable c3 charts + * (default: false) */ +/*global netdataNoD3pie *//* boolean, disable d3pie charts + * (default: false) */ +/*global netdataNoBootstrap *//* boolean, disable bootstrap - disables help too + * (default: false) */ +/*global netdataNoFontAwesome *//* boolean, disable fontawesome (do not load it) + * (default: false) */ +/*global netdataIcons *//* object, overwrite netdata fontawesome icons + * (default: null) */ +/*global netdataDontStart *//* boolean, do not start the thread to process the charts + * (default: false) */ +/*global netdataErrorCallback *//* function, callback to be called when the dashboard encounters an error + * (default: null) */ +/*global netdataRegistry:true *//* boolean, use the netdata registry + * (default: false) */ +/*global netdataNoRegistry *//* boolean, included only for compatibility with existing custom dashboard + * (obsolete - do not use this any more) */ +/*global netdataRegistryCallback *//* function, callback that will be invoked with one param: the URLs from the registry + * (default: null) */ +/*global netdataShowHelp:true *//* boolean, disable charts help + * (default: true) */ +/*global netdataShowAlarms:true *//* boolean, enable alarms checks and notifications + * (default: false) */ +/*global netdataRegistryAfterMs:true *//* ms, delay registry use at started + * (default: 1500) */ +/*global netdataCallback *//* function, callback to be called when netdata is ready to start + * (default: null) + * netdata will be running while this is called + * (call NETDATA.pause to stop it) */ +/*global netdataPrepCallback *//* function, callback to be called before netdata does anything else + * (default: null) */ +/*global netdataServer *//* string, the URL of the netdata server to use + * (default: the URL the page is hosted at) */ +/*global netdataServerStatic *//* string, the URL of the netdata server to use for static files + * (default: netdataServer) */ +/*global netdataSnapshotData *//* object, a netdata snapshot loaded + * (default: null) */ +/*global netdataAlarmsRecipients *//* array, an array of alarm recipients to show notifications for + * (default: null) */ +/*global netdataAlarmsRemember *//* boolen, keep our position in the alarm log at browser local storage + * (default: true) */ +/*global netdataAlarmsActiveCallback *//* function, a hook for the alarm logs + * (default: undefined) */ +/*global netdataAlarmsNotifCallback *//* function, a hook for alarm notifications + * (default: undefined) */ +/*global netdataIntersectionObserver *//* boolean, enable or disable the use of intersection observer + * (default: true) */ +/*global netdataCheckXSS *//* boolean, enable or disable checking for XSS issues + * (default: false) */ + +// ---------------------------------------------------------------------------- +// global namespace + +// Should stay var! +var NETDATA = window.NETDATA || {}; + +(function(window, document, $, undefined) { + diff --git a/web/gui/src/dashboard.js/registry.js b/web/gui/src/dashboard.js/registry.js new file mode 100644 index 0000000..77a822b --- /dev/null +++ b/web/gui/src/dashboard.js/registry.js @@ -0,0 +1,303 @@ + +// Registry of netdata hosts + +NETDATA.registry = { + server: null, // the netdata registry server + isCloudEnabled: false,// is netdata.cloud functionality enabled? + cloudBaseURL: null, // the netdata cloud base url + person_guid: null, // the unique ID of this browser / user + machine_guid: null, // the unique ID the netdata server that served dashboard.js + hostname: 'unknown', // the hostname of the netdata server that served dashboard.js + machines: null, // the user's other URLs + machines_array: null, // the user's other URLs in an array + person_urls: null, + + MASKED_DATA: "***", + + isUsingGlobalRegistry: function() { + return NETDATA.registry.server == "https://registry.my-netdata.io"; + }, + + isRegistryEnabled: function() { + return !(NETDATA.registry.isUsingGlobalRegistry() || isSignedIn()) + }, + + parsePersonUrls: function (person_urls) { + NETDATA.registry.person_urls = person_urls; + + if (person_urls) { + NETDATA.registry.machines = {}; + NETDATA.registry.machines_array = []; + + let apu = person_urls; + let i = apu.length; + while (i--) { + if (typeof NETDATA.registry.machines[apu[i][0]] === 'undefined') { + // console.log('adding: ' + apu[i][4] + ', ' + ((now - apu[i][2]) / 1000).toString()); + + let obj = { + guid: apu[i][0], + url: apu[i][1], + last_t: apu[i][2], + accesses: apu[i][3], + name: apu[i][4], + alternate_urls: [] + }; + obj.alternate_urls.push(apu[i][1]); + + NETDATA.registry.machines[apu[i][0]] = obj; + NETDATA.registry.machines_array.push(obj); + } else { + // console.log('appending: ' + apu[i][4] + ', ' + ((now - apu[i][2]) / 1000).toString()); + + let pu = NETDATA.registry.machines[apu[i][0]]; + if (pu.last_t < apu[i][2]) { + pu.url = apu[i][1]; + pu.last_t = apu[i][2]; + pu.name = apu[i][4]; + } + pu.accesses += apu[i][3]; + pu.alternate_urls.push(apu[i][1]); + } + } + } + + if (typeof netdataRegistryCallback === 'function') { + netdataRegistryCallback(NETDATA.registry.machines_array); + } + }, + + init: function () { + if (netdataRegistry !== true) { + return; + } + + NETDATA.registry.hello(NETDATA.serverDefault, function (data) { + if (data) { + NETDATA.registry.server = data.registry; + if (data.cloud_base_url != "") { + NETDATA.registry.isCloudEnabled = true; + NETDATA.registry.cloudBaseURL = data.cloud_base_url; + } else { + NETDATA.registry.isCloudEnabled = false; + NETDATA.registry.cloudBaseURL = ""; + } + NETDATA.registry.machine_guid = data.machine_guid; + NETDATA.registry.hostname = data.hostname; + if (dataLayer) { + if (data.anonymous_statistics) dataLayer.push({"anonymous_statistics" : "true", "machine_guid" : data.machine_guid}); + } + NETDATA.registry.access(2, function (person_urls) { + NETDATA.registry.parsePersonUrls(person_urls); + }); + } + }); + }, + + hello: function (host, callback) { + host = NETDATA.fixHost(host); + + // send HELLO to a netdata server: + // 1. verifies the server is reachable + // 2. responds with the registry URL, the machine GUID of this netdata server and its hostname + $.ajax({ + url: host + '/api/v1/registry?action=hello', + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkOptional('/api/v1/registry?action=hello', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(408, host + ' response: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(407, host); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + access: function (max_redirects, callback) { + let name = NETDATA.registry.MASKED_DATA; + let url = NETDATA.registry.MASKED_DATA; + + if (!NETDATA.registry.isUsingGlobalRegistry()) { + // If the user is using a private registry keep sending identifiable + // data. + name = NETDATA.registry.hostname; + url = NETDATA.serverDefault; + } + + console.log("ACCESS", name, url); + + // send ACCESS to a netdata registry: + // 1. it lets it know we are accessing a netdata server (its machine GUID and its URL) + // 2. it responds with a list of netdata servers we know + // the registry identifies us using a cookie it sets the first time we access it + // the registry may respond with a redirect URL to send us to another registry + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=access&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(name) + '&url=' + encodeURIComponent(url), // + '&visible_url=' + encodeURIComponent(document.location), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=access', data); + + let redirect = null; + if (typeof data.registry === 'string') { + redirect = data.registry; + } + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(409, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (data === null) { + if (redirect !== null && max_redirects > 0) { + NETDATA.registry.server = redirect; + NETDATA.registry.access(max_redirects - 1, callback); + } + else { + if (typeof callback === 'function') { + return callback(null); + } + } + } else { + if (typeof data.person_guid === 'string') { + NETDATA.registry.person_guid = data.person_guid; + } + + if (typeof callback === 'function') { + const urls = data.urls.filter((u) => u[1] !== NETDATA.registry.MASKED_DATA); + return callback(urls); + } + } + }) + .fail(function () { + NETDATA.error(410, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + delete: function (delete_url, callback) { + // send DELETE to a netdata registry: + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=delete&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&delete_url=' + encodeURIComponent(delete_url), + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=delete', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(411, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(412, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + search: function (machine_guid, callback) { + // SEARCH for the URLs of a machine: + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=search&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&for=' + machine_guid, + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=search', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(417, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(418, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + }, + + switch: function (new_person_guid, callback) { + // impersonate + $.ajax({ + url: NETDATA.registry.server + '/api/v1/registry?action=switch&machine=' + NETDATA.registry.machine_guid + '&name=' + encodeURIComponent(NETDATA.registry.hostname) + '&url=' + encodeURIComponent(NETDATA.serverDefault) + '&to=' + new_person_guid, + async: true, + cache: false, + headers: { + 'Cache-Control': 'no-cache, no-store', + 'Pragma': 'no-cache' + }, + xhrFields: {withCredentials: true} // required for the cookie + }) + .done(function (data) { + data = NETDATA.xss.checkAlways('/api/v1/registry?action=switch', data); + + if (typeof data.status !== 'string' || data.status !== 'ok') { + NETDATA.error(413, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data)); + data = null; + } + + if (typeof callback === 'function') { + return callback(data); + } + }) + .fail(function () { + NETDATA.error(414, NETDATA.registry.server); + + if (typeof callback === 'function') { + return callback(null); + } + }); + } +}; diff --git a/web/gui/src/dashboard.js/server-detection.js b/web/gui/src/dashboard.js/server-detection.js new file mode 100644 index 0000000..472ad48 --- /dev/null +++ b/web/gui/src/dashboard.js/server-detection.js @@ -0,0 +1,29 @@ + +// *** src/dashboard.js/server-detection.js + +if (typeof netdataServer !== 'undefined') { + NETDATA.serverDefault = netdataServer; +} else { + let s = NETDATA._scriptSource(); + if (s) { + NETDATA.serverDefault = s.replace(/\/dashboard.js(\?.*)?$/g, ""); + } else { + console.log('WARNING: Cannot detect the URL of the netdata server.'); + NETDATA.serverDefault = null; + } +} + +if (NETDATA.serverDefault === null) { + NETDATA.serverDefault = ''; +} else if (NETDATA.serverDefault.slice(-1) !== '/') { + NETDATA.serverDefault += '/'; +} + +if (typeof netdataServerStatic !== 'undefined' && netdataServerStatic !== null && netdataServerStatic !== '') { + NETDATA.serverStatic = netdataServerStatic; + if (NETDATA.serverStatic.slice(-1) !== '/') { + NETDATA.serverStatic += '/'; + } +} else { + NETDATA.serverStatic = NETDATA.serverDefault; +} diff --git a/web/gui/src/dashboard.js/themes.js b/web/gui/src/dashboard.js/themes.js new file mode 100644 index 0000000..aafe157 --- /dev/null +++ b/web/gui/src/dashboard.js/themes.js @@ -0,0 +1,92 @@ +// Codacy declarations +/* global netdataTheme */ + +NETDATA.themes = { + white: { + bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-3.3.7.css', + dashboard_css: NETDATA.serverStatic + 'dashboard.css?v20180210-1', + background: '#FFFFFF', + foreground: '#000000', + grid: '#F0F0F0', + axis: '#F0F0F0', + highlight: '#F5F5F5', + colors: ['#3366CC', '#DC3912', '#109618', '#FF9900', '#990099', '#DD4477', + '#3B3EAC', '#66AA00', '#0099C6', '#B82E2E', '#AAAA11', '#5574A6', + '#994499', '#22AA99', '#6633CC', '#E67300', '#316395', '#8B0707', + '#329262', '#3B3EAC'], + easypiechart_track: '#f0f0f0', + easypiechart_scale: '#dfe0e0', + gauge_pointer: '#C0C0C0', + gauge_stroke: '#F0F0F0', + gauge_gradient: false, + d3pie: { + title: '#333333', + subtitle: '#666666', + footer: '#888888', + other: '#aaaaaa', + mainlabel: '#333333', + percentage: '#dddddd', + value: '#aaaa22', + tooltip_bg: '#000000', + tooltip_fg: '#efefef', + segment_stroke: "#ffffff", + gradient_color: '#000000' + } + }, + slate: { + bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-slate-flat-3.3.7.css?v20161229-1', + dashboard_css: NETDATA.serverStatic + 'dashboard.slate.css?v20180210-1', + background: '#272b30', + foreground: '#C8C8C8', + grid: '#283236', + axis: '#283236', + highlight: '#383838', + /* colors: [ '#55bb33', '#ff2222', '#0099C6', '#faa11b', '#adbce0', '#DDDD00', + '#4178ba', '#f58122', '#a5cc39', '#f58667', '#f5ef89', '#cf93c0', + '#a5d18a', '#b8539d', '#3954a3', '#c8a9cf', '#c7de8a', '#fad20a', + '#a6a479', '#a66da8' ], + */ + colors: ['#66AA00', '#FE3912', '#3366CC', '#D66300', '#0099C6', '#DDDD00', + '#5054e6', '#EE9911', '#BB44CC', '#e45757', '#ef0aef', '#CC7700', + '#22AA99', '#109618', '#905bfd', '#f54882', '#4381bf', '#ff3737', + '#329262', '#3B3EFF'], + easypiechart_track: '#373b40', + easypiechart_scale: '#373b40', + gauge_pointer: '#474b50', + gauge_stroke: '#373b40', + gauge_gradient: false, + d3pie: { + title: '#C8C8C8', + subtitle: '#283236', + footer: '#283236', + other: '#283236', + mainlabel: '#C8C8C8', + percentage: '#dddddd', + value: '#cccc44', + tooltip_bg: '#272b30', + tooltip_fg: '#C8C8C8', + segment_stroke: "#283236", + gradient_color: '#000000' + } + } +}; + +if (typeof netdataTheme !== 'undefined' && typeof NETDATA.themes[netdataTheme] !== 'undefined') { + NETDATA.themes.current = NETDATA.themes[netdataTheme]; +} else { + NETDATA.themes.current = NETDATA.themes.white; +} + +NETDATA.colors = NETDATA.themes.current.colors; + +// these are the colors Google Charts are using +// we have them here to attempt emulate their look and feel on the other chart libraries +// http://there4.io/2012/05/02/google-chart-color-list/ +//NETDATA.colors = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6', +// '#DD4477', '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11', +// '#6633CC', '#E67300', '#8B0707', '#329262', '#5574A6', '#3B3EAC' ]; + +// an alternative set +// http://www.mulinblog.com/a-color-palette-optimized-for-data-visualization/ +// (blue) (red) (orange) (green) (pink) (brown) (purple) (yellow) (gray) +//NETDATA.colors = [ '#5DA5DA', '#F15854', '#FAA43A', '#60BD68', '#F17CB0', '#B2912F', '#B276B2', '#DECF3F', '#4D4D4D' ]; diff --git a/web/gui/src/dashboard.js/timeout.js b/web/gui/src/dashboard.js/timeout.js new file mode 100644 index 0000000..4adf9bb --- /dev/null +++ b/web/gui/src/dashboard.js/timeout.js @@ -0,0 +1,100 @@ + +// *** src/dashboard.js/timeout.js + +// TODO: Better name needed + +NETDATA.timeout = { + // by default, these are just wrappers to setTimeout() / clearTimeout() + + step: function (callback) { + return window.setTimeout(callback, 1000 / 60); + }, + + set: function (callback, delay) { + return window.setTimeout(callback, delay); + }, + + clear: function (id) { + return window.clearTimeout(id); + }, + + init: function () { + let custom = true; + + if (window.requestAnimationFrame) { + this.step = function (callback) { + return window.requestAnimationFrame(callback); + }; + + this.clear = function (handle) { + return window.cancelAnimationFrame(handle.value); + }; + // } else if (window.webkitRequestAnimationFrame) { + // this.step = function (callback) { + // return window.webkitRequestAnimationFrame(callback); + // }; + + // if (window.webkitCancelAnimationFrame) { + // this.clear = function (handle) { + // return window.webkitCancelAnimationFrame(handle.value); + // }; + // } else if (window.webkitCancelRequestAnimationFrame) { + // this.clear = function (handle) { + // return window.webkitCancelRequestAnimationFrame(handle.value); + // }; + // } + // } else if (window.mozRequestAnimationFrame) { + // this.step = function (callback) { + // return window.mozRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.mozCancelRequestAnimationFrame(handle.value); + // }; + // } else if (window.oRequestAnimationFrame) { + // this.step = function (callback) { + // return window.oRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.oCancelRequestAnimationFrame(handle.value); + // }; + // } else if (window.msRequestAnimationFrame) { + // this.step = function (callback) { + // return window.msRequestAnimationFrame(callback); + // }; + + // this.clear = function (handle) { + // return window.msCancelRequestAnimationFrame(handle.value); + // }; + } else { + custom = false; + } + + if (custom) { + // we have installed custom .step() / .clear() functions + // overwrite the .set() too + + this.set = function (callback, delay) { + let start = Date.now(), + handle = new Object(); + + const loop = () => { + let current = Date.now(), + delta = current - start; + + if (delta >= delay) { + callback.call(); + } else { + handle.value = this.step(loop); + } + } + + handle.value = this.step(loop); + return handle; + }; + } + } +}; + +NETDATA.timeout.init(); diff --git a/web/gui/src/dashboard.js/units-conversion.js b/web/gui/src/dashboard.js/units-conversion.js new file mode 100644 index 0000000..26b8403 --- /dev/null +++ b/web/gui/src/dashboard.js/units-conversion.js @@ -0,0 +1,441 @@ +NETDATA.unitsConversion = { + keys: {}, // keys for data-common-units + latest: {}, // latest selected units for data-common-units + + globalReset: function () { + this.keys = {}; + this.latest = {}; + }, + + scalableUnits: { + 'packets/s': { + 'pps': 1, + 'Kpps': 1000, + 'Mpps': 1000000 + }, + 'pps': { + 'pps': 1, + 'Kpps': 1000, + 'Mpps': 1000000 + }, + 'kilobits/s': { + 'bits/s': 1 / 1000, + 'kilobits/s': 1, + 'megabits/s': 1000, + 'gigabits/s': 1000000, + 'terabits/s': 1000000000 + }, + 'kilobytes/s': { + 'bytes/s': 1 / 1024, + 'kilobytes/s': 1, + 'megabytes/s': 1024, + 'gigabytes/s': 1024 * 1024, + 'terabytes/s': 1024 * 1024 * 1024 + }, + 'KB/s': { + 'B/s': 1 / 1024, + 'KB/s': 1, + 'MB/s': 1024, + 'GB/s': 1024 * 1024, + 'TB/s': 1024 * 1024 * 1024 + }, + 'KiB/s': { + 'B/s': 1 / 1024, + 'KiB/s': 1, + 'MiB/s': 1024, + 'GiB/s': 1024 * 1024, + 'TiB/s': 1024 * 1024 * 1024 + }, + 'B': { + 'B': 1, + 'KiB': 1024, + 'MiB': 1024 * 1024, + 'GiB': 1024 * 1024 * 1024, + 'TiB': 1024 * 1024 * 1024 * 1024, + 'PiB': 1024 * 1024 * 1024 * 1024 * 1024 + }, + 'KB': { + 'B': 1 / 1024, + 'KB': 1, + 'MB': 1024, + 'GB': 1024 * 1024, + 'TB': 1024 * 1024 * 1024 + }, + 'KiB': { + 'B': 1 / 1024, + 'KiB': 1, + 'MiB': 1024, + 'GiB': 1024 * 1024, + 'TiB': 1024 * 1024 * 1024 + }, + 'MB': { + 'B': 1 / (1024 * 1024), + 'KB': 1 / 1024, + 'MB': 1, + 'GB': 1024, + 'TB': 1024 * 1024, + 'PB': 1024 * 1024 * 1024 + }, + 'MiB': { + 'B': 1 / (1024 * 1024), + 'KiB': 1 / 1024, + 'MiB': 1, + 'GiB': 1024, + 'TiB': 1024 * 1024, + 'PiB': 1024 * 1024 * 1024 + }, + 'GB': { + 'B': 1 / (1024 * 1024 * 1024), + 'KB': 1 / (1024 * 1024), + 'MB': 1 / 1024, + 'GB': 1, + 'TB': 1024, + 'PB': 1024 * 1024, + 'EB': 1024 * 1024 * 1024 + }, + 'GiB': { + 'B': 1 / (1024 * 1024 * 1024), + 'KiB': 1 / (1024 * 1024), + 'MiB': 1 / 1024, + 'GiB': 1, + 'TiB': 1024, + 'PiB': 1024 * 1024, + 'EiB': 1024 * 1024 * 1024 + } + /* + 'milliseconds': { + 'seconds': 1000 + }, + 'seconds': { + 'milliseconds': 0.001, + 'seconds': 1, + 'minutes': 60, + 'hours': 3600, + 'days': 86400 + } + */ + }, + + convertibleUnits: { + 'Celsius': { + 'Fahrenheit': { + check: function (max) { + void(max); + return NETDATA.options.current.temperature === 'fahrenheit'; + }, + convert: function (value) { + return value * 9 / 5 + 32; + } + } + }, + 'celsius': { + 'fahrenheit': { + check: function (max) { + void(max); + return NETDATA.options.current.temperature === 'fahrenheit'; + }, + convert: function (value) { + return value * 9 / 5 + 32; + } + } + }, + 'seconds': { + 'time': { + check: function (max) { + void(max); + return NETDATA.options.current.seconds_as_time; + }, + convert: function (seconds) { + return NETDATA.unitsConversion.seconds2time(seconds); + } + } + }, + 'milliseconds': { + 'milliseconds': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max < 1000; + }, + convert: function (milliseconds) { + let tms = Math.round(milliseconds * 10); + milliseconds = Math.floor(tms / 10); + + tms -= milliseconds * 10; + + return (milliseconds).toString() + '.' + tms.toString(); + } + }, + 'seconds': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max >= 1000 && max < 60000; + }, + convert: function (milliseconds) { + milliseconds = Math.round(milliseconds); + + let seconds = Math.floor(milliseconds / 1000); + milliseconds -= seconds * 1000; + + milliseconds = Math.round(milliseconds / 10); + + return seconds.toString() + '.' + + NETDATA.zeropad(milliseconds); + } + }, + 'M:SS.ms': { + check: function (max) { + return NETDATA.options.current.seconds_as_time && max >= 60000; + }, + convert: function (milliseconds) { + milliseconds = Math.round(milliseconds); + + let minutes = Math.floor(milliseconds / 60000); + milliseconds -= minutes * 60000; + + let seconds = Math.floor(milliseconds / 1000); + milliseconds -= seconds * 1000; + + milliseconds = Math.round(milliseconds / 10); + + return minutes.toString() + ':' + + NETDATA.zeropad(seconds) + '.' + + NETDATA.zeropad(milliseconds); + } + } + } + }, + + seconds2time: function (seconds) { + seconds = Math.abs(seconds); + + let days = Math.floor(seconds / 86400); + seconds -= days * 86400; + + let hours = Math.floor(seconds / 3600); + seconds -= hours * 3600; + + let minutes = Math.floor(seconds / 60); + seconds -= minutes * 60; + + seconds = Math.round(seconds); + + let ms_txt = ''; + /* + let ms = seconds - Math.floor(seconds); + seconds -= ms; + ms = Math.round(ms * 1000); + + if (ms > 1) { + if (ms < 10) + ms_txt = '.00' + ms.toString(); + else if (ms < 100) + ms_txt = '.0' + ms.toString(); + else + ms_txt = '.' + ms.toString(); + } + */ + + return ((days > 0) ? days.toString() + 'd:' : '').toString() + + NETDATA.zeropad(hours) + ':' + + NETDATA.zeropad(minutes) + ':' + + NETDATA.zeropad(seconds) + + ms_txt; + }, + + // get a function that converts the units + // + every time units are switched call the callback + get: function (uuid, min, max, units, desired_units, common_units_name, switch_units_callback) { + // validate the parameters + if (typeof units === 'undefined') { + units = 'undefined'; + } + + // check if we support units conversion + if (typeof this.scalableUnits[units] === 'undefined' && typeof this.convertibleUnits[units] === 'undefined') { + // we can't convert these units + //console.log('DEBUG: ' + uuid.toString() + ' can\'t convert units: ' + units.toString()); + return function (value) { + return value; + }; + } + + // check if the caller wants the original units + if (typeof desired_units === 'undefined' || desired_units === null || desired_units === 'original' || desired_units === units) { + //console.log('DEBUG: ' + uuid.toString() + ' original units wanted'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + + // now we know we can convert the units + // and the caller wants some kind of conversion + + let tunits = null; + let tdivider = 0; + + if (typeof this.scalableUnits[units] !== 'undefined') { + // units that can be scaled + // we decide a divider + + // console.log('NETDATA.unitsConversion.get(' + units.toString() + ', ' + desired_units.toString() + ', function()) decide divider with min = ' + min.toString() + ', max = ' + max.toString()); + + if (desired_units === 'auto') { + // the caller wants to auto-scale the units + + // find the absolute maximum value that is rendered on the chart + // based on this we decide the scale + min = Math.abs(min); + max = Math.abs(max); + if (min > max) { + max = min; + } + + // find the smallest scale that provides integers + // for (x in this.scalableUnits[units]) { + // if (this.scalableUnits[units].hasOwnProperty(x)) { + // let m = this.scalableUnits[units][x]; + // if (m <= max && m > tdivider) { + // tunits = x; + // tdivider = m; + // } + // } + // } + const sunit = this.scalableUnits[units]; + for (var x of Object.keys(sunit)) { + let m = sunit[x]; + if (m <= max && m > tdivider) { + tunits = x; + tdivider = m; + } + } + + if (tunits === null || tdivider <= 0) { + // we couldn't find one + //console.log('DEBUG: ' + uuid.toString() + ' cannot find an auto-scaling candidate for units: ' + units.toString() + ' (max: ' + max.toString() + ')'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + + if (typeof common_units_name === 'string' && typeof uuid === 'string') { + // the caller wants several charts to have the same units + // data-common-units + + let common_units_key = common_units_name + '-' + units; + + // add our divider into the list of keys + let t = this.keys[common_units_key]; + if (typeof t === 'undefined') { + this.keys[common_units_key] = {}; + t = this.keys[common_units_key]; + } + t[uuid] = { + units: tunits, + divider: tdivider + }; + + // find the max divider of all charts + let common_units = t[uuid]; + for (var x in t) { + if (t.hasOwnProperty(x) && t[x].divider > common_units.divider) { + common_units = t[x]; + } + } + + // save our common_max to the latest keys + let latest = this.latest[common_units_key]; + if (typeof latest === 'undefined') { + this.latest[common_units_key] = {}; + latest = this.latest[common_units_key]; + } + latest.units = common_units.units; + latest.divider = common_units.divider; + + tunits = latest.units; + tdivider = latest.divider; + + //console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + tunits.toString() + ' with divider ' + tdivider.toString() + ', common-units=' + common_units_name.toString() + ((t[uuid].divider !== tdivider)?' USED COMMON, mine was ' + t[uuid].units:' set common').toString()); + + // apply it to this chart + switch_units_callback(tunits); + return function (value) { + if (tdivider !== latest.divider) { + // another chart switched our common units + // we should switch them too + //console.log('DEBUG: ' + uuid + ' switching units due to a common-units change, from ' + tunits.toString() + ' to ' + latest.units.toString()); + tunits = latest.units; + tdivider = latest.divider; + switch_units_callback(tunits); + } + + return value / tdivider; + }; + } else { + // the caller did not give data-common-units + // this chart auto-scales independently of all others + //console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + tunits.toString() + ' with divider ' + tdivider.toString() + ', autonomously'); + + switch_units_callback(tunits); + return function (value) { + return value / tdivider; + }; + } + } else { + // the caller wants specific units + + if (typeof this.scalableUnits[units][desired_units] !== 'undefined') { + // all good, set the new units + tdivider = this.scalableUnits[units][desired_units]; + // console.log('DEBUG: ' + uuid.toString() + ' converted units: ' + units.toString() + ' to units: ' + desired_units.toString() + ' with divider ' + tdivider.toString() + ', by reference'); + switch_units_callback(desired_units); + return function (value) { + return value / tdivider; + }; + } else { + // oops! switch back to original units + console.log('Units conversion from ' + units.toString() + ' to ' + desired_units.toString() + ' is not supported.'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } + } else if (typeof this.convertibleUnits[units] !== 'undefined') { + // units that can be converted + if (desired_units === 'auto') { + for (var x in this.convertibleUnits[units]) { + if (this.convertibleUnits[units].hasOwnProperty(x)) { + if (this.convertibleUnits[units][x].check(max)) { + //console.log('DEBUG: ' + uuid.toString() + ' converting ' + units.toString() + ' to: ' + x.toString()); + switch_units_callback(x); + return this.convertibleUnits[units][x].convert; + } + } + } + + // none checked ok + //console.log('DEBUG: ' + uuid.toString() + ' no conversion available for ' + units.toString() + ' to: ' + desired_units.toString()); + switch_units_callback(units); + return function (value) { + return value; + }; + } else if (typeof this.convertibleUnits[units][desired_units] !== 'undefined') { + switch_units_callback(desired_units); + return this.convertibleUnits[units][desired_units].convert; + } else { + console.log('Units conversion from ' + units.toString() + ' to ' + desired_units.toString() + ' is not supported.'); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } else { + // hm... did we forget to implement the new type? + console.log(`Unmatched unit conversion method for units ${units.toString()}`); + switch_units_callback(units); + return function (value) { + return value; + }; + } + } +}; diff --git a/web/gui/src/dashboard.js/utils.js b/web/gui/src/dashboard.js/utils.js new file mode 100644 index 0000000..8014aaf --- /dev/null +++ b/web/gui/src/dashboard.js/utils.js @@ -0,0 +1,432 @@ +// *** src/dashboard.js/utils.js + +NETDATA.name2id = function (s) { + return s + .replace(/ /g, '_') + .replace(/:/g, '_') + .replace(/\(/g, '_') + .replace(/\)/g, '_') + .replace(/\./g, '_') + .replace(/\//g, '_'); +}; + +NETDATA.encodeURIComponent = function (s) { + if (typeof(s) === 'string') { + return encodeURIComponent(s); + } + + return s; +}; + +/// A heuristic for detecting slow devices. +let isSlowDeviceResult = undefined; +const isSlowDevice = function () { + if (!isSlowDeviceResult) { + return isSlowDeviceResult; + } + + try { + let ua = navigator.userAgent.toLowerCase(); + + let iOS = /ipad|iphone|ipod/.test(ua) && !window.MSStream; + let android = /android/.test(ua) && !window.MSStream; + isSlowDeviceResult = (iOS || android); + } catch (e) { + isSlowDeviceResult = false; + } + + return isSlowDeviceResult; +}; + +NETDATA.guid = function () { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); +}; + +NETDATA.zeropad = function (x) { + if (x > -10 && x < 10) { + return '0' + x.toString(); + } else { + return x.toString(); + } +}; + +NETDATA.seconds4human = function (seconds, options) { + let defaultOptions = { + now: 'now', + space: ' ', + negative_suffix: 'ago', + day: 'day', + days: 'days', + hour: 'hour', + hours: 'hours', + minute: 'min', + minutes: 'mins', + second: 'sec', + seconds: 'secs', + and: 'and' + }; + + if (typeof options !== 'object') { + options = defaultOptions; + } else { + for (var x in defaultOptions) { + if (typeof options[x] !== 'string') { + options[x] = defaultOptions[x]; + } + } + } + + if (typeof seconds === 'string') { + seconds = parseInt(seconds, 10); + } + + if (seconds === 0) { + return options.now; + } + + let suffix = ''; + if (seconds < 0) { + seconds = -seconds; + if (options.negative_suffix !== '') { + suffix = options.space + options.negative_suffix; + } + } + + let days = Math.floor(seconds / 86400); + seconds -= (days * 86400); + + let hours = Math.floor(seconds / 3600); + seconds -= (hours * 3600); + + let minutes = Math.floor(seconds / 60); + seconds -= (minutes * 60); + + let strings = []; + + if (days > 1) { + strings.push(days.toString() + options.space + options.days); + } else if (days === 1) { + strings.push(days.toString() + options.space + options.day); + } + + if (hours > 1) { + strings.push(hours.toString() + options.space + options.hours); + } else if (hours === 1) { + strings.push(hours.toString() + options.space + options.hour); + } + + if (minutes > 1) { + strings.push(minutes.toString() + options.space + options.minutes); + } else if (minutes === 1) { + strings.push(minutes.toString() + options.space + options.minute); + } + + if (seconds > 1) { + strings.push(Math.floor(seconds).toString() + options.space + options.seconds); + } else if (seconds === 1) { + strings.push(Math.floor(seconds).toString() + options.space + options.second); + } + + if (strings.length === 1) { + return strings.pop() + suffix; + } + + let last = strings.pop(); + return strings.join(", ") + " " + options.and + " " + last + suffix; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// element data attributes + +NETDATA.dataAttribute = function (element, attribute, def) { + let key = 'data-' + attribute.toString(); + if (element.hasAttribute(key)) { + let data = element.getAttribute(key); + + if (data === 'true') { + return true; + } + if (data === 'false') { + return false; + } + if (data === 'null') { + return null; + } + + // Only convert to a number if it doesn't change the string + if (data === +data + '') { + return +data; + } + + if (/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/.test(data)) { + return JSON.parse(data); + } + + return data; + } else { + return def; + } +}; + +NETDATA.dataAttributeBoolean = function (element, attribute, def) { + let value = NETDATA.dataAttribute(element, attribute, def); + + if (value === true || value === false) // gmosx: Love this :) + { + return value; + } + + if (typeof(value) === 'string') { + if (value === 'yes' || value === 'on') { + return true; + } + + if (value === '' || value === 'no' || value === 'off' || value === 'null') { + return false; + } + + return def; + } + + if (typeof(value) === 'number') { + return value !== 0; + } + + return def; +}; + +// ---------------------------------------------------------------------------------------------------------------- +// fast numbers formatting + +NETDATA.fastNumberFormat = { + formattersFixed: [], + formattersZeroBased: [], + + // this is the fastest and the preferred + getIntlNumberFormat: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + + return this.formattersZeroBased[key]; + } else { + // this is never used + // it is added just for completeness + return new Intl.NumberFormat(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }, + + // this respects locale + getLocaleString: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + + return this.formattersZeroBased[key]; + } else { + return { + format: function (value) { + return value.toLocaleString(undefined, { + // style: 'decimal', + // minimumIntegerDigits: 1, + // minimumSignificantDigits: 1, + // maximumSignificantDigits: 1, + useGrouping: true, + minimumFractionDigits: min, + maximumFractionDigits: max + }); + } + }; + } + }, + + // the fallback + getFixed: function (min, max) { + let key = max; + if (min === max) { + if (typeof this.formattersFixed[key] === 'undefined') { + this.formattersFixed[key] = { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + + return this.formattersFixed[key]; + } else if (min === 0) { + if (typeof this.formattersZeroBased[key] === 'undefined') { + this.formattersZeroBased[key] = { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + + return this.formattersZeroBased[key]; + } else { + return { + format: function (value) { + if (value === 0) { + return "0"; + } + return value.toFixed(max); + } + }; + } + }, + + testIntlNumberFormat: function () { + let value = 1.12345; + let e1 = "1.12", e2 = "1,12"; + let s = ""; + + try { + let x = new Intl.NumberFormat(undefined, { + useGrouping: true, + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + + s = x.format(value); + } catch (e) { + s = ""; + } + + // console.log('NumberFormat: ', s); + return (s === e1 || s === e2); + }, + + testLocaleString: function () { + let value = 1.12345; + let e1 = "1.12", e2 = "1,12"; + let s = ""; + + try { + s = value.toLocaleString(undefined, { + useGrouping: true, + minimumFractionDigits: 2, + maximumFractionDigits: 2 + }); + } catch (e) { + s = ""; + } + + // console.log('localeString: ', s); + return (s === e1 || s === e2); + }, + + // on first run we decide which formatter to use + get: function (min, max) { + if (this.testIntlNumberFormat()) { + // console.log('numberformat'); + this.get = this.getIntlNumberFormat; + } else if (this.testLocaleString()) { + // console.log('localestring'); + this.get = this.getLocaleString; + } else { + // console.log('fixed'); + this.get = this.getFixed; + } + return this.get(min, max); + } +}; + +// ---------------------------------------------------------------------------------------------------------------- +// Detect the netdata server + +// http://stackoverflow.com/questions/984510/what-is-my-script-src-url +// http://stackoverflow.com/questions/6941533/get-protocol-domain-and-port-from-url +NETDATA._scriptSource = function () { + let script = null; + + if (typeof document.currentScript !== 'undefined') { + script = document.currentScript; + } else { + const all_scripts = document.getElementsByTagName('script'); + script = all_scripts[all_scripts.length - 1]; + } + + if (typeof script.getAttribute.length !== 'undefined') { + script = script.src; + } else { + script = script.getAttribute('src', -1); + } + + return script; +}; diff --git a/web/gui/src/dashboard.js/xss.js b/web/gui/src/dashboard.js/xss.js new file mode 100644 index 0000000..fa66f34 --- /dev/null +++ b/web/gui/src/dashboard.js/xss.js @@ -0,0 +1,84 @@ +// ---------------------------------------------------------------------------------------------------------------- +// XSS checks + +NETDATA.xss = { + enabled: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS, + enabled_for_data: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS, + + string: function (s) { + return s.toString() + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }, + + object: function (name, obj, ignore_regex) { + if (typeof ignore_regex !== 'undefined' && ignore_regex.test(name)) { + // console.log('XSS: ignoring "' + name + '"'); + return obj; + } + + switch (typeof(obj)) { + case 'string': + const ret = this.string(obj); + if (ret !== obj) { + console.log('XSS protection changed string ' + name + ' from "' + obj + '" to "' + ret + '"'); + } + return ret; + + case 'object': + if (obj === null) { + return obj; + } + + if (Array.isArray(obj)) { + // console.log('checking array "' + name + '"'); + + let len = obj.length; + while (len--) { + obj[len] = this.object(name + '[' + len + ']', obj[len], ignore_regex); + } + } else { + // console.log('checking object "' + name + '"'); + + for (var i in obj) { + if (obj.hasOwnProperty(i) === false) { + continue; + } + if (this.string(i) !== i) { + console.log('XSS protection removed invalid object member "' + name + '.' + i + '"'); + delete obj[i]; + } else { + obj[i] = this.object(name + '.' + i, obj[i], ignore_regex); + } + } + } + return obj; + + default: + return obj; + } + }, + + checkOptional: function (name, obj, ignore_regex) { + if (this.enabled) { + //console.log('XSS: checking optional "' + name + '"...'); + return this.object(name, obj, ignore_regex); + } + return obj; + }, + + checkAlways: function (name, obj, ignore_regex) { + //console.log('XSS: checking always "' + name + '"...'); + return this.object(name, obj, ignore_regex); + }, + + checkData: function (name, obj, ignore_regex) { + if (this.enabled_for_data) { + //console.log('XSS: checking data "' + name + '"...'); + return this.object(name, obj, ignore_regex); + } + return obj; + } +}; diff --git a/web/gui/tv.html b/web/gui/tv.html new file mode 100644 index 0000000..bd549be --- /dev/null +++ b/web/gui/tv.html @@ -0,0 +1,279 @@ +<!DOCTYPE html> +<!-- SPDX-License-Identifier: GPL-3.0-or-later --> +<html lang="en"> +<head> + <title>NetData TV Dashboard</title> + <meta name="application-name" content="netdata"> + + <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> + + <meta property="og:locale" content="en_US" /> + <meta property="og:image" content="https://cloud.githubusercontent.com/assets/2662304/22945737/e98cd0c6-f2fd-11e6-96f1-5501934b0955.png"/> + <meta property="og:url" content="http://my-netdata.io/"/> + <meta property="og:type" content="website"/> + <meta property="og:site_name" content="netdata"/> + <meta property="og:title" content="netdata - real-time performance monitoring, done right!"/> + <meta property="og:description" content="Stunning real-time dashboards, blazingly fast and extremely interactive. Zero configuration, zero dependencies, zero maintenance." /> + +</head> +<script> +// this section has to appear before loading dashboard.js + +// Select a theme. +// uncomment on of the two themes: + +// var netdataTheme = 'default'; // this is white +var netdataTheme = 'slate'; // this is dark + + +// Set the default netdata server. +// on charts without a 'data-host', this one will be used. +// the default is the server that dashboard.js is downloaded from. + +// var netdataServer = 'http://my.server:19999/'; +</script> + +<!-- + Load dashboard.js + + to host this HTML file on your web server, + you have to load dashboard.js from the netdata server. + + So, pick one the two below + If you pick the first, set the server name/IP. + + The second assumes you host this file on /usr/share/netdata/web + and that you have chown it to be owned by netdata:netdata +--> +<!-- <script type="text/javascript" src="http://my.server:19999/dashboard.js"></script> --> +<script type="text/javascript" src="dashboard.js?v20170724-7"></script> + +<script> +// Set options for TV operation +// This has to be done, after dashboard.js is loaded + +// destroy charts not shown (lowers memory on the browser) +NETDATA.options.current.destroy_on_hide = true; + +// set this to false, to always show all dimensions +NETDATA.options.current.eliminate_zero_dimensions = true; + +// lower the pressure on this browser +NETDATA.options.current.concurrent_refreshes = false; + +// if the tv browser is too slow (a pi?) +// set this to false +NETDATA.options.current.parallel_refresher = true; + +// always update the charts, even if focus is lost +// NETDATA.options.current.stop_updates_when_focus_is_lost = false; + +// Since you may render charts from many servers and any of them may +// become offline for some time, the charts will break. +// This will reload the page every RELOAD_EVERY minutes + +var RELOAD_EVERY = 5; +setTimeout(function(){ + location.reload(); +}, RELOAD_EVERY * 60 * 1000); + +</script> +<body> + +<div style="width: 100%; text-align: center; display: inline-block;"> + + <div style="width: 100%; height: 24vh; text-align: center; display: inline-block;"> + <div style="width: 100%; height: 15px; text-align: center; display: inline-block;"> + <b>CPU On both servers</b> + </div> + <div style="width: 100%; height: calc(100% - 15px); text-align: center; display: inline-block;"> + <br/> + <div data-netdata="system.cpu" + data-host="http://registry.my-netdata.io" + data-title="CPU usage of registry.my-netdata.io" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + <div data-netdata="system.cpu" + data-title="CPU usage of your netdata server" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + data-dygraph-valuerange="[0, 100]" + ></div> + </div> + </div> + + + <div style="width: 100%; height: 24vh; text-align: center; display: inline-block;"> + <div style="width: 100%; height: 15px; text-align: center; display: inline-block;"> + <b>Disk I/O on both servers</b> + </div> + <div style="width: 100%; height: calc(100% - 15px); text-align: center; display: inline-block;"> + <div data-netdata="system.io" + data-host="http://registry.my-netdata.io" + data-common-max="io" + data-common-min="io" + data-title="I/O on registry.my-netdata.io" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + ></div> + <div data-netdata="system.io" + data-title="I/O on your netdata server" + data-common-max="io" + data-common-min="io" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + ></div> + </div> + </div> + + + <div style="width: 100%; height: 24vh; text-align: center; display: inline-block;"> + <div style="width: 100%; height: 15px; text-align: center; display: inline-block;"> + <b>IPv4 traffic on both servers</b> + </div> + <div style="width: 100%; height: calc(100% - 15px); text-align: center; display: inline-block;"> + <div data-netdata="system.net" + data-host="http://registry.my-netdata.io" + data-common-max="traffic" + data-common-min="traffic" + data-title="Network traffic on registry.my-netdata.io" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + ></div> + <div data-netdata="system.net" + data-title="Network traffic on your netdata server" + data-common-max="traffic" + data-common-min="traffic" + data-chart-library="dygraph" + data-width="49%" + data-height="100%" + data-after="-300" + ></div> + </div> + </div> + + <div style="width: 100%; height: 23vh; text-align: center; display: inline-block;"> + <div style="width: 100%; height: 15px; text-align: center; display: inline-block;"> + <b>Netdata statistics on both servers</b> + </div> + <div style="width: 100%; max-height: calc(100% - 15px); text-align: center; display: inline-block;"> + <div style="width: 49%; height:100%; align: center; display: inline-block;"> + registry.my-netdata.io + <br/> + <div data-netdata="netdata.requests" + data-host="http://registry.my-netdata.io" + data-common-max="netdata-requests" + data-decimal-digits="0" + data-title="Chart Refreshes/s" + data-chart-library="gauge" + data-width="20%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + <div data-netdata="netdata.clients" + data-host="http://registry.my-netdata.io" + data-common-max="netdata-clients" + data-decimal-digits="0" + data-title="Sockets" + data-chart-library="gauge" + data-width="20%" + data-height="100%" + data-after="-300" + data-points="300" + data-colors="#AA5500" + ></div> + <div data-netdata="netdata.net" + data-dimensions="in" + data-common-max="netdata-net-in" + data-decimal-digits="0" + data-host="http://registry.my-netdata.io" + data-title="Requests Traffic" + data-chart-library="easypiechart" + data-width="15%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + <div data-netdata="netdata.net" + data-dimensions="out" + data-common-max="netdata-net-out" + data-decimal-digits="0" + data-host="http://registry.my-netdata.io" + data-title="Chart Data Traffic" + data-chart-library="easypiechart" + data-width="15%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + </div> + <div style="width: 49%; height:100%; align: center; display: inline-block;"> + your netdata server + <br/> + <div data-netdata="netdata.requests" + data-title="Chart Refreshes/s" + data-common-max="netdata-requests" + data-decimal-digits="0" + data-chart-library="gauge" + data-width="20%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + <div data-netdata="netdata.clients" + data-common-max="netdata-clients" + data-decimal-digits="0" + data-title="Sockets" + data-chart-library="gauge" + data-width="20%" + data-height="100%" + data-after="-300" + data-points="300" + data-colors="#AA5500" + ></div> + <div data-netdata="netdata.net" + data-dimensions="in" + data-common-max="netdata-net-in" + data-decimal-digits="0" + data-title="Requests Traffic" + data-chart-library="easypiechart" + data-width="15%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + <div data-netdata="netdata.net" + data-dimensions="out" + data-common-max="netdata-net-out" + data-decimal-digits="0" + data-title="Chart Data Traffic" + data-chart-library="easypiechart" + data-width="15%" + data-height="100%" + data-after="-300" + data-points="300" + ></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/web/server/Makefile.am b/web/server/Makefile.am new file mode 100644 index 0000000..5860a5c --- /dev/null +++ b/web/server/Makefile.am @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + static \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/server/README.md b/web/server/README.md new file mode 100644 index 0000000..7d74c18 --- /dev/null +++ b/web/server/README.md @@ -0,0 +1,123 @@ +# Web server + +The Netdata web server runs as `static-threaded`, i.e. with a fixed, configurable number of threads. +It uses non-blocking I/O and respects the `keep-alive` HTTP header to serve multiple HTTP requests via the same connection. + +## Configuration + +You can disable the web server by editing `netdata.conf` and setting: + +``` +[web] + mode = none +``` + +With the web server enabled, you can control the number of threads and sockets with the following settings: + +``` +[web] + web server threads = 4 + web server max sockets = 512 +``` + +The default number of processor threads is `min(cpu cores, 6)`. + +The `web server max sockets` setting is automatically adjusted to 50% of the max number of open files netdata is allowed to use (via `/etc/security/limits.conf` or systemd), to allow enough file descriptors to be available for data collection. + +### Binding netdata to multiple ports + +Netdata can bind to multiple IPs and ports, offering access to different services on each. Up to 100 sockets can be used (you can increase it at compile time with `CFLAGS="-DMAX_LISTEN_FDS=200" ./netdata-installer.sh ...`). + +The ports to bind are controlled via `[web].bind to`, like this: + +``` +[web] + default port = 19999 + bind to = 127.0.0.1=dashboard 10.1.1.1:19998=management|netdata.conf hostname:19997=badges [::]:19996=streaming localhost:19995=registry *:http=dashboard unix:/tmp/netdata.sock +``` + +Using the above, netdata will bind to: + +- IPv4 127.0.0.1 at port 19999 (port was used from `default port`). Only the UI (dashboard) and the read API will be accessible on this port. +- IPv4 10.1.1.1 at port 19998. The management API and netdata.conf will be accessible on this port. +- All the IPs `hostname` resolves to (both IPv4 and IPv6 depending on the resolved IPs) at port 19997. Only badges will be accessible on this port. +- All IPv6 IPs at port 19996. Only metric streaming requests from other netdata agents will be accepted on this port. +- All the IPs `localhost` resolves to (both IPv4 and IPv6 depending the resolved IPs) at port 19996. This port will only accept registry API requests. +- All IPv4 and IPv6 IPs at port `http` as set in `/etc/services`. Only the UI (dashboard) and the read API will be accessible on this port. +- Unix domain socket `/tmp/netdata.sock`. All requests are serviceable on this socket. + +The option `[web].default port` is used when an entries in `[web].bind to` do not specify a port. + +Note that the access permissions specified with the `=request type|request type|...` format are available from version 1.12 onwards. +As shown in the example above, these permissions are optional, with the default being to permit all request types on the specified port. +The request types are strings identical to the `allow X from` directives of the access lists, i.e. `dashboard`, `streaming`, `registry`, `netdata.conf`, `badges` and `management`. +The access lists themselves and the general setting `allow connections from` in the next section are applied regardless of the ports that are configured to provide these services. +The API requests are serviced as follows: +- `dashboard` gives access to the UI, the read API and badges API calls. +- `badges` gives access only to the badges API calls. +- `management` gives access only to the management API calls. + +### Access lists + +Netdata supports access lists in `netdata.conf`: + +``` +[web] + allow connections from = localhost * + allow dashboard from = localhost * + allow badges from = * + allow streaming from = * + allow netdata.conf from = localhost fd* 10.* 192.168.* 172.16.* 172.17.* 172.18.* 172.19.* 172.20.* 172.21.* 172.22.* 172.23.* 172.24.* 172.25.* 172.26.* 172.27.* 172.28.* 172.29.* 172.30.* 172.31.* + allow management from = localhost +``` + +`*` does string matches on the IPs of the clients. + +- `allow connections from` matches anyone that connects on the netdata port(s). + So, if someone is not allowed, it will be connected and disconnected immediately, without reading even + a single byte from its connection. This is a global settings with higher priority to any of the ones below. + +- `allow dashboard from` receives the request and examines if it is a static dashboard file or an API call the + dashboards do. + +- `allow badges from` checks if the API request is for a badge. Badges are not matched by `allow dashboard from`. + +- `allow streaming from` checks if the slave willing to stream metrics to this netdata is allowed. + This can be controlled per API KEY and MACHINE GUID in [stream.conf](../../streaming/stream.conf). + The setting in `netdata.conf` is checked before the ones in [stream.conf](../../streaming/stream.conf). + +- `allow netdata.conf from` checks the IP to allow `http://netdata.host:19999/netdata.conf`. + The IPs listed are all the private IPv4 addresses, including link local IPv6 addresses. Keep in mind that connections to netdata API ports are filtered by `allow connections from`. So, IPs allowed by `allow netdata.conf from` should also be allowed by `allow connections from`. + +- `allow management from` checks the IPs to allow API management calls. Management via the API is currently supported for [health](../api/health/#health-management-api) + +### Other netdata.conf [web] section options +setting | default | info +:------:|:-------:|:---- +ses max window | `15` | See [single exponential smoothing](../api/queries/des/) +des max window | `15` | See [double exponential smoothing](../api/queries/des/) +listen backlog | `4096` | The port backlog. Check `man 2 listen`. +web files owner | `netdata` | The user that owns the web static files. Netdata will refuse to serve a file that is not owned by this user, even if it has read access to that file. If the user given is not found, netdata will only serve files owned by user given in `run as user`. +web files group | `netdata` | If this is set, Netdata will check if the file is owned by this group and refuse to serve the file if it's not. +disconnect idle clients after seconds | `60` | The time in seconds to disconnect web clients after being totally idle. +timeout for first request | `60` | How long to wait for a client to send a request before closing the socket. Prevents slow request attacks. +accept a streaming request every seconds | `0` | Can be used to set a limit on how often a master Netdata server will accept streaming requests from the slaves in a [streaming and replication setup](../../streaming) +respect do not track policy | `no` | If set to `yes`, will respect the client's browser preferences on storing cookies. +x-frame-options response header | | [Avoid clickjacking attacks, by ensuring that the content is not embedded into other sites](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options). +enable gzip compression | `yes` | When set to `yes`, netdata web responses will be GZIP compressed, if the web client accepts such responses. +gzip compression strategy | `default` | Valid strategies are `default`, `filtered`, `huffman only`, `rle` and `fixed` +gzip compression level | `3` | Valid levels are 1 (fastest) to 9 (best ratio) + + +## DDoS protection + +If you publish your netdata to the internet, you may want to apply some protection against DDoS: + +1. Use the `static-threaded` web server (it is the default) +2. Use reasonable `[web].web server max sockets` (the default is) +3. Don't use all your cpu cores for netdata (lower `[web].web server threads`) +4. Run netdata with a low process scheduling priority (the default is the lowest) +5. If possible, proxy netdata via a full featured web server (nginx, apache, etc) + + +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fserver%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/server/static/Makefile.am b/web/server/static/Makefile.am new file mode 100644 index 0000000..90cc9ca --- /dev/null +++ b/web/server/static/Makefile.am @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +AUTOMAKE_OPTIONS = subdir-objects +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +SUBDIRS = \ + $(NULL) + +dist_noinst_DATA = \ + README.md \ + $(NULL) diff --git a/web/server/static/README.md b/web/server/static/README.md new file mode 100644 index 0000000..653b364 --- /dev/null +++ b/web/server/static/README.md @@ -0,0 +1,10 @@ +# `static-threaded` web server + +The `static-threaded` web server spawns a fixed number of threads. +All the threads are concurrently listening for web requests on the same sockets. +The kernel distributes the incoming requests to them. + +Each thread uses non-blocking I/O so it can serve any number of web requests in parallel. + +This web server respects the `keep-alive` HTTP header to serve multiple HTTP requests via the same connection. +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fweb%2Fserver%2Fstatic%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]() diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c new file mode 100644 index 0000000..56e726b --- /dev/null +++ b/web/server/static/static-threaded.c @@ -0,0 +1,437 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#define WEB_SERVER_INTERNALS 1 +#include "static-threaded.h" + +int web_client_timeout = DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS; +int web_client_first_request_timeout = DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST; +long web_client_streaming_rate_t = 0L; + +// ---------------------------------------------------------------------------- +// high level web clients connection management + +static struct web_client *web_client_create_on_fd(int fd, const char *client_ip, const char *client_port, int port_acl) { + struct web_client *w; + + w = web_client_get_from_cache_or_allocate(); + w->ifd = w->ofd = fd; + + strncpyz(w->client_ip, client_ip, sizeof(w->client_ip) - 1); + strncpyz(w->client_port, client_port, sizeof(w->client_port) - 1); + + if(unlikely(!*w->client_ip)) strcpy(w->client_ip, "-"); + if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); + w->port_acl = port_acl; + + web_client_initialize_connection(w); + return(w); +} + +// -------------------------------------------------------------------------------------- +// the main socket listener - STATIC-THREADED + +struct web_server_static_threaded_worker { + netdata_thread_t thread; + + int id; + int running; + + size_t max_sockets; + + volatile size_t connected; + volatile size_t disconnected; + volatile size_t receptions; + volatile size_t sends; + volatile size_t max_concurrent; + + volatile size_t files_read; + volatile size_t file_reads; +}; + +static long long static_threaded_workers_count = 1; + +static struct web_server_static_threaded_worker *static_workers_private_data = NULL; +static __thread struct web_server_static_threaded_worker *worker_private = NULL; + +// ---------------------------------------------------------------------------- + +static inline int web_server_check_client_status(struct web_client *w) { + if(unlikely(web_client_check_dead(w) || (!web_client_has_wait_receive(w) && !web_client_has_wait_send(w)))) + return -1; + + return 0; +} + +// ---------------------------------------------------------------------------- +// web server files + +static void *web_server_file_add_callback(POLLINFO *pi, short int *events, void *data) { + struct web_client *w = (struct web_client *)data; + + worker_private->files_read++; + + debug(D_WEB_CLIENT, "%llu: ADDED FILE READ ON FD %d", w->id, pi->fd); + *events = POLLIN; + pi->data = w; + return w; +} + +static void web_werver_file_del_callback(POLLINFO *pi) { + struct web_client *w = (struct web_client *)pi->data; + debug(D_WEB_CLIENT, "%llu: RELEASE FILE READ ON FD %d", w->id, pi->fd); + + w->pollinfo_filecopy_slot = 0; + + if(unlikely(!w->pollinfo_slot)) { + debug(D_WEB_CLIENT, "%llu: CROSS WEB CLIENT CLEANUP (iFD %d, oFD %d)", w->id, pi->fd, w->ofd); + web_client_release(w); + } +} + +static int web_server_file_read_callback(POLLINFO *pi, short int *events) { + struct web_client *w = (struct web_client *)pi->data; + + // if there is no POLLINFO linked to this, it means the client disconnected + // stop the file reading too + if(unlikely(!w->pollinfo_slot)) { + debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON CLOSED WEB CLIENT", w->id, pi->fd); + return -1; + } + + if(unlikely(w->mode != WEB_CLIENT_MODE_FILECOPY || w->ifd == w->ofd)) { + debug(D_WEB_CLIENT, "%llu: PREVENTED ATTEMPT TO READ FILE ON FD %d, ON NON-FILECOPY WEB CLIENT", w->id, pi->fd); + return -1; + } + + debug(D_WEB_CLIENT, "%llu: READING FILE ON FD %d", w->id, pi->fd); + + worker_private->file_reads++; + ssize_t ret = unlikely(web_client_read_file(w)); + + if(likely(web_client_has_wait_send(w))) { + POLLJOB *p = pi->p; // our POLLJOB + POLLINFO *wpi = pollinfo_from_slot(p, w->pollinfo_slot); // POLLINFO of the client socket + + debug(D_WEB_CLIENT, "%llu: SIGNALING W TO SEND (iFD %d, oFD %d)", w->id, pi->fd, wpi->fd); + p->fds[wpi->slot].events |= POLLOUT; + } + + if(unlikely(ret <= 0 || w->ifd == w->ofd)) { + debug(D_WEB_CLIENT, "%llu: DONE READING FILE ON FD %d", w->id, pi->fd); + return -1; + } + + *events = POLLIN; + return 0; +} + +static int web_server_file_write_callback(POLLINFO *pi, short int *events) { + (void)pi; + (void)events; + + error("Writing to web files is not supported!"); + + return -1; +} + +// ---------------------------------------------------------------------------- +// web server clients + +static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data) { + (void)data; + + worker_private->connected++; + + size_t concurrent = worker_private->connected - worker_private->disconnected; + if(unlikely(concurrent > worker_private->max_concurrent)) + worker_private->max_concurrent = concurrent; + + *events = POLLIN; + + debug(D_WEB_CLIENT_ACCESS, "LISTENER on %d: new connection.", pi->fd); + struct web_client *w = web_client_create_on_fd(pi->fd, pi->client_ip, pi->client_port, pi->port_acl); + w->pollinfo_slot = pi->slot; + + if(unlikely(pi->socktype == AF_UNIX)) + web_client_set_unix(w); + else + web_client_set_tcp(w); + + debug(D_WEB_CLIENT, "%llu: ADDED CLIENT FD %d", w->id, pi->fd); + return w; +} + +// TCP client disconnected +static void web_server_del_callback(POLLINFO *pi) { + worker_private->disconnected++; + + struct web_client *w = (struct web_client *)pi->data; + + w->pollinfo_slot = 0; + if(unlikely(w->pollinfo_filecopy_slot)) { + POLLINFO *fpi = pollinfo_from_slot(pi->p, w->pollinfo_filecopy_slot); // POLLINFO of the client socket + (void)fpi; + + debug(D_WEB_CLIENT, "%llu: THE CLIENT WILL BE FRED BY READING FILE JOB ON FD %d", w->id, fpi->fd); + } + else { + if(web_client_flag_check(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET)) + pi->flags |= POLLINFO_FLAG_DONT_CLOSE; + + debug(D_WEB_CLIENT, "%llu: CLOSING CLIENT FD %d", w->id, pi->fd); + web_client_release(w); + } +} + +static int web_server_rcv_callback(POLLINFO *pi, short int *events) { + worker_private->receptions++; + + struct web_client *w = (struct web_client *)pi->data; + int fd = pi->fd; + + if(unlikely(web_client_receive(w) < 0)) + return -1; + + debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd); + web_client_process_request(w); + + if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { + if(w->pollinfo_filecopy_slot == 0) { + debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd); + + if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) { + // add a new socket to poll_events, with the same + debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd); + + POLLINFO *fpi = poll_add_fd( + pi->p + , w->ifd + , pi->port_acl + , 0 + , POLLINFO_FLAG_CLIENT_SOCKET + , "FILENAME" + , "" + , web_server_file_add_callback + , web_werver_file_del_callback + , web_server_file_read_callback + , web_server_file_write_callback + , (void *) w + ); + + if(fpi) + w->pollinfo_filecopy_slot = fpi->slot; + else { + error("Failed to add filecopy fd. Closing client."); + return -1; + } + } + } + } + else { + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + *events |= POLLIN; + } + + if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) + *events |= POLLOUT; + + return web_server_check_client_status(w); +} + +static int web_server_snd_callback(POLLINFO *pi, short int *events) { + worker_private->sends++; + + struct web_client *w = (struct web_client *)pi->data; + int fd = pi->fd; + + debug(D_WEB_CLIENT, "%llu: sending data on fd %d.", w->id, fd); + + if(unlikely(web_client_send(w) < 0)) + return -1; + + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + *events |= POLLIN; + + if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) + *events |= POLLOUT; + + return web_server_check_client_status(w); +} + +static void web_server_tmr_callback(void *timer_data) { + worker_private = (struct web_server_static_threaded_worker *)timer_data; + + static __thread RRDSET *st = NULL; + static __thread RRDDIM *rd_user = NULL, *rd_system = NULL; + + if(unlikely(!st)) { + char id[100 + 1]; + char title[100 + 1]; + + snprintfz(id, 100, "web_thread%d_cpu", worker_private->id + 1); + snprintfz(title, 100, "NetData web server thread No %d CPU usage", worker_private->id + 1); + + st = rrdset_create_localhost( + "netdata" + , id + , NULL + , "web" + , "netdata.web_cpu" + , title + , "milliseconds/s" + , "web" + , "stats" + , 132000 + worker_private->id + , default_rrd_update_every + , RRDSET_TYPE_STACKED + ); + + rd_user = rrddim_add(st, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + rd_system = rrddim_add(st, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL); + } + else + rrdset_next(st); + + struct rusage rusage; + getrusage(RUSAGE_THREAD, &rusage); + rrddim_set_by_pointer(st, rd_user, rusage.ru_utime.tv_sec * 1000000ULL + rusage.ru_utime.tv_usec); + rrddim_set_by_pointer(st, rd_system, rusage.ru_stime.tv_sec * 1000000ULL + rusage.ru_stime.tv_usec); + rrdset_done(st); +} + +// ---------------------------------------------------------------------------- +// web server worker thread + +static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) { + worker_private = (struct web_server_static_threaded_worker *)ptr; + + info("freeing local web clients cache..."); + web_client_cache_destroy(); + + info("stopped after %zu connects, %zu disconnects (max concurrent %zu), %zu receptions and %zu sends", + worker_private->connected, + worker_private->disconnected, + worker_private->max_concurrent, + worker_private->receptions, + worker_private->sends + ); + + worker_private->running = 0; +} + +void *socket_listen_main_static_threaded_worker(void *ptr) { + worker_private = (struct web_server_static_threaded_worker *)ptr; + worker_private->running = 1; + + netdata_thread_cleanup_push(socket_listen_main_static_threaded_worker_cleanup, ptr); + + poll_events(&api_sockets + , web_server_add_callback + , web_server_del_callback + , web_server_rcv_callback + , web_server_snd_callback + , web_server_tmr_callback + , web_allow_connections_from + , NULL + , web_client_first_request_timeout + , web_client_timeout + , default_rrd_update_every * 1000 // timer_milliseconds + , ptr // timer_data + , worker_private->max_sockets + ); + + netdata_thread_cleanup_pop(1); + return NULL; +} + + +// ---------------------------------------------------------------------------- +// web server main thread - also becomes a worker + +static void socket_listen_main_static_threaded_cleanup(void *ptr) { + struct netdata_static_thread *static_thread = (struct netdata_static_thread *)ptr; + static_thread->enabled = NETDATA_MAIN_THREAD_EXITING; + + int i, found = 0; + usec_t max = 2 * USEC_PER_SEC, step = 50000; + + // we start from 1, - 0 is self + for(i = 1; i < static_threaded_workers_count; i++) { + if(static_workers_private_data[i].running) { + found++; + info("stopping worker %d", i + 1); + netdata_thread_cancel(static_workers_private_data[i].thread); + } + else + info("found stopped worker %d", i + 1); + } + + while(found && max > 0) { + max -= step; + info("Waiting %d static web threads to finish...", found); + sleep_usec(step); + found = 0; + + // we start from 1, - 0 is self + for(i = 1; i < static_threaded_workers_count; i++) { + if (static_workers_private_data[i].running) + found++; + } + } + + if(found) + error("%d static web threads are taking too long to finish. Giving up.", found); + + info("closing all web server sockets..."); + listen_sockets_close(&api_sockets); + + info("all static web threads stopped."); + static_thread->enabled = NETDATA_MAIN_THREAD_EXITED; +} + +void *socket_listen_main_static_threaded(void *ptr) { + netdata_thread_cleanup_push(socket_listen_main_static_threaded_cleanup, ptr); + web_server_mode = WEB_SERVER_MODE_STATIC_THREADED; + + if(!api_sockets.opened) + fatal("LISTENER: no listen sockets available."); + + // 6 threads is the optimal value + // since 6 are the parallel connections browsers will do + // so, if the machine has more CPUs, avoid using resources unnecessarily + int def_thread_count = (processors > 6)?6:processors; + + if (!strcmp(config_get(CONFIG_SECTION_WEB, "mode", ""),"single-threaded")) { + info("Running web server with one thread, because mode is single-threaded"); + config_set(CONFIG_SECTION_WEB, "mode", "static-threaded"); + def_thread_count = 1; + } + static_threaded_workers_count = config_get_number(CONFIG_SECTION_WEB, "web server threads", def_thread_count); + + if(static_threaded_workers_count < 1) static_threaded_workers_count = 1; + + size_t max_sockets = (size_t)config_get_number(CONFIG_SECTION_WEB, "web server max sockets", (long long int)(rlimit_nofile.rlim_cur / 2)); + + static_workers_private_data = callocz((size_t)static_threaded_workers_count, sizeof(struct web_server_static_threaded_worker)); + + web_server_is_multithreaded = (static_threaded_workers_count > 1); + + int i; + for(i = 1; i < static_threaded_workers_count; i++) { + static_workers_private_data[i].id = i; + static_workers_private_data[i].max_sockets = max_sockets / static_threaded_workers_count; + + char tag[50 + 1]; + snprintfz(tag, 50, "WEB_SERVER[static%d]", i+1); + + info("starting worker %d", i+1); + netdata_thread_create(&static_workers_private_data[i].thread, tag, NETDATA_THREAD_OPTION_DEFAULT, socket_listen_main_static_threaded_worker, (void *)&static_workers_private_data[i]); + } + + // and the main one + static_workers_private_data[0].max_sockets = max_sockets / static_threaded_workers_count; + socket_listen_main_static_threaded_worker((void *)&static_workers_private_data[0]); + + netdata_thread_cleanup_pop(1); + return NULL; +} diff --git a/web/server/static/static-threaded.h b/web/server/static/static-threaded.h new file mode 100644 index 0000000..5f4862e --- /dev/null +++ b/web/server/static/static-threaded.h @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_SERVER_STATIC_THREADED_H +#define NETDATA_WEB_SERVER_STATIC_THREADED_H + +#include "web/server/web_server.h" + +extern void *socket_listen_main_static_threaded(void *ptr); + +#endif //NETDATA_WEB_SERVER_STATIC_THREADED_H diff --git a/web/server/web_client.c b/web/server/web_client.c new file mode 100644 index 0000000..4e34ae3 --- /dev/null +++ b/web/server/web_client.c @@ -0,0 +1,1691 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "web_client.h" + +// this is an async I/O implementation of the web server request parser +// it is used by all netdata web servers + +int respect_web_browser_do_not_track_policy = 0; +char *web_x_frame_options = NULL; + +#ifdef NETDATA_WITH_ZLIB +int web_enable_gzip = 1, web_gzip_level = 3, web_gzip_strategy = Z_DEFAULT_STRATEGY; +#endif /* NETDATA_WITH_ZLIB */ + +inline int web_client_permission_denied(struct web_client *w) { + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "You are not allowed to access this resource."); + w->response.code = 403; + return 403; +} + +static inline int web_client_crock_socket(struct web_client *w) { +#ifdef TCP_CORK + if(likely(web_client_is_corkable(w) && !w->tcp_cork && w->ofd != -1)) { + w->tcp_cork = 1; + if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) { + error("%llu: failed to enable TCP_CORK on socket.", w->id); + + w->tcp_cork = 0; + return -1; + } + } +#else + (void)w; +#endif /* TCP_CORK */ + + return 0; +} + +static inline int web_client_uncrock_socket(struct web_client *w) { +#ifdef TCP_CORK + if(likely(w->tcp_cork && w->ofd != -1)) { + w->tcp_cork = 0; + if(unlikely(setsockopt(w->ofd, IPPROTO_TCP, TCP_CORK, (char *) &w->tcp_cork, sizeof(int)) != 0)) { + error("%llu: failed to disable TCP_CORK on socket.", w->id); + w->tcp_cork = 1; + return -1; + } + } +#else + (void)w; +#endif /* TCP_CORK */ + + return 0; +} + +static inline char *strip_control_characters(char *url) { + char *s = url; + if(!s) return ""; + + if(iscntrl(*s)) *s = ' '; + while(*++s) { + if(iscntrl(*s)) *s = ' '; + } + + return url; +} + +void web_client_request_done(struct web_client *w) { + web_client_uncrock_socket(w); + + debug(D_WEB_CLIENT, "%llu: Resetting client.", w->id); + + if(likely(w->last_url[0])) { + struct timeval tv; + now_realtime_timeval(&tv); + + size_t size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->response.rlen:w->response.data->len; + size_t sent = size; +#ifdef NETDATA_WITH_ZLIB + if(likely(w->response.zoutput)) sent = (size_t)w->response.zstream.total_out; +#endif + + // -------------------------------------------------------------------- + // global statistics + + finished_web_request_statistics(dt_usec(&tv, &w->tv_in), + w->stats_received_bytes, + w->stats_sent_bytes, + size, + sent); + + w->stats_received_bytes = 0; + w->stats_sent_bytes = 0; + + + // -------------------------------------------------------------------- + + const char *mode; + switch(w->mode) { + case WEB_CLIENT_MODE_FILECOPY: + mode = "FILECOPY"; + break; + + case WEB_CLIENT_MODE_OPTIONS: + mode = "OPTIONS"; + break; + + case WEB_CLIENT_MODE_STREAM: + mode = "STREAM"; + break; + + case WEB_CLIENT_MODE_NORMAL: + mode = "DATA"; + break; + + default: + mode = "UNKNOWN"; + break; + } + + // access log + log_access("%llu: %d '[%s]:%s' '%s' (sent/all = %zu/%zu bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %d '%s'", + w->id + , gettid() + , w->client_ip + , w->client_port + , mode + , sent + , size + , -((size > 0) ? ((size - sent) / (double) size * 100.0) : 0.0) + , dt_usec(&w->tv_ready, &w->tv_in) / 1000.0 + , dt_usec(&tv, &w->tv_ready) / 1000.0 + , dt_usec(&tv, &w->tv_in) / 1000.0 + , w->response.code + , strip_control_characters(w->last_url) + ); + } + + if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { + if(w->ifd != w->ofd) { + debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd); + + if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) { + if (w->ifd != -1) close(w->ifd); + } + + w->ifd = w->ofd; + } + } + + w->last_url[0] = '\0'; + w->cookie1[0] = '\0'; + w->cookie2[0] = '\0'; + w->origin[0] = '*'; + w->origin[1] = '\0'; + + freez(w->user_agent); w->user_agent = NULL; + if (w->auth_bearer_token) { + freez(w->auth_bearer_token); + w->auth_bearer_token = NULL; + } + + w->mode = WEB_CLIENT_MODE_NORMAL; + + w->tcp_cork = 0; + web_client_disable_donottrack(w); + web_client_disable_tracking_required(w); + web_client_disable_keepalive(w); + w->decoded_url[0] = '\0'; + + buffer_reset(w->response.header_output); + buffer_reset(w->response.header); + buffer_reset(w->response.data); + w->response.rlen = 0; + w->response.sent = 0; + w->response.code = 0; + + w->header_parse_tries = 0; + w->header_parse_last_size = 0; + + web_client_enable_wait_receive(w); + web_client_disable_wait_send(w); + + w->response.zoutput = 0; + + // if we had enabled compression, release it +#ifdef NETDATA_WITH_ZLIB + if(w->response.zinitialized) { + debug(D_DEFLATE, "%llu: Freeing compression resources.", w->id); + deflateEnd(&w->response.zstream); + w->response.zsent = 0; + w->response.zhave = 0; + w->response.zstream.avail_in = 0; + w->response.zstream.avail_out = 0; + w->response.zstream.total_in = 0; + w->response.zstream.total_out = 0; + w->response.zinitialized = 0; + } +#endif // NETDATA_WITH_ZLIB +} + +uid_t web_files_uid(void) { + static char *web_owner = NULL; + static uid_t owner_uid = 0; + + if(unlikely(!web_owner)) { + // getpwuid() is not thread safe, + // but we have called this function once + // while single threaded + struct passwd *pw = getpwuid(geteuid()); + web_owner = config_get(CONFIG_SECTION_WEB, "web files owner", (pw)?(pw->pw_name?pw->pw_name:""):""); + if(!web_owner || !*web_owner) + owner_uid = geteuid(); + else { + // getpwnam() is not thread safe, + // but we have called this function once + // while single threaded + pw = getpwnam(web_owner); + if(!pw) { + error("User '%s' is not present. Ignoring option.", web_owner); + owner_uid = geteuid(); + } + else { + debug(D_WEB_CLIENT, "Web files owner set to %s.", web_owner); + owner_uid = pw->pw_uid; + } + } + } + + return(owner_uid); +} + +gid_t web_files_gid(void) { + static char *web_group = NULL; + static gid_t owner_gid = 0; + + if(unlikely(!web_group)) { + // getgrgid() is not thread safe, + // but we have called this function once + // while single threaded + struct group *gr = getgrgid(getegid()); + web_group = config_get(CONFIG_SECTION_WEB, "web files group", (gr)?(gr->gr_name?gr->gr_name:""):""); + if(!web_group || !*web_group) + owner_gid = getegid(); + else { + // getgrnam() is not thread safe, + // but we have called this function once + // while single threaded + gr = getgrnam(web_group); + if(!gr) { + error("Group '%s' is not present. Ignoring option.", web_group); + owner_gid = getegid(); + } + else { + debug(D_WEB_CLIENT, "Web files group set to %s.", web_group); + owner_gid = gr->gr_gid; + } + } + } + + return(owner_gid); +} + +static struct { + const char *extension; + uint32_t hash; + uint8_t contenttype; +} mime_types[] = { + { "html" , 0 , CT_TEXT_HTML} + , {"js" , 0 , CT_APPLICATION_X_JAVASCRIPT} + , {"css" , 0 , CT_TEXT_CSS} + , {"xml" , 0 , CT_TEXT_XML} + , {"xsl" , 0 , CT_TEXT_XSL} + , {"txt" , 0 , CT_TEXT_PLAIN} + , {"svg" , 0 , CT_IMAGE_SVG_XML} + , {"ttf" , 0 , CT_APPLICATION_X_FONT_TRUETYPE} + , {"otf" , 0 , CT_APPLICATION_X_FONT_OPENTYPE} + , {"woff2", 0 , CT_APPLICATION_FONT_WOFF2} + , {"woff" , 0 , CT_APPLICATION_FONT_WOFF} + , {"eot" , 0 , CT_APPLICATION_VND_MS_FONTOBJ} + , {"png" , 0 , CT_IMAGE_PNG} + , {"jpg" , 0 , CT_IMAGE_JPG} + , {"jpeg" , 0 , CT_IMAGE_JPG} + , {"gif" , 0 , CT_IMAGE_GIF} + , {"bmp" , 0 , CT_IMAGE_BMP} + , {"ico" , 0 , CT_IMAGE_XICON} + , {"icns" , 0 , CT_IMAGE_ICNS} + , { NULL, 0, 0} +}; + +static inline uint8_t contenttype_for_filename(const char *filename) { + // info("checking filename '%s'", filename); + + static int initialized = 0; + int i; + + if(unlikely(!initialized)) { + for (i = 0; mime_types[i].extension; i++) + mime_types[i].hash = simple_hash(mime_types[i].extension); + + initialized = 1; + } + + const char *s = filename, *last_dot = NULL; + + // find the last dot + while(*s) { + if(unlikely(*s == '.')) last_dot = s; + s++; + } + + if(unlikely(!last_dot || !*last_dot || !last_dot[1])) { + // info("no extension for filename '%s'", filename); + return CT_APPLICATION_OCTET_STREAM; + } + last_dot++; + + // info("extension for filename '%s' is '%s'", filename, last_dot); + + uint32_t hash = simple_hash(last_dot); + for(i = 0; mime_types[i].extension ; i++) { + if(unlikely(hash == mime_types[i].hash && !strcmp(last_dot, mime_types[i].extension))) { + // info("matched extension for filename '%s': '%s'", filename, last_dot); + return mime_types[i].contenttype; + } + } + + // info("not matched extension for filename '%s': '%s'", filename, last_dot); + return CT_APPLICATION_OCTET_STREAM; +} + +static inline int access_to_file_is_not_permitted(struct web_client *w, const char *filename) { + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Access to file is not permitted: "); + buffer_strcat_htmlescape(w->response.data, filename); + return 403; +} + +int mysendfile(struct web_client *w, char *filename) { + debug(D_WEB_CLIENT, "%llu: Looking for file '%s/%s'", w->id, netdata_configured_web_dir, filename); + + if(!web_client_can_access_dashboard(w)) + return web_client_permission_denied(w); + + // skip leading slashes + while (*filename == '/') filename++; + + // if the filename contains "strange" characters, refuse to serve it + char *s; + for(s = filename; *s ;s++) { + if( !isalnum(*s) && *s != '/' && *s != '.' && *s != '-' && *s != '_') { + debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_sprintf(w->response.data, "Filename contains invalid characters: "); + buffer_strcat_htmlescape(w->response.data, filename); + return 400; + } + } + + // if the filename contains a .. refuse to serve it + if(strstr(filename, "..") != 0) { + debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Relative filenames are not supported: "); + buffer_strcat_htmlescape(w->response.data, filename); + return 400; + } + + // find the physical file on disk + char webfilename[FILENAME_MAX + 1]; + snprintfz(webfilename, FILENAME_MAX, "%s/%s", netdata_configured_web_dir, filename); + + struct stat statbuf; + int done = 0; + while(!done) { + // check if the file exists + if (lstat(webfilename, &statbuf) != 0) { + debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "File does not exist, or is not accessible: "); + buffer_strcat_htmlescape(w->response.data, webfilename); + return 404; + } + + if ((statbuf.st_mode & S_IFMT) == S_IFDIR) { + snprintfz(webfilename, FILENAME_MAX, "%s/%s/index.html", netdata_configured_web_dir, filename); + continue; + } + + if ((statbuf.st_mode & S_IFMT) != S_IFREG) { + error("%llu: File '%s' is not a regular file. Access Denied.", w->id, webfilename); + return access_to_file_is_not_permitted(w, webfilename); + } + + // check if the file is owned by expected user + if (statbuf.st_uid != web_files_uid()) { + error("%llu: File '%s' is owned by user %u (expected user %u). Access Denied.", w->id, webfilename, statbuf.st_uid, web_files_uid()); + return access_to_file_is_not_permitted(w, webfilename); + } + + // check if the file is owned by expected group + if (statbuf.st_gid != web_files_gid()) { + error("%llu: File '%s' is owned by group %u (expected group %u). Access Denied.", w->id, webfilename, statbuf.st_gid, web_files_gid()); + return access_to_file_is_not_permitted(w, webfilename); + } + + done = 1; + } + + // open the file + w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY); + if(w->ifd == -1) { + w->ifd = w->ofd; + + if(errno == EBUSY || errno == EAGAIN) { + error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_sprintf(w->response.header, "Location: /%s\r\n", filename); + buffer_strcat(w->response.data, "File is currently busy, please try again later: "); + buffer_strcat_htmlescape(w->response.data, webfilename); + return 307; + } + else { + error("%llu: Cannot open file '%s'.", w->id, webfilename); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Cannot open file: "); + buffer_strcat_htmlescape(w->response.data, webfilename); + return 404; + } + } + + sock_setnonblock(w->ifd); + + w->response.data->contenttype = contenttype_for_filename(webfilename); + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, statbuf.st_size, w->ifd, w->ofd); + + w->mode = WEB_CLIENT_MODE_FILECOPY; + web_client_enable_wait_receive(w); + web_client_disable_wait_send(w); + buffer_flush(w->response.data); + buffer_need_bytes(w->response.data, (size_t)statbuf.st_size); + w->response.rlen = (size_t)statbuf.st_size; +#ifdef __APPLE__ + w->response.data->date = statbuf.st_mtimespec.tv_sec; +#else + w->response.data->date = statbuf.st_mtim.tv_sec; +#endif /* __APPLE__ */ + buffer_cacheable(w->response.data); + + return 200; +} + + +#ifdef NETDATA_WITH_ZLIB +void web_client_enable_deflate(struct web_client *w, int gzip) { + if(unlikely(w->response.zinitialized)) { + debug(D_DEFLATE, "%llu: Compression has already be initialized for this client.", w->id); + return; + } + + if(unlikely(w->response.sent)) { + error("%llu: Cannot enable compression in the middle of a conversation.", w->id); + return; + } + + w->response.zstream.zalloc = Z_NULL; + w->response.zstream.zfree = Z_NULL; + w->response.zstream.opaque = Z_NULL; + + w->response.zstream.next_in = (Bytef *)w->response.data->buffer; + w->response.zstream.avail_in = 0; + w->response.zstream.total_in = 0; + + w->response.zstream.next_out = w->response.zbuffer; + w->response.zstream.avail_out = 0; + w->response.zstream.total_out = 0; + + w->response.zstream.zalloc = Z_NULL; + w->response.zstream.zfree = Z_NULL; + w->response.zstream.opaque = Z_NULL; + +// if(deflateInit(&w->response.zstream, Z_DEFAULT_COMPRESSION) != Z_OK) { +// error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id); +// return; +// } + + // Select GZIP compression: windowbits = 15 + 16 = 31 + if(deflateInit2(&w->response.zstream, web_gzip_level, Z_DEFLATED, 15 + ((gzip)?16:0), 8, web_gzip_strategy) != Z_OK) { + error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id); + return; + } + + w->response.zsent = 0; + w->response.zoutput = 1; + w->response.zinitialized = 1; + + debug(D_DEFLATE, "%llu: Initialized compression.", w->id); +} +#endif // NETDATA_WITH_ZLIB + +void buffer_data_options2string(BUFFER *wb, uint32_t options) { + int count = 0; + + if(options & RRDR_OPTION_NONZERO) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "nonzero"); + } + + if(options & RRDR_OPTION_REVERSED) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "flip"); + } + + if(options & RRDR_OPTION_JSON_WRAP) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "jsonwrap"); + } + + if(options & RRDR_OPTION_MIN2MAX) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "min2max"); + } + + if(options & RRDR_OPTION_MILLISECONDS) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "ms"); + } + + if(options & RRDR_OPTION_ABSOLUTE) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "absolute"); + } + + if(options & RRDR_OPTION_SECONDS) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "seconds"); + } + + if(options & RRDR_OPTION_NULL2ZERO) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "null2zero"); + } + + if(options & RRDR_OPTION_OBJECTSROWS) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "objectrows"); + } + + if(options & RRDR_OPTION_GOOGLE_JSON) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "google_json"); + } + + if(options & RRDR_OPTION_PERCENTAGE) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "percentage"); + } + + if(options & RRDR_OPTION_NOT_ALIGNED) { + if(count++) buffer_strcat(wb, " "); + buffer_strcat(wb, "unaligned"); + } +} + +static inline int check_host_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { + if(unlikely(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE)) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "This host does not maintain a database"); + return 400; + } + + return func(host, w, url); +} + +static inline int check_host_and_dashboard_acl_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { + if(!web_client_can_access_dashboard(w)) + return web_client_permission_denied(w); + + return check_host_and_call(host, w, url, func); +} + +static inline int check_host_and_mgmt_acl_and_call(RRDHOST *host, struct web_client *w, char *url, int (*func)(RRDHOST *, struct web_client *, char *)) { + if(!web_client_can_access_mgmt(w)) + return web_client_permission_denied(w); + + return check_host_and_call(host, w, url, func); +} + +int web_client_api_request(RRDHOST *host, struct web_client *w, char *url) +{ + // get the api version + char *tok = mystrsep(&url, "/"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok); + if(strcmp(tok, "v1") == 0) + return web_client_api_request_v1(host, w, url); + else { + buffer_flush(w->response.data); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Unsupported API version: "); + buffer_strcat_htmlescape(w->response.data, tok); + return 404; + } + } + else { + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Which API version?"); + return 400; + } +} + +const char *web_content_type_to_string(uint8_t contenttype) { + switch(contenttype) { + case CT_TEXT_HTML: + return "text/html; charset=utf-8"; + + case CT_APPLICATION_XML: + return "application/xml; charset=utf-8"; + + case CT_APPLICATION_JSON: + return "application/json; charset=utf-8"; + + case CT_APPLICATION_X_JAVASCRIPT: + return "application/x-javascript; charset=utf-8"; + + case CT_TEXT_CSS: + return "text/css; charset=utf-8"; + + case CT_TEXT_XML: + return "text/xml; charset=utf-8"; + + case CT_TEXT_XSL: + return "text/xsl; charset=utf-8"; + + case CT_APPLICATION_OCTET_STREAM: + return "application/octet-stream"; + + case CT_IMAGE_SVG_XML: + return "image/svg+xml"; + + case CT_APPLICATION_X_FONT_TRUETYPE: + return "application/x-font-truetype"; + + case CT_APPLICATION_X_FONT_OPENTYPE: + return "application/x-font-opentype"; + + case CT_APPLICATION_FONT_WOFF: + return "application/font-woff"; + + case CT_APPLICATION_FONT_WOFF2: + return "application/font-woff2"; + + case CT_APPLICATION_VND_MS_FONTOBJ: + return "application/vnd.ms-fontobject"; + + case CT_IMAGE_PNG: + return "image/png"; + + case CT_IMAGE_JPG: + return "image/jpeg"; + + case CT_IMAGE_GIF: + return "image/gif"; + + case CT_IMAGE_XICON: + return "image/x-icon"; + + case CT_IMAGE_BMP: + return "image/bmp"; + + case CT_IMAGE_ICNS: + return "image/icns"; + + case CT_PROMETHEUS: + return "text/plain; version=0.0.4"; + + default: + case CT_TEXT_PLAIN: + return "text/plain; charset=utf-8"; + } +} + + +const char *web_response_code_to_string(int code) { + switch(code) { + case 200: + return "OK"; + + case 307: + return "Temporary Redirect"; + + case 400: + return "Bad Request"; + + case 403: + return "Forbidden"; + + case 404: + return "Not Found"; + + case 412: + return "Preconditions Failed"; + + default: + if(code >= 100 && code < 200) + return "Informational"; + + if(code >= 200 && code < 300) + return "Successful"; + + if(code >= 300 && code < 400) + return "Redirection"; + + if(code >= 400 && code < 500) + return "Bad Request"; + + if(code >= 500 && code < 600) + return "Server Error"; + + return "Undefined Error"; + } +} + +static inline char *http_header_parse(struct web_client *w, char *s, int parse_useragent) { + static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0, hash_useragent = 0, hash_authorization = 0; + + if(unlikely(!hash_origin)) { + hash_origin = simple_uhash("Origin"); + hash_connection = simple_uhash("Connection"); + hash_accept_encoding = simple_uhash("Accept-Encoding"); + hash_donottrack = simple_uhash("DNT"); + hash_useragent = simple_uhash("User-Agent"); + hash_authorization = simple_uhash("X-Auth-Token"); + } + + char *e = s; + + // find the : + while(*e && *e != ':') e++; + if(!*e) return e; + + // get the name + *e = '\0'; + + // find the value + char *v = e + 1, *ve; + + // skip leading spaces from value + while(*v == ' ') v++; + ve = v; + + // find the \r + while(*ve && *ve != '\r') ve++; + if(!*ve || ve[1] != '\n') { + *e = ':'; + return ve; + } + + // terminate the value + *ve = '\0'; + + // fprintf(stderr, "HEADER: '%s' = '%s'\n", s, v); + uint32_t hash = simple_uhash(s); + + if(hash == hash_origin && !strcasecmp(s, "Origin")) + strncpyz(w->origin, v, NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE); + + else if(hash == hash_connection && !strcasecmp(s, "Connection")) { + if(strcasestr(v, "keep-alive")) + web_client_enable_keepalive(w); + } + else if(respect_web_browser_do_not_track_policy && hash == hash_donottrack && !strcasecmp(s, "DNT")) { + if(*v == '0') web_client_disable_donottrack(w); + else if(*v == '1') web_client_enable_donottrack(w); + } + else if(parse_useragent && hash == hash_useragent && !strcasecmp(s, "User-Agent")) { + w->user_agent = strdupz(v); + } else if(hash == hash_authorization&& !strcasecmp(s, "X-Auth-Token")) { + w->auth_bearer_token = strdupz(v); + } +#ifdef NETDATA_WITH_ZLIB + else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) { + if(web_enable_gzip) { + if(strcasestr(v, "gzip")) + web_client_enable_deflate(w, 1); + // + // does not seem to work + // else if(strcasestr(v, "deflate")) + // web_client_enable_deflate(w, 0); + } + } +#endif /* NETDATA_WITH_ZLIB */ + + *e = ':'; + *ve = '\r'; + return ve; +} + +// http_request_validate() +// returns: +// = 0 : all good, process the request +// > 0 : request is not supported +// < 0 : request is incomplete - wait for more data + +typedef enum { + HTTP_VALIDATION_OK, + HTTP_VALIDATION_NOT_SUPPORTED, + HTTP_VALIDATION_INCOMPLETE +} HTTP_VALIDATION; + +static inline HTTP_VALIDATION http_request_validate(struct web_client *w) { + char *s = (char *)buffer_tostring(w->response.data), *encoded_url = NULL; + + size_t last_pos = w->header_parse_last_size; + if(last_pos > 4) last_pos -= 4; // allow searching for \r\n\r\n + else last_pos = 0; + + w->header_parse_tries++; + w->header_parse_last_size = buffer_strlen(w->response.data); + + if(w->header_parse_tries > 1) { + if(w->header_parse_last_size < last_pos) + last_pos = 0; + + if(strstr(&s[last_pos], "\r\n\r\n") == NULL) { + if(w->header_parse_tries > 10) { + info("Disabling slow client after %zu attempts to read the request (%zu bytes received)", w->header_parse_tries, buffer_strlen(w->response.data)); + w->header_parse_tries = 0; + w->header_parse_last_size = 0; + web_client_disable_wait_receive(w); + return HTTP_VALIDATION_NOT_SUPPORTED; + } + + return HTTP_VALIDATION_INCOMPLETE; + } + } + + // is is a valid request? + if(!strncmp(s, "GET ", 4)) { + encoded_url = s = &s[4]; + w->mode = WEB_CLIENT_MODE_NORMAL; + } + else if(!strncmp(s, "OPTIONS ", 8)) { + encoded_url = s = &s[8]; + w->mode = WEB_CLIENT_MODE_OPTIONS; + } + else if(!strncmp(s, "STREAM ", 7)) { + encoded_url = s = &s[7]; + w->mode = WEB_CLIENT_MODE_STREAM; + } + else { + w->header_parse_tries = 0; + w->header_parse_last_size = 0; + web_client_disable_wait_receive(w); + return HTTP_VALIDATION_NOT_SUPPORTED; + } + + // find the SPACE + "HTTP/" + while(*s) { + // find the next space + while (*s && *s != ' ') s++; + + // is it SPACE + "HTTP/" ? + if(*s && !strncmp(s, " HTTP/", 6)) break; + else s++; + } + + // incomplete requests + if(unlikely(!*s)) { + web_client_enable_wait_receive(w); + return HTTP_VALIDATION_INCOMPLETE; + } + + // we have the end of encoded_url - remember it + char *ue = s; + + // make sure we have complete request + // complete requests contain: \r\n\r\n + while(*s) { + // find a line feed + while(*s && *s++ != '\r'); + + // did we reach the end? + if(unlikely(!*s)) break; + + // is it \r\n ? + if(likely(*s++ == '\n')) { + + // is it again \r\n ? (header end) + if(unlikely(*s == '\r' && s[1] == '\n')) { + // a valid complete HTTP request found + + *ue = '\0'; + url_decode_r(w->decoded_url, encoded_url, NETDATA_WEB_REQUEST_URL_SIZE + 1); + *ue = ' '; + + // copy the URL - we are going to overwrite parts of it + // TODO -- ideally we we should avoid copying buffers around + strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE); + + w->header_parse_tries = 0; + w->header_parse_last_size = 0; + web_client_disable_wait_receive(w); + return HTTP_VALIDATION_OK; + } + + // another header line + s = http_header_parse(w, s, + (w->mode == WEB_CLIENT_MODE_STREAM) // parse user agent + ); + } + } + + // incomplete request + web_client_enable_wait_receive(w); + return HTTP_VALIDATION_INCOMPLETE; +} + +static inline void web_client_send_http_header(struct web_client *w) { + if(unlikely(w->response.code != 200)) + buffer_no_cacheable(w->response.data); + + // set a proper expiration date, if not already set + if(unlikely(!w->response.data->expires)) { + if(w->response.data->options & WB_CONTENT_NO_CACHEABLE) + w->response.data->expires = w->tv_ready.tv_sec + localhost->rrd_update_every; + else + w->response.data->expires = w->tv_ready.tv_sec + 86400; + } + + // prepare the HTTP response header + debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, w->response.code); + + const char *content_type_string = web_content_type_to_string(w->response.data->contenttype); + const char *code_msg = web_response_code_to_string(w->response.code); + + // prepare the last modified and expiration dates + char date[32], edate[32]; + { + struct tm tmbuf, *tm; + + tm = gmtime_r(&w->response.data->date, &tmbuf); + strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", tm); + + tm = gmtime_r(&w->response.data->expires, &tmbuf); + strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", tm); + } + + buffer_sprintf(w->response.header_output, + "HTTP/1.1 %d %s\r\n" + "Connection: %s\r\n" + "Server: NetData Embedded HTTP Server v%s\r\n" + "Access-Control-Allow-Origin: %s\r\n" + "Access-Control-Allow-Credentials: true\r\n" + "Content-Type: %s\r\n" + "Date: %s\r\n" + , w->response.code, code_msg + , web_client_has_keepalive(w)?"keep-alive":"close" + , VERSION + , w->origin + , content_type_string + , date + ); + + if(unlikely(web_x_frame_options)) + buffer_sprintf(w->response.header_output, "X-Frame-Options: %s\r\n", web_x_frame_options); + + if(w->cookie1[0] || w->cookie2[0]) { + if(w->cookie1[0]) { + buffer_sprintf(w->response.header_output, + "Set-Cookie: %s\r\n", + w->cookie1); + } + + if(w->cookie2[0]) { + buffer_sprintf(w->response.header_output, + "Set-Cookie: %s\r\n", + w->cookie2); + } + + if(respect_web_browser_do_not_track_policy) + buffer_sprintf(w->response.header_output, + "Tk: T;cookies\r\n"); + } + else { + if(respect_web_browser_do_not_track_policy) { + if(web_client_has_tracking_required(w)) + buffer_sprintf(w->response.header_output, + "Tk: T;cookies\r\n"); + else + buffer_sprintf(w->response.header_output, + "Tk: N\r\n"); + } + } + + if(w->mode == WEB_CLIENT_MODE_OPTIONS) { + buffer_strcat(w->response.header_output, + "Access-Control-Allow-Methods: GET, OPTIONS\r\n" + "Access-Control-Allow-Headers: accept, x-requested-with, origin, content-type, cookie, pragma, cache-control\r\n" + "Access-Control-Max-Age: 1209600\r\n" // 86400 * 14 + ); + } + else { + buffer_sprintf(w->response.header_output, + "Cache-Control: %s\r\n" + "Expires: %s\r\n", + (w->response.data->options & WB_CONTENT_NO_CACHEABLE)?"no-cache":"public", + edate); + } + + // copy a possibly available custom header + if(unlikely(buffer_strlen(w->response.header))) + buffer_strcat(w->response.header_output, buffer_tostring(w->response.header)); + + // headers related to the transfer method + if(likely(w->response.zoutput)) { + buffer_strcat(w->response.header_output, + "Content-Encoding: gzip\r\n" + "Transfer-Encoding: chunked\r\n" + ); + } + else { + if(likely((w->response.data->len || w->response.rlen))) { + // we know the content length, put it + buffer_sprintf(w->response.header_output, "Content-Length: %zu\r\n", w->response.data->len? w->response.data->len: w->response.rlen); + } + else { + // we don't know the content length, disable keep-alive + web_client_disable_keepalive(w); + } + } + + // end of HTTP header + buffer_strcat(w->response.header_output, "\r\n"); + + // sent the HTTP header + debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %zu: '%s'" + , w->id + , buffer_strlen(w->response.header_output) + , buffer_tostring(w->response.header_output) + ); + + web_client_crock_socket(w); + + size_t count = 0; + ssize_t bytes; + while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) { + count++; + + if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) { + error("Cannot send HTTP headers to web client."); + break; + } + } + + if(bytes != (ssize_t) buffer_strlen(w->response.header_output)) { + if(bytes > 0) + w->stats_sent_bytes += bytes; + + error("HTTP headers failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client." + , buffer_strlen(w->response.header_output) + , bytes); + + WEB_CLIENT_IS_DEAD(w); + return; + } + else + w->stats_sent_bytes += bytes; +} + +static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url); + +static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t hash_localhost = 0; + + if(unlikely(!hash_localhost)) { + hash_localhost = simple_hash("localhost"); + } + + if(host != localhost) { + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "Nesting of hosts is not allowed."); + return 400; + } + + char *tok = mystrsep(&url, "/"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for host with name '%s'.", w->id, tok); + + // copy the URL, we need it to serve files + w->last_url[0] = '/'; + if(url && *url) strncpyz(&w->last_url[1], url, NETDATA_WEB_REQUEST_URL_SIZE - 1); + else w->last_url[1] = '\0'; + + uint32_t hash = simple_hash(tok); + + host = rrdhost_find_by_hostname(tok, hash); + if(!host) host = rrdhost_find_by_guid(tok, hash); + + if(host) return web_client_process_url(host, w, url); + } + + buffer_flush(w->response.data); + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "This netdata does not maintain a database for host: "); + buffer_strcat_htmlescape(w->response.data, tok?tok:""); + return 404; +} + +static inline int web_client_process_url(RRDHOST *host, struct web_client *w, char *url) { + static uint32_t + hash_api = 0, + hash_netdata_conf = 0, + hash_host = 0; + +#ifdef NETDATA_INTERNAL_CHECKS + static uint32_t hash_exit = 0, hash_debug = 0, hash_mirror = 0; +#endif + + if(unlikely(!hash_api)) { + hash_api = simple_hash("api"); + hash_netdata_conf = simple_hash("netdata.conf"); + hash_host = simple_hash("host"); +#ifdef NETDATA_INTERNAL_CHECKS + hash_exit = simple_hash("exit"); + hash_debug = simple_hash("debug"); + hash_mirror = simple_hash("mirror"); +#endif + } + + char *tok = mystrsep(&url, "/?"); + if(likely(tok && *tok)) { + uint32_t hash = simple_hash(tok); + debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok); + + if(unlikely(hash == hash_api && strcmp(tok, "api") == 0)) { // current API + debug(D_WEB_CLIENT_ACCESS, "%llu: API request ...", w->id); + return check_host_and_call(host, w, url, web_client_api_request); + } + else if(unlikely(hash == hash_host && strcmp(tok, "host") == 0)) { // host switching + debug(D_WEB_CLIENT_ACCESS, "%llu: host switch request ...", w->id); + return web_client_switch_host(host, w, url); + } + else if(unlikely(hash == hash_netdata_conf && strcmp(tok, "netdata.conf") == 0)) { // netdata.conf + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + + debug(D_WEB_CLIENT_ACCESS, "%llu: generating netdata.conf ...", w->id); + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + config_generate(w->response.data, 0); + return 200; + } +#ifdef NETDATA_INTERNAL_CHECKS + else if(unlikely(hash == hash_exit && strcmp(tok, "exit") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + + if(!netdata_exit) + buffer_strcat(w->response.data, "ok, will do..."); + else + buffer_strcat(w->response.data, "I am doing it already"); + + error("web request to exit received."); + netdata_cleanup_and_exit(0); + return 200; + } + else if(unlikely(hash == hash_debug && strcmp(tok, "debug") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + + buffer_flush(w->response.data); + + // get the name of the data to show + tok = mystrsep(&url, "&"); + if(tok && *tok) { + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok); + + // do we have such a data set? + RRDSET *st = rrdset_find_byname(host, tok); + if(!st) st = rrdset_find(host, tok); + if(!st) { + w->response.data->contenttype = CT_TEXT_HTML; + buffer_strcat(w->response.data, "Chart is not found: "); + buffer_strcat_htmlescape(w->response.data, tok); + debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok); + return 404; + } + + debug_flags |= D_RRD_STATS; + + if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) + rrdset_flag_clear(st, RRDSET_FLAG_DEBUG); + else + rrdset_flag_set(st, RRDSET_FLAG_DEBUG); + + w->response.data->contenttype = CT_TEXT_HTML; + buffer_sprintf(w->response.data, "Chart has now debug %s: ", rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled"); + buffer_strcat_htmlescape(w->response.data, tok); + debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, rrdset_flag_check(st, RRDSET_FLAG_DEBUG)?"enabled":"disabled"); + return 200; + } + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "debug which chart?\r\n"); + return 400; + } + else if(unlikely(hash == hash_mirror && strcmp(tok, "mirror") == 0)) { + if(unlikely(!web_client_can_access_netdataconf(w))) + return web_client_permission_denied(w); + + debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id); + + // replace the zero bytes with spaces + buffer_char_replace(w->response.data, '\0', ' '); + + // just leave the buffer as is + // it will be copied back to the client + + return 200; + } +#endif /* NETDATA_INTERNAL_CHECKS */ + } + + char filename[FILENAME_MAX+1]; + url = filename; + strncpyz(filename, w->last_url, FILENAME_MAX); + tok = mystrsep(&url, "?"); + buffer_flush(w->response.data); + return mysendfile(w, (tok && *tok)?tok:"/"); +} + +void web_client_process_request(struct web_client *w) { + + // start timing us + now_realtime_timeval(&w->tv_in); + + switch(http_request_validate(w)) { + case HTTP_VALIDATION_OK: + switch(w->mode) { + case WEB_CLIENT_MODE_STREAM: + if(unlikely(!web_client_can_access_stream(w))) { + web_client_permission_denied(w); + return; + } + + w->response.code = rrdpush_receiver_thread_spawn(localhost, w, w->decoded_url); + return; + + case WEB_CLIENT_MODE_OPTIONS: + if(unlikely( + !web_client_can_access_dashboard(w) && + !web_client_can_access_registry(w) && + !web_client_can_access_badges(w) && + !web_client_can_access_mgmt(w) && + !web_client_can_access_netdataconf(w) + )) { + web_client_permission_denied(w); + break; + } + + w->response.data->contenttype = CT_TEXT_PLAIN; + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "OK"); + w->response.code = 200; + break; + + case WEB_CLIENT_MODE_FILECOPY: + case WEB_CLIENT_MODE_NORMAL: + if(unlikely( + !web_client_can_access_dashboard(w) && + !web_client_can_access_registry(w) && + !web_client_can_access_badges(w) && + !web_client_can_access_mgmt(w) && + !web_client_can_access_netdataconf(w) + )) { + web_client_permission_denied(w); + break; + } + + w->response.code = web_client_process_url(localhost, w, w->decoded_url); + break; + } + break; + + case HTTP_VALIDATION_INCOMPLETE: + if(w->response.data->len > NETDATA_WEB_REQUEST_MAX_SIZE) { + strcpy(w->last_url, "too big request"); + + debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big (%zu bytes).", w->id, w->response.data->len); + + buffer_flush(w->response.data); + buffer_sprintf(w->response.data, "Received request is too big (%zu bytes).\r\n", w->response.data->len); + w->response.code = 400; + } + else { + // wait for more data + return; + } + break; + + case HTTP_VALIDATION_NOT_SUPPORTED: + debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer); + + buffer_flush(w->response.data); + buffer_strcat(w->response.data, "I don't understand you...\r\n"); + w->response.code = 400; + break; + } + + // keep track of the time we done processing + now_realtime_timeval(&w->tv_ready); + + w->response.sent = 0; + + // set a proper last modified date + if(unlikely(!w->response.data->date)) + w->response.data->date = w->tv_ready.tv_sec; + + web_client_send_http_header(w); + + // enable sending immediately if we have data + if(w->response.data->len) web_client_enable_wait_send(w); + else web_client_disable_wait_send(w); + + switch(w->mode) { + case WEB_CLIENT_MODE_STREAM: + debug(D_WEB_CLIENT, "%llu: STREAM done.", w->id); + break; + + case WEB_CLIENT_MODE_OPTIONS: + debug(D_WEB_CLIENT, "%llu: Done preparing the OPTIONS response. Sending data (%zu bytes) to client.", w->id, w->response.data->len); + break; + + case WEB_CLIENT_MODE_NORMAL: + debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%zu bytes) to client.", w->id, w->response.data->len); + break; + + case WEB_CLIENT_MODE_FILECOPY: + if(w->response.rlen) { + debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %zu bytes to client.", w->id, w->response.rlen); + web_client_enable_wait_receive(w); + + /* + // utilize the kernel sendfile() for copying the file to the socket. + // this block of code can be commented, without anything missing. + // when it is commented, the program will copy the data using async I/O. + { + long len = sendfile(w->ofd, w->ifd, NULL, w->response.data->rbytes); + if(len != w->response.data->rbytes) + error("%llu: sendfile() should copy %ld bytes, but copied %ld. Falling back to manual copy.", w->id, w->response.data->rbytes, len); + else + web_client_request_done(w); + } + */ + } + else + debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending an unknown amount of bytes to client.", w->id); + break; + + default: + fatal("%llu: Unknown client mode %u.", w->id, w->mode); + break; + } +} + +ssize_t web_client_send_chunk_header(struct web_client *w, size_t len) +{ + debug(D_DEFLATE, "%llu: OPEN CHUNK of %zu bytes (hex: %zx).", w->id, len, len); + char buf[24]; + sprintf(buf, "%zX\r\n", len); + + ssize_t bytes = send(w->ofd, buf, strlen(buf), 0); + if(bytes > 0) { + debug(D_DEFLATE, "%llu: Sent chunk header %zd bytes.", w->id, bytes); + w->stats_sent_bytes += bytes; + } + + else if(bytes == 0) { + debug(D_WEB_CLIENT, "%llu: Did not send chunk header to the client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + else { + debug(D_WEB_CLIENT, "%llu: Failed to send chunk header to client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return bytes; +} + +ssize_t web_client_send_chunk_close(struct web_client *w) +{ + //debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id); + + ssize_t bytes = send(w->ofd, "\r\n", 2, 0); + if(bytes > 0) { + debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes); + w->stats_sent_bytes += bytes; + } + + else if(bytes == 0) { + debug(D_WEB_CLIENT, "%llu: Did not send chunk suffix to the client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + else { + debug(D_WEB_CLIENT, "%llu: Failed to send chunk suffix to client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return bytes; +} + +ssize_t web_client_send_chunk_finalize(struct web_client *w) +{ + //debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id); + + ssize_t bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, 0); + if(bytes > 0) { + debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes); + w->stats_sent_bytes += bytes; + } + + else if(bytes == 0) { + debug(D_WEB_CLIENT, "%llu: Did not send chunk finalize suffix to the client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + else { + debug(D_WEB_CLIENT, "%llu: Failed to send chunk finalize suffix to client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return bytes; +} + +#ifdef NETDATA_WITH_ZLIB +ssize_t web_client_send_deflate(struct web_client *w) +{ + ssize_t len = 0, t = 0; + + // when using compression, + // w->response.sent is the amount of bytes passed through compression + + debug(D_DEFLATE, "%llu: web_client_send_deflate(): w->response.data->len = %zu, w->response.sent = %zu, w->response.zhave = %zu, w->response.zsent = %zu, w->response.zstream.avail_in = %u, w->response.zstream.avail_out = %u, w->response.zstream.total_in = %lu, w->response.zstream.total_out = %lu.", + w->id, w->response.data->len, w->response.sent, w->response.zhave, w->response.zsent, w->response.zstream.avail_in, w->response.zstream.avail_out, w->response.zstream.total_in, w->response.zstream.total_out); + + if(w->response.data->len - w->response.sent == 0 && w->response.zstream.avail_in == 0 && w->response.zhave == w->response.zsent && w->response.zstream.avail_out != 0) { + // there is nothing to send + + debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id); + + // finalize the chunk + if(w->response.sent != 0) { + t = web_client_send_chunk_finalize(w); + if(t < 0) return t; + } + + if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) { + // we have to wait, more data will come + debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id); + web_client_disable_wait_send(w); + return t; + } + + if(unlikely(!web_client_has_keepalive(w))) { + debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent); + WEB_CLIENT_IS_DEAD(w); + return t; + } + + // reset the client + web_client_request_done(w); + debug(D_WEB_CLIENT, "%llu: Done sending all data on socket.", w->id); + return t; + } + + if(w->response.zhave == w->response.zsent) { + // compress more input data + + // close the previous open chunk + if(w->response.sent != 0) { + t = web_client_send_chunk_close(w); + if(t < 0) return t; + } + + debug(D_DEFLATE, "%llu: Compressing %zu new bytes starting from %zu (and %u left behind).", w->id, (w->response.data->len - w->response.sent), w->response.sent, w->response.zstream.avail_in); + + // give the compressor all the data not passed through the compressor yet + if(w->response.data->len > w->response.sent) { + w->response.zstream.next_in = (Bytef *)&w->response.data->buffer[w->response.sent - w->response.zstream.avail_in]; + w->response.zstream.avail_in += (uInt) (w->response.data->len - w->response.sent); + } + + // reset the compressor output buffer + w->response.zstream.next_out = w->response.zbuffer; + w->response.zstream.avail_out = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE; + + // ask for FINISH if we have all the input + int flush = Z_SYNC_FLUSH; + if(w->mode == WEB_CLIENT_MODE_NORMAL + || (w->mode == WEB_CLIENT_MODE_FILECOPY && !web_client_has_wait_receive(w) && w->response.data->len == w->response.rlen)) { + flush = Z_FINISH; + debug(D_DEFLATE, "%llu: Requesting Z_FINISH, if possible.", w->id); + } + else { + debug(D_DEFLATE, "%llu: Requesting Z_SYNC_FLUSH.", w->id); + } + + // compress + if(deflate(&w->response.zstream, flush) == Z_STREAM_ERROR) { + error("%llu: Compression failed. Closing down client.", w->id); + web_client_request_done(w); + return(-1); + } + + w->response.zhave = NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE - w->response.zstream.avail_out; + w->response.zsent = 0; + + // keep track of the bytes passed through the compressor + w->response.sent = w->response.data->len; + + debug(D_DEFLATE, "%llu: Compression produced %zu bytes.", w->id, w->response.zhave); + + // open a new chunk + ssize_t t2 = web_client_send_chunk_header(w, w->response.zhave); + if(t2 < 0) return t2; + t += t2; + } + + debug(D_WEB_CLIENT, "%llu: Sending %zu bytes of data (+%zd of chunk header).", w->id, w->response.zhave - w->response.zsent, t); + + len = send(w->ofd, &w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT); + if(len > 0) { + w->stats_sent_bytes += len; + w->response.zsent += len; + len += t; + debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, len); + } + else if(len == 0) { + debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client (zhave = %zu, zsent = %zu, need to send = %zu).", + w->id, w->response.zhave, w->response.zsent, w->response.zhave - w->response.zsent); + + WEB_CLIENT_IS_DEAD(w); + } + else { + debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return(len); +} +#endif // NETDATA_WITH_ZLIB + +ssize_t web_client_send(struct web_client *w) { +#ifdef NETDATA_WITH_ZLIB + if(likely(w->response.zoutput)) return web_client_send_deflate(w); +#endif // NETDATA_WITH_ZLIB + + ssize_t bytes; + + if(unlikely(w->response.data->len - w->response.sent == 0)) { + // there is nothing to send + + debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id); + + // there can be two cases for this + // A. we have done everything + // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd + + if(w->mode == WEB_CLIENT_MODE_FILECOPY && web_client_has_wait_receive(w) && w->response.rlen && w->response.rlen > w->response.data->len) { + // we have to wait, more data will come + debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id); + web_client_disable_wait_send(w); + return 0; + } + + if(unlikely(!web_client_has_keepalive(w))) { + debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %zu bytes sent.", w->id, w->response.sent); + WEB_CLIENT_IS_DEAD(w); + return 0; + } + + web_client_request_done(w); + debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id); + return 0; + } + + bytes = send(w->ofd, &w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT); + if(likely(bytes > 0)) { + w->stats_sent_bytes += bytes; + w->response.sent += bytes; + debug(D_WEB_CLIENT, "%llu: Sent %zd bytes.", w->id, bytes); + } + else if(likely(bytes == 0)) { + debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + else { + debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return(bytes); +} + +ssize_t web_client_read_file(struct web_client *w) +{ + if(unlikely(w->response.rlen > w->response.data->size)) + buffer_need_bytes(w->response.data, w->response.rlen - w->response.data->size); + + if(unlikely(w->response.rlen <= w->response.data->len)) + return 0; + + ssize_t left = w->response.rlen - w->response.data->len; + ssize_t bytes = read(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t)left); + if(likely(bytes > 0)) { + size_t old = w->response.data->len; + (void)old; + + w->response.data->len += bytes; + w->response.data->buffer[w->response.data->len] = '\0'; + + debug(D_WEB_CLIENT, "%llu: Read %zd bytes.", w->id, bytes); + debug(D_WEB_DATA, "%llu: Read data: '%s'.", w->id, &w->response.data->buffer[old]); + + web_client_enable_wait_send(w); + + if(w->response.rlen && w->response.data->len >= w->response.rlen) + web_client_disable_wait_receive(w); + } + else if(likely(bytes == 0)) { + debug(D_WEB_CLIENT, "%llu: Out of input file data.", w->id); + + // if we cannot read, it means we have an error on input. + // if however, we are copying a file from ifd to ofd, we should not return an error. + // in this case, the error should be generated when the file has been sent to the client. + + // we are copying data from ifd to ofd + // let it finish copying... + web_client_disable_wait_receive(w); + + debug(D_WEB_CLIENT, "%llu: Read the whole file.", w->id); + + if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) { + if (w->ifd != w->ofd) close(w->ifd); + } + + w->ifd = w->ofd; + } + else { + debug(D_WEB_CLIENT, "%llu: read data failed.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return(bytes); +} + +ssize_t web_client_receive(struct web_client *w) +{ + if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) + return web_client_read_file(w); + + // do we have any space for more data? + buffer_need_bytes(w->response.data, NETDATA_WEB_REQUEST_RECEIVE_SIZE); + + ssize_t left = w->response.data->size - w->response.data->len; + ssize_t bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT); + + if(likely(bytes > 0)) { + w->stats_received_bytes += bytes; + + size_t old = w->response.data->len; + (void)old; + + w->response.data->len += bytes; + w->response.data->buffer[w->response.data->len] = '\0'; + + debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes); + debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]); + } + else { + debug(D_WEB_CLIENT, "%llu: receive data failed.", w->id); + WEB_CLIENT_IS_DEAD(w); + } + + return(bytes); +} diff --git a/web/server/web_client.h b/web/server/web_client.h new file mode 100644 index 0000000..4263e25 --- /dev/null +++ b/web/server/web_client.h @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_CLIENT_H +#define NETDATA_WEB_CLIENT_H 1 + +#include "libnetdata/libnetdata.h" + +#ifdef NETDATA_WITH_ZLIB +extern int web_enable_gzip, + web_gzip_level, + web_gzip_strategy; +#endif /* NETDATA_WITH_ZLIB */ + +extern int respect_web_browser_do_not_track_policy; +extern char *web_x_frame_options; + +typedef enum web_client_mode { + WEB_CLIENT_MODE_NORMAL = 0, + WEB_CLIENT_MODE_FILECOPY = 1, + WEB_CLIENT_MODE_OPTIONS = 2, + WEB_CLIENT_MODE_STREAM = 3 +} WEB_CLIENT_MODE; + +typedef enum web_client_flags { + WEB_CLIENT_FLAG_DEAD = 1 << 1, // if set, this client is dead + + WEB_CLIENT_FLAG_KEEPALIVE = 1 << 2, // if set, the web client will be re-used + + WEB_CLIENT_FLAG_WAIT_RECEIVE = 1 << 3, // if set, we are waiting more input data + WEB_CLIENT_FLAG_WAIT_SEND = 1 << 4, // if set, we have data to send to the client + + WEB_CLIENT_FLAG_DO_NOT_TRACK = 1 << 5, // if set, we should not set cookies on this client + WEB_CLIENT_FLAG_TRACKING_REQUIRED = 1 << 6, // if set, we need to send cookies + + WEB_CLIENT_FLAG_TCP_CLIENT = 1 << 7, // if set, the client is using a TCP socket + WEB_CLIENT_FLAG_UNIX_CLIENT = 1 << 8, // if set, the client is using a UNIX socket + + WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET = 1 << 9, // don't close the socket when cleaning up (static-threaded web server) +} WEB_CLIENT_FLAGS; + +//#ifdef HAVE_C___ATOMIC +//#define web_client_flag_check(w, flag) (__atomic_load_n(&((w)->flags), __ATOMIC_SEQ_CST) & flag) +//#define web_client_flag_set(w, flag) __atomic_or_fetch(&((w)->flags), flag, __ATOMIC_SEQ_CST) +//#define web_client_flag_clear(w, flag) __atomic_and_fetch(&((w)->flags), ~flag, __ATOMIC_SEQ_CST) +//#else +#define web_client_flag_check(w, flag) ((w)->flags & (flag)) +#define web_client_flag_set(w, flag) (w)->flags |= flag +#define web_client_flag_clear(w, flag) (w)->flags &= ~flag +//#endif + +#define WEB_CLIENT_IS_DEAD(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DEAD) +#define web_client_check_dead(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DEAD) + +#define web_client_has_keepalive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_KEEPALIVE) +#define web_client_enable_keepalive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_KEEPALIVE) +#define web_client_disable_keepalive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_KEEPALIVE) + +#define web_client_has_donottrack(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DO_NOT_TRACK) +#define web_client_enable_donottrack(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DO_NOT_TRACK) +#define web_client_disable_donottrack(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_DO_NOT_TRACK) + +#define web_client_has_tracking_required(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED) +#define web_client_enable_tracking_required(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED) +#define web_client_disable_tracking_required(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED) + +#define web_client_has_wait_receive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_RECEIVE) +#define web_client_enable_wait_receive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_RECEIVE) +#define web_client_disable_wait_receive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_RECEIVE) + +#define web_client_has_wait_send(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_SEND) +#define web_client_enable_wait_send(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_SEND) +#define web_client_disable_wait_send(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_SEND) + +#define web_client_set_tcp(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TCP_CLIENT) +#define web_client_set_unix(w) web_client_flag_set(w, WEB_CLIENT_FLAG_UNIX_CLIENT) +#define web_client_check_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_UNIX_CLIENT) +#define web_client_check_tcp(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT) + +#define web_client_is_corkable(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TCP_CLIENT) + +#define NETDATA_WEB_REQUEST_URL_SIZE 8192 +#define NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE 16384 +#define NETDATA_WEB_RESPONSE_HEADER_SIZE 4096 +#define NETDATA_WEB_REQUEST_COOKIE_SIZE 1024 +#define NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE 1024 +#define NETDATA_WEB_RESPONSE_INITIAL_SIZE 16384 +#define NETDATA_WEB_REQUEST_RECEIVE_SIZE 16384 +#define NETDATA_WEB_REQUEST_MAX_SIZE 16384 + +struct response { + BUFFER *header; // our response header + BUFFER *header_output; // internal use + BUFFER *data; // our response data buffer + + int code; // the HTTP response code + + size_t rlen; // if non-zero, the excepted size of ifd (input of firecopy) + size_t sent; // current data length sent to output + + int zoutput; // if set to 1, web_client_send() will send compressed data +#ifdef NETDATA_WITH_ZLIB + z_stream zstream; // zlib stream for sending compressed output to client + Bytef zbuffer[NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE]; // temporary buffer for storing compressed output + size_t zsent; // the compressed bytes we have sent to the client + size_t zhave; // the compressed bytes that we have received from zlib + unsigned int zinitialized:1; +#endif /* NETDATA_WITH_ZLIB */ + +}; + +struct web_client { + unsigned long long id; + + WEB_CLIENT_FLAGS flags; // status flags for the client + WEB_CLIENT_MODE mode; // the operational mode of the client + WEB_CLIENT_ACL acl; // the access list of the client + int port_acl; // the operations permitted on the port the client connected to + char *auth_bearer_token; // the Bearer auth token (if sent) + size_t header_parse_tries; + size_t header_parse_last_size; + + int tcp_cork; // 1 = we have a cork on the socket + + int ifd; + int ofd; + + char client_ip[NI_MAXHOST+1]; + char client_port[NI_MAXSERV+1]; + + char decoded_url[NETDATA_WEB_REQUEST_URL_SIZE + 1]; // we decode the URL in this buffer + char last_url[NETDATA_WEB_REQUEST_URL_SIZE+1]; // we keep a copy of the decoded URL here + + struct timeval tv_in, tv_ready; + + char cookie1[NETDATA_WEB_REQUEST_COOKIE_SIZE+1]; + char cookie2[NETDATA_WEB_REQUEST_COOKIE_SIZE+1]; + char origin[NETDATA_WEB_REQUEST_ORIGIN_HEADER_SIZE+1]; + char *user_agent; + + struct response response; + + size_t stats_received_bytes; + size_t stats_sent_bytes; + + // cache of web_client allocations + struct web_client *prev; // maintain a linked list of web clients + struct web_client *next; // for the web servers that need it + + // MULTI-THREADED WEB SERVER MEMBERS + netdata_thread_t thread; // the thread servicing this client + volatile int running; // 1 when the thread runs, 0 otherwise + + // STATIC-THREADED WEB SERVER MEMBERS + size_t pollinfo_slot; // POLLINFO slot of the web client + size_t pollinfo_filecopy_slot; // POLLINFO slot of the file read +}; + +extern uid_t web_files_uid(void); +extern uid_t web_files_gid(void); + +extern int web_client_permission_denied(struct web_client *w); + +extern ssize_t web_client_send(struct web_client *w); +extern ssize_t web_client_receive(struct web_client *w); +extern ssize_t web_client_read_file(struct web_client *w); + +extern void web_client_process_request(struct web_client *w); +extern void web_client_request_done(struct web_client *w); + +extern void buffer_data_options2string(BUFFER *wb, uint32_t options); + +extern int mysendfile(struct web_client *w, char *filename); + +#include "daemon/common.h" + +#endif diff --git a/web/server/web_client_cache.c b/web/server/web_client_cache.c new file mode 100644 index 0000000..ab47056 --- /dev/null +++ b/web/server/web_client_cache.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#define WEB_SERVER_INTERNALS 1 +#include "web_client_cache.h" + +// ---------------------------------------------------------------------------- +// allocate and free web_clients + +static void web_client_zero(struct web_client *w) { + // zero everything about it - but keep the buffers + + // remember the pointers to the buffers + BUFFER *b1 = w->response.data; + BUFFER *b2 = w->response.header; + BUFFER *b3 = w->response.header_output; + + // empty the buffers + buffer_flush(b1); + buffer_flush(b2); + buffer_flush(b3); + + freez(w->user_agent); + + // zero everything + memset(w, 0, sizeof(struct web_client)); + + // restore the pointers of the buffers + w->response.data = b1; + w->response.header = b2; + w->response.header_output = b3; +} + +static void web_client_free(struct web_client *w) { + buffer_free(w->response.header_output); + buffer_free(w->response.header); + buffer_free(w->response.data); + freez(w->user_agent); + freez(w); +} + +static struct web_client *web_client_alloc(void) { + struct web_client *w = callocz(1, sizeof(struct web_client)); + w->response.data = buffer_create(NETDATA_WEB_RESPONSE_INITIAL_SIZE); + w->response.header = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); + w->response.header_output = buffer_create(NETDATA_WEB_RESPONSE_HEADER_SIZE); + return w; +} + +// ---------------------------------------------------------------------------- +// web clients caching + +// When clients connect and disconnect, avoid allocating and releasing memory. +// Instead, when new clients get connected, reuse any memory previously allocated +// for serving web clients that are now disconnected. + +// The size of the cache is adaptive. It caches the structures of 2x +// the number of currently connected clients. + +// Comments per server: +// SINGLE-THREADED : 1 cache is maintained +// MULTI-THREADED : 1 cache is maintained +// STATIC-THREADED : 1 cache for each thred of the web server + +__thread struct clients_cache web_clients_cache = { + .pid = 0, + .used = NULL, + .used_count = 0, + .avail = NULL, + .avail_count = 0, + .allocated = 0, + .reused = 0 +}; + +inline void web_client_cache_verify(int force) { +#ifdef NETDATA_INTERNAL_CHECKS + static __thread size_t count = 0; + count++; + + if(unlikely(force || count > 1000)) { + count = 0; + + struct web_client *w; + size_t used = 0, avail = 0; + for(w = web_clients_cache.used; w ; w = w->next) used++; + for(w = web_clients_cache.avail; w ; w = w->next) avail++; + + info("web_client_cache has %zu (%zu) used and %zu (%zu) available clients, allocated %zu, reused %zu (hit %zu%%)." + , used, web_clients_cache.used_count + , avail, web_clients_cache.avail_count + , web_clients_cache.allocated + , web_clients_cache.reused + , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0 + ); + } +#else + if(unlikely(force)) { + info("web_client_cache has %zu used and %zu available clients, allocated %zu, reused %zu (hit %zu%%)." + , web_clients_cache.used_count + , web_clients_cache.avail_count + , web_clients_cache.allocated + , web_clients_cache.reused + , (web_clients_cache.allocated + web_clients_cache.reused)?(web_clients_cache.reused * 100 / (web_clients_cache.allocated + web_clients_cache.reused)):0 + ); + } +#endif +} + +// destroy the cache and free all the memory it uses +void web_client_cache_destroy(void) { +#ifdef NETDATA_INTERNAL_CHECKS + if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) + error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); + + web_client_cache_verify(1); +#endif + + netdata_thread_disable_cancelability(); + + struct web_client *w, *t; + + w = web_clients_cache.used; + while(w) { + t = w; + w = w->next; + web_client_free(t); + } + web_clients_cache.used = NULL; + web_clients_cache.used_count = 0; + + w = web_clients_cache.avail; + while(w) { + t = w; + w = w->next; + web_client_free(t); + } + web_clients_cache.avail = NULL; + web_clients_cache.avail_count = 0; + + netdata_thread_enable_cancelability(); +} + +struct web_client *web_client_get_from_cache_or_allocate() { + +#ifdef NETDATA_INTERNAL_CHECKS + if(unlikely(web_clients_cache.pid == 0)) + web_clients_cache.pid = gettid(); + + if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) + error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); +#endif + + netdata_thread_disable_cancelability(); + + struct web_client *w = web_clients_cache.avail; + + if(w) { + // get it from avail + if (w == web_clients_cache.avail) web_clients_cache.avail = w->next; + if(w->prev) w->prev->next = w->next; + if(w->next) w->next->prev = w->prev; + web_clients_cache.avail_count--; + web_client_zero(w); + web_clients_cache.reused++; + } + else { + // allocate it + w = web_client_alloc(); + web_clients_cache.allocated++; + } + + // link it to used web clients + if (web_clients_cache.used) web_clients_cache.used->prev = w; + w->next = web_clients_cache.used; + w->prev = NULL; + web_clients_cache.used = w; + web_clients_cache.used_count++; + + // initialize it + w->id = web_client_connected(); + w->mode = WEB_CLIENT_MODE_NORMAL; + + netdata_thread_enable_cancelability(); + + return w; +} + +void web_client_release(struct web_client *w) { +#ifdef NETDATA_INTERNAL_CHECKS + if(unlikely(web_clients_cache.pid != 0 && web_clients_cache.pid != gettid())) + error("Oops! wrong thread accessing the cache. Expected %d, found %d", (int)web_clients_cache.pid, (int)gettid()); + + if(unlikely(w->running)) + error("%llu: releasing web client from %s port %s, but it still running.", w->id, w->client_ip, w->client_port); +#endif + + debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s port %s.", w->id, w->client_ip, w->client_port); + + web_server_log_connection(w, "DISCONNECTED"); + web_client_request_done(w); + web_client_disconnected(); + + netdata_thread_disable_cancelability(); + + if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) { + if (w->ifd != -1) close(w->ifd); + if (w->ofd != -1 && w->ofd != w->ifd) close(w->ofd); + w->ifd = w->ofd = -1; + } + + // unlink it from the used + if (w == web_clients_cache.used) web_clients_cache.used = w->next; + if(w->prev) w->prev->next = w->next; + if(w->next) w->next->prev = w->prev; + web_clients_cache.used_count--; + + if(web_clients_cache.avail_count >= 2 * web_clients_cache.used_count) { + // we have too many of them - free it + web_client_free(w); + } + else { + // link it to the avail + if (web_clients_cache.avail) web_clients_cache.avail->prev = w; + w->next = web_clients_cache.avail; + w->prev = NULL; + web_clients_cache.avail = w; + web_clients_cache.avail_count++; + } + + netdata_thread_enable_cancelability(); +} + diff --git a/web/server/web_client_cache.h b/web/server/web_client_cache.h new file mode 100644 index 0000000..f638880 --- /dev/null +++ b/web/server/web_client_cache.h @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_CLIENT_CACHE_H +#define NETDATA_WEB_CLIENT_CACHE_H + +#include "libnetdata/libnetdata.h" +#include "web_client.h" + +struct clients_cache { + pid_t pid; + + struct web_client *used; // the structures of the currently connected clients + size_t used_count; // the count the currently connected clients + + struct web_client *avail; // the cached structures, available for future clients + size_t avail_count; // the number of cached structures + + size_t reused; // the number of re-uses + size_t allocated; // the number of allocations +}; + +extern __thread struct clients_cache web_clients_cache; + +extern void web_client_release(struct web_client *w); +extern struct web_client *web_client_get_from_cache_or_allocate(); +extern void web_client_cache_destroy(void); +extern void web_client_cache_verify(int force); + +#include "web_server.h" + +#endif //NETDATA_WEB_CLIENT_CACHE_H diff --git a/web/server/web_server.c b/web/server/web_server.c new file mode 100644 index 0000000..11f7edf --- /dev/null +++ b/web/server/web_server.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#define WEB_SERVER_INTERNALS 1 +#include "web_server.h" + +WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_STATIC_THREADED; + +// -------------------------------------------------------------------------------------- + +WEB_SERVER_MODE web_server_mode_id(const char *mode) { + if(!strcmp(mode, "none")) + return WEB_SERVER_MODE_NONE; + else + return WEB_SERVER_MODE_STATIC_THREADED; + +} + +const char *web_server_mode_name(WEB_SERVER_MODE id) { + switch(id) { + case WEB_SERVER_MODE_NONE: + return "none"; + default: + case WEB_SERVER_MODE_STATIC_THREADED: + return "static-threaded"; + } +} + +// -------------------------------------------------------------------------------------- +// API sockets + +LISTEN_SOCKETS api_sockets = { + .config = &netdata_config, + .config_section = CONFIG_SECTION_WEB, + .default_bind_to = "*", + .default_port = API_LISTEN_PORT, + .backlog = API_LISTEN_BACKLOG +}; + +void debug_sockets() { + BUFFER *wb = buffer_create(256 * sizeof(char)); + int i; + + for(i = 0 ; i < (int)api_sockets.opened ; i++) { + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_NOCHECK)?"NONE ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_DASHBOARD)?"dashboard ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_REGISTRY)?"registry ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_BADGE)?"badges ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_MGMT)?"management ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_STREAMING)?"streaming ":""); + buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_NETDATACONF)?"netdata.conf ":""); + debug(D_WEB_CLIENT, "Socket fd %d name '%s' acl_flags: %s", + i, + api_sockets.fds_names[i], + buffer_tostring(wb)); + buffer_reset(wb); + } + buffer_free(wb); +} + +void api_listen_sockets_setup(void) { + int socks = listen_sockets_setup(&api_sockets); + + if(!socks) + fatal("LISTENER: Cannot listen on any API socket. Exiting..."); + + if(unlikely(debug_flags & D_WEB_CLIENT)) + debug_sockets(); + + return; +} + + +// -------------------------------------------------------------------------------------- +// access lists + +SIMPLE_PATTERN *web_allow_connections_from = NULL; + +// WEB_CLIENT_ACL +SIMPLE_PATTERN *web_allow_dashboard_from = NULL; +SIMPLE_PATTERN *web_allow_registry_from = NULL; +SIMPLE_PATTERN *web_allow_badges_from = NULL; +SIMPLE_PATTERN *web_allow_mgmt_from = NULL; +SIMPLE_PATTERN *web_allow_streaming_from = NULL; +SIMPLE_PATTERN *web_allow_netdataconf_from = NULL; + +void web_client_update_acl_matches(struct web_client *w) { + w->acl = WEB_CLIENT_ACL_NONE; + + if(!web_allow_dashboard_from || simple_pattern_matches(web_allow_dashboard_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_DASHBOARD; + + if(!web_allow_registry_from || simple_pattern_matches(web_allow_registry_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_REGISTRY; + + if(!web_allow_badges_from || simple_pattern_matches(web_allow_badges_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_BADGE; + + if(!web_allow_mgmt_from || simple_pattern_matches(web_allow_mgmt_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_MGMT; + + if(!web_allow_streaming_from || simple_pattern_matches(web_allow_streaming_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_STREAMING; + + if(!web_allow_netdataconf_from || simple_pattern_matches(web_allow_netdataconf_from, w->client_ip)) + w->acl |= WEB_CLIENT_ACL_NETDATACONF; + + w->acl &= w->port_acl; +} + + +// -------------------------------------------------------------------------------------- + +void web_server_log_connection(struct web_client *w, const char *msg) { + log_access("%llu: %d '[%s]:%s' '%s'", w->id, gettid(), w->client_ip, w->client_port, msg); +} + +// -------------------------------------------------------------------------------------- + +void web_client_initialize_connection(struct web_client *w) { + int flag = 1; + + if(unlikely(web_client_check_tcp(w) && setsockopt(w->ifd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)) + debug(D_WEB_CLIENT, "%llu: failed to enable TCP_NODELAY on socket fd %d.", w->id, w->ifd); + + flag = 1; + if(unlikely(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0)) + debug(D_WEB_CLIENT, "%llu: failed to enable SO_KEEPALIVE on socket fd %d.", w->id, w->ifd); + + web_client_update_acl_matches(w); + + w->origin[0] = '*'; w->origin[1] = '\0'; + w->cookie1[0] = '\0'; w->cookie2[0] = '\0'; + freez(w->user_agent); w->user_agent = NULL; + + web_client_enable_wait_receive(w); + + web_server_log_connection(w, "CONNECTED"); + + web_client_cache_verify(0); +} + + diff --git a/web/server/web_server.h b/web/server/web_server.h new file mode 100644 index 0000000..e7c2dd4 --- /dev/null +++ b/web/server/web_server.h @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_WEB_SERVER_H +#define NETDATA_WEB_SERVER_H 1 + +#include "libnetdata/libnetdata.h" +#include "web_client.h" + +#ifndef API_LISTEN_PORT +#define API_LISTEN_PORT 19999 +#endif + +#ifndef API_LISTEN_BACKLOG +#define API_LISTEN_BACKLOG 4096 +#endif + +typedef enum web_server_mode { + WEB_SERVER_MODE_STATIC_THREADED, + WEB_SERVER_MODE_NONE +} WEB_SERVER_MODE; + +extern SIMPLE_PATTERN *web_allow_connections_from; +extern SIMPLE_PATTERN *web_allow_dashboard_from; +extern SIMPLE_PATTERN *web_allow_registry_from; +extern SIMPLE_PATTERN *web_allow_badges_from; +extern SIMPLE_PATTERN *web_allow_streaming_from; +extern SIMPLE_PATTERN *web_allow_netdataconf_from; +extern SIMPLE_PATTERN *web_allow_mgmt_from; + +extern WEB_SERVER_MODE web_server_mode; + +extern WEB_SERVER_MODE web_server_mode_id(const char *mode); +extern const char *web_server_mode_name(WEB_SERVER_MODE id); + +extern void api_listen_sockets_setup(void); + +#define DEFAULT_TIMEOUT_TO_RECEIVE_FIRST_WEB_REQUEST 60 +#define DEFAULT_DISCONNECT_IDLE_WEB_CLIENTS_AFTER_SECONDS 60 +extern int web_client_timeout; +extern int web_client_first_request_timeout; +extern long web_client_streaming_rate_t; + +#ifdef WEB_SERVER_INTERNALS +extern LISTEN_SOCKETS api_sockets; +extern void web_client_update_acl_matches(struct web_client *w); +extern void web_server_log_connection(struct web_client *w, const char *msg); +extern void web_client_initialize_connection(struct web_client *w); +extern struct web_client *web_client_create_on_listenfd(int listener); + +#include "web_client_cache.h" +#endif // WEB_SERVER_INTERNALS + +#include "static/static-threaded.h" + +#include "daemon/common.h" + +#endif /* NETDATA_WEB_SERVER_H */ |