From cc0139c7028f116349d4975a4c08f2b39953e67c Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sat, 30 Sep 2017 15:33:26 +0200 Subject: [PATCH 01/55] initialized dashboard --- web/controllers/dashboard_controller.ex | 9 +++++++++ web/router.ex | 13 +++++++++++++ web/templates/dashboard/show.html.eex | 1 + web/views/dashboard_view.ex | 5 +++++ 4 files changed, 28 insertions(+) create mode 100644 web/controllers/dashboard_controller.ex create mode 100644 web/templates/dashboard/show.html.eex create mode 100644 web/views/dashboard_view.ex diff --git a/web/controllers/dashboard_controller.ex b/web/controllers/dashboard_controller.ex new file mode 100644 index 0000000..f36ef33 --- /dev/null +++ b/web/controllers/dashboard_controller.ex @@ -0,0 +1,9 @@ +defmodule ExDebugToolbar.DashboardController do + @moduledoc false + + use ExDebugToolbar.Web, :controller + + def show(conn, _) do + conn |> put_layout(false) |> render("show.html") + end +end diff --git a/web/router.ex b/web/router.ex index cdfee3b..ca0b1b2 100644 --- a/web/router.ex +++ b/web/router.ex @@ -2,4 +2,17 @@ defmodule ExDebugToolbar.Router do @moduledoc false use ExDebugToolbar.Web, :router + + pipeline :browser do + plug :accepts, ["html"] + plug :fetch_session + plug :fetch_flash + plug :protect_from_forgery + plug :put_secure_browser_headers + end + + scope "/", ExDebugToolbar do + pipe_through :browser + get "/", DashboardController, :show + end end diff --git a/web/templates/dashboard/show.html.eex b/web/templates/dashboard/show.html.eex new file mode 100644 index 0000000..4cd2b39 --- /dev/null +++ b/web/templates/dashboard/show.html.eex @@ -0,0 +1 @@ +I am dashboard! diff --git a/web/views/dashboard_view.ex b/web/views/dashboard_view.ex new file mode 100644 index 0000000..1ffcf2a --- /dev/null +++ b/web/views/dashboard_view.ex @@ -0,0 +1,5 @@ +defmodule ExDebugToolbar.DashboardView do + @moduledoc false + + use ExDebugToolbar.Web, :view +end From dbf5b9a5fd996fb85b6ee59b3e237b8ecbcc9abd Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sat, 30 Sep 2017 16:08:12 +0200 Subject: [PATCH 02/55] use dashboard_layout --- web/controllers/dashboard_controller.ex | 4 +++- web/templates/dashboard_layout/app.html.eex | 18 ++++++++++++++++++ web/views/dashboard_layout_view.ex | 5 +++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 web/templates/dashboard_layout/app.html.eex create mode 100644 web/views/dashboard_layout_view.ex diff --git a/web/controllers/dashboard_controller.ex b/web/controllers/dashboard_controller.ex index f36ef33..a0975ab 100644 --- a/web/controllers/dashboard_controller.ex +++ b/web/controllers/dashboard_controller.ex @@ -3,7 +3,9 @@ defmodule ExDebugToolbar.DashboardController do use ExDebugToolbar.Web, :controller + plug :put_layout, {ExDebugToolbar.DashboardLayoutView, :app} + def show(conn, _) do - conn |> put_layout(false) |> render("show.html") + conn |> render("show.html") end end diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex new file mode 100644 index 0000000..875a661 --- /dev/null +++ b/web/templates/dashboard_layout/app.html.eex @@ -0,0 +1,18 @@ + + + + + + + + + Developer Dashboard + "> + + +
+ <%= render @view_module, @view_template, assigns %> +
+ + + diff --git a/web/views/dashboard_layout_view.ex b/web/views/dashboard_layout_view.ex new file mode 100644 index 0000000..a9241c9 --- /dev/null +++ b/web/views/dashboard_layout_view.ex @@ -0,0 +1,5 @@ +defmodule ExDebugToolbar.DashboardLayoutView do + @moduledoc false + + use ExDebugToolbar.Web, :view +end From dac4be02efa3b4b630c9289e08d3cab058c938b5 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sat, 30 Sep 2017 16:08:25 +0200 Subject: [PATCH 03/55] installed adminlte package --- package.json | 1 + yarn.lock | 653 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 638 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 5b6946e..dbb2abf 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,7 @@ "watch": "brunch watch --stdin" }, "dependencies": { + "admin-lte": "^2.4.0", "bootstrap-sass": "^3.3.7", "copycat-brunch": "^1.1.0", "css-reset-and-normalize-sass": "^0.1.2", diff --git a/yarn.lock b/yarn.lock index caf083d..c9054f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,13 @@ # yarn lockfile v1 +JSONStream@^1.0.3: + version "1.3.1" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.1.tgz#707f761e01dae9e16f1bcf93703b78c70966579a" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" @@ -17,6 +24,39 @@ acorn@^4.0.3: version "4.0.11" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" +admin-lte@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/admin-lte/-/admin-lte-2.4.0.tgz#e5b768738defed3550932d7faab129f1f6402f4a" + dependencies: + bootstrap "^3.3.7" + bootstrap-colorpicker "^2.5.1" + bootstrap-datepicker "^1.7.0" + bootstrap-daterangepicker "^2.1.25" + bootstrap-slider "^9.8.0" + bootstrap-timepicker "^0.5.2" + chart.js "1.0.*" + ckeditor "^4.7.0" + datatables.net "^1.10.15" + datatables.net-bs "^1.10.15" + fastclick "^1.0.6" + flot "^0.8.0-alpha" + font-awesome "^4.7.0" + fullcalendar "^3.4.0" + inputmask "^3.3.7" + ion-rangeslider "^2.2.0" + ionicons "^3.0.0" + jquery "^3.2.1" + jquery-knob "^1.2.11" + jquery-sparkline "^2.4.0" + jquery-ui "^1.12.1" + jvectormap "^1.2.2" + moment "^2.18.1" + morris.js "^0.5.0" + pace "0.0.4" + raphael "^2.2.7" + select2 "^4.0.3" + slimscroll "^0.9.1" + ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" @@ -32,6 +72,10 @@ align-text@^0.1.1, align-text@^0.1.3: longest "^1.0.1" repeat-string "^1.5.2" +almond@~0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/almond/-/almond-0.3.3.tgz#a0e7c95ac7624d6417b4494b1e68bff693168a20" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -86,6 +130,10 @@ arr-flatten@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1" +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + array-find-index@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" @@ -94,6 +142,14 @@ array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -122,12 +178,24 @@ assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" +assert@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + assert@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/assert/-/assert-1.3.0.tgz#03939a622582a812cc202320a0b9a56c9b815849" dependencies: util "0.10.3" +astw@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917" + dependencies: + acorn "^4.0.3" + async-each@^1.0.0, async-each@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -635,10 +703,41 @@ boom@2.x.x: dependencies: hoek "2.x.x" +bootstrap-colorpicker@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/bootstrap-colorpicker/-/bootstrap-colorpicker-2.5.2.tgz#33bfb2043485f12dcb3df0f60ad171762cc3c0e4" + dependencies: + jquery ">=1.10" + +bootstrap-datepicker@^1.7.0: + version "1.7.1" + resolved "https://registry.yarnpkg.com/bootstrap-datepicker/-/bootstrap-datepicker-1.7.1.tgz#4ee7faf34888dbec7834fbf9dbe7c4277e01ddaf" + dependencies: + jquery ">=1.7.1 <4.0.0" + +bootstrap-daterangepicker@^2.1.25: + version "2.1.25" + resolved "https://registry.yarnpkg.com/bootstrap-daterangepicker/-/bootstrap-daterangepicker-2.1.25.tgz#fcd8ba0b755a054d330d7a3b7c4dd8bb855cffb7" + dependencies: + jquery ">=1.10" + moment "^2.9.0" + bootstrap-sass@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/bootstrap-sass/-/bootstrap-sass-3.3.7.tgz#6596c7ab40f6637393323ab0bc80d064fc630498" +bootstrap-slider@^9.8.0: + version "9.9.0" + resolved "https://registry.yarnpkg.com/bootstrap-slider/-/bootstrap-slider-9.9.0.tgz#4e14ecc6401901da1ddf7681aa24e33b00dadce8" + +bootstrap-timepicker@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/bootstrap-timepicker/-/bootstrap-timepicker-0.5.2.tgz#10ed9f2a2f0b8ccaefcde0fcf6a0738b919a3835" + +bootstrap@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-3.3.7.tgz#5a389394549f23330875a3b150656574f8a9eb71" + bower-config@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/bower-config/-/bower-config-1.4.0.tgz#16c38c1135f8071c19f25938d61b0d8cbf18d3f1" @@ -668,7 +767,17 @@ brorand@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" -browser-resolve@^1.11.1: +browser-pack@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.0.2.tgz#f86cd6cef4f5300c8e63e07a4d512f65fbff4531" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.7.1" + defined "^1.0.0" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^1.11.0, browser-resolve@^1.11.1, browser-resolve@^1.7.0: version "1.11.2" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" dependencies: @@ -719,6 +828,64 @@ browserify-sign@^4.0.0: inherits "^2.0.1" parse-asn1 "^5.0.0" +browserify-zlib@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +browserify@>=3.46.0: + version "14.4.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-14.4.0.tgz#089a3463af58d0e48d8cd4070b3f74654d5abca9" + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.1.2" + buffer "^5.0.2" + cached-path-relative "^1.0.0" + concat-stream "~1.5.1" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "~1.1.0" + duplexer2 "~0.1.2" + events "~1.1.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "^1.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + module-deps "^4.0.8" + os-browserify "~0.1.1" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "~1.0.0" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "~0.0.0" + url "~0.11.0" + util "~0.10.1" + vm-browserify "~0.0.1" + xtend "^4.0.0" + brunch-skeletons@~0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/brunch-skeletons/-/brunch-skeletons-0.1.5.tgz#2b35112b8c792d8f11087653d3fc8febf892375b" @@ -757,6 +924,13 @@ buffer-xor@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" +buffer@^5.0.2: + version "5.0.8" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + buffer@~4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.3.1.tgz#0e65fd01cc3e9154d152f6b3c934b5b8a1b6733c" @@ -773,6 +947,14 @@ builtin-status-codes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz#6f22003baacf003ccd287afe6872151fddc58579" +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +cached-path-relative@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" + camelcase-keys@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" @@ -820,6 +1002,14 @@ chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +charm@~0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/charm/-/charm-0.1.2.tgz#06c21eed1a1b06aeb67553cdc53e23274bac2296" + +chart.js@1.0.*: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-1.0.2.tgz#ad57d2229cfd8ccf5955147e8121b4911e69dfe7" + check-dependencies@~0.12.0: version "0.12.3" resolved "https://registry.yarnpkg.com/check-dependencies/-/check-dependencies-0.12.3.tgz#6ba493d4221dbc3f695113353ae4638f772c5c75" @@ -853,6 +1043,14 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: dependencies: inherits "^2.0.1" +ckeditor@^4.7.0: + version "4.7.3" + resolved "https://registry.yarnpkg.com/ckeditor/-/ckeditor-4.7.3.tgz#b486fb9eb91af9532a0acfaea4a55374970254d5" + +classie@>=0.0.1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/classie/-/classie-1.0.0.tgz#fc9b29b47e64e374a2062fb624d05a61cd703ab2" + clean-css-brunch@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/clean-css-brunch/-/clean-css-brunch-2.0.0.tgz#37c27476c4708a0094cd646c9c464ac1970c4b17" @@ -902,6 +1100,15 @@ coffee-script@~1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.10.0.tgz#12938bcf9be1948fa006f92e0c4c9e81705108c0" +combine-source-map@~0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.7.2.tgz#0870312856b307a87cc4ac486f3a9a62aeccc09e" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -928,14 +1135,32 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@~1.5.0, concat-stream@~1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" + dependencies: + inherits "~2.0.1" + readable-stream "~2.0.0" + typedarray "~0.0.5" + connect-slashes@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/connect-slashes/-/connect-slashes-1.3.1.tgz#95d61830d0f9d5853c8688f0b5f43988b186ac37" +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" +constants-browserify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" @@ -948,6 +1173,10 @@ convert-source-map@^1.1.0: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -1012,6 +1241,21 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" +crypto-browserify@^3.0.0: + version "3.11.1" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f" + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + crypto-browserify@~3.11.0: version "3.11.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522" @@ -1070,6 +1314,23 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +datatables.net-bs@^1.10.15: + version "1.10.16" + resolved "https://registry.yarnpkg.com/datatables.net-bs/-/datatables.net-bs-1.10.16.tgz#b0854f5b374f713ae3db4156c7cea8a760c3de76" + dependencies: + datatables.net "1.10.16" + jquery ">=1.7" + +datatables.net@1.10.16, datatables.net@^1.10.15: + version "1.10.16" + resolved "https://registry.yarnpkg.com/datatables.net/-/datatables.net-1.10.16.tgz#4b052d1082824261b68eed9d22741b711d3d2469" + dependencies: + jquery ">=1.7" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + date-utils@~1.2.17: version "1.2.21" resolved "https://registry.yarnpkg.com/date-utils/-/date-utils-1.2.21.tgz#61fb16cdc1274b3c9acaaffe9fc69df8720a2b64" @@ -1135,6 +1396,15 @@ deppack@~0.4.0: node-browser-modules "^0.1.0" "true-case-path" "^1.0.2" +deps-sort@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" + dependencies: + JSONStream "^1.0.3" + shasum "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -1158,7 +1428,7 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" -detective@^4.3.1: +detective@^4.0.0, detective@^4.3.1: version "4.5.0" resolved "https://registry.yarnpkg.com/detective/-/detective-4.5.0.tgz#6e5a8c6b26e6c7a254b1c6b6d7490d98ec91edd1" dependencies: @@ -1173,10 +1443,24 @@ diffie-hellman@^5.0.0: miller-rabin "^4.0.0" randombytes "^2.0.0" -domain-browser@~1.1.7: +domain-browser@~1.1.0, domain-browser@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" +domhelper@~0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/domhelper/-/domhelper-0.9.1.tgz#26554e5bac2c9e9585dca500978df5067d64bd00" + dependencies: + browserify ">=3.46.0" + classie ">=0.0.1" + util-extend "^1.0.1" + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + dependencies: + readable-stream "^2.0.2" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -1233,6 +1517,10 @@ etag@~1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.0.tgz#6f631aef336d6c46362b51764044ce216be3c051" +eve-raphael@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30" + events@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" @@ -1312,6 +1600,10 @@ fast-levenshtein@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz#e6a754cc8f15e58987aa9cbd27af66fd6f4e5af9" +fastclick@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/fastclick/-/fastclick-1.0.6.tgz#161625b27b1a5806405936bda9a2c1926d06be6a" + fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" @@ -1362,10 +1654,18 @@ findup-sync@^0.4.2: micromatch "^2.3.7" resolve-dir "^0.1.0" +flot@^0.8.0-alpha: + version "0.8.0-alpha" + resolved "https://registry.yarnpkg.com/flot/-/flot-0.8.0-alpha.tgz#9cbbc7147c10a47d2549db90bd2987ec1ba784ba" + fn-args@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fn-args/-/fn-args-1.0.0.tgz#974dafa1aeac4ac7c21fa09cc3b80f650106ed32" +font-awesome@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -1434,6 +1734,17 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: mkdirp ">=0.5 0" rimraf "2" +fullcalendar@^3.4.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/fullcalendar/-/fullcalendar-3.5.1.tgz#c70d642ca18d2854fbb97a9b4f5eecef6aa3e884" + dependencies: + jquery "2 - 3" + moment "^2.9.0" + +function-bind@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1507,6 +1818,17 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@~7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-modules@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" @@ -1578,6 +1900,12 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" +has@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + hash-base@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" @@ -1628,6 +1956,10 @@ hosted-git-info@^2.1.4, hosted-git-info@~2.1.4: version "2.1.5" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.1.5.tgz#0ba81d90da2e25ab34a332e6ec77936e1598118b" +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" + http-errors@~1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257" @@ -1645,6 +1977,10 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + https-browserify@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" @@ -1678,7 +2014,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -1700,6 +2036,29 @@ init-skeleton@~0.9.0: ncp "^2.0.0" normalize-git-url "~3.0.1" +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" + dependencies: + source-map "~0.5.3" + +inputmask@^3.3.7: + version "3.3.8" + resolved "https://registry.yarnpkg.com/inputmask/-/inputmask-3.3.8.tgz#a29c6a24083ced712361be47a7d6c750efd2bb78" + +insert-module-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.0.1.tgz#c03bf4e01cb086d5b5e5ace8ad0afe7889d638c3" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.7.1" + concat-stream "~1.5.1" + is-buffer "^1.1.0" + lexical-scope "^1.2.0" + process "~0.11.0" + through2 "^2.0.0" + xtend "^4.0.0" + invariant@^2.2.0: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -1710,6 +2069,16 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +ion-rangeslider@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ion-rangeslider/-/ion-rangeslider-2.2.0.tgz#388f12cd70593a61b3368fad6c4f30a5da8b97c9" + dependencies: + jquery ">=1.8" + +ionicons@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-3.0.0.tgz#40b8daf4fd7a31150bd002160f66496e22a98c3c" + ipaddr.js@1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec" @@ -1724,7 +2093,7 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" -is-buffer@^1.1.5: +is-buffer@^1.1.0, is-buffer@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" @@ -1804,6 +2173,10 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +isarray@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1830,7 +2203,23 @@ jodid25519@^1.0.0: dependencies: jsbn "~0.1.0" -jquery@^3.2.1: +jquery-knob@^1.2.11: + version "1.2.11" + resolved "https://registry.yarnpkg.com/jquery-knob/-/jquery-knob-1.2.11.tgz#f37c39dbc1c7a6a6c12cdb2ed4f6bffb683f10d6" + +jquery-mousewheel@~3.1.13: + version "3.1.13" + resolved "https://registry.yarnpkg.com/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz#06f0335f16e353a695e7206bf50503cb523a6ee5" + +jquery-sparkline@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jquery-sparkline/-/jquery-sparkline-2.4.0.tgz#1be8b7b704dd3857152708aefb1d4a4b3a69fb33" + +jquery-ui@^1.12.1: + version "1.12.1" + resolved "https://registry.yarnpkg.com/jquery-ui/-/jquery-ui-1.12.1.tgz#bcb4045c8dd0539c134bc1488cdd3e768a7a9e51" + +"jquery@2 - 3", jquery@>=1.10, jquery@>=1.5, jquery@>=1.7, "jquery@>=1.7.1 <4.0.0", jquery@>=1.8, jquery@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787" @@ -1864,6 +2253,12 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" + dependencies: + jsonify "~0.0.0" + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -1876,6 +2271,10 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + jsprim@^1.2.2: version "1.4.0" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" @@ -1885,12 +2284,26 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.3.6" +jvectormap@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jvectormap/-/jvectormap-1.2.2.tgz#2e4408b24a60473ff106c1e7243e375ae5ca85da" + dependencies: + jquery ">=1.5" + kind-of@^3.0.2: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: is-buffer "^1.1.5" +labeled-stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.0.tgz#a52e1d138024c00b86b1c0c91f677918b8ae0a59" + dependencies: + inherits "^2.0.1" + isarray "~0.0.1" + stream-splicer "^2.0.0" + lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -1901,6 +2314,12 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +lexical-scope@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/lexical-scope/-/lexical-scope-1.2.0.tgz#fcea5edc704a4b3a8796cdca419c3a0afaf22df4" + dependencies: + astw "^2.0.0" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -1924,6 +2343,10 @@ lodash.clonedeep@^4.3.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" + lodash@^4.0.0, lodash@^4.15.0, lodash@^4.2.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2053,7 +2476,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -2063,7 +2486,7 @@ minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.1.3, minimist@^1.2.0: +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -2073,6 +2496,34 @@ minimist@^1.1.3, minimist@^1.2.0: dependencies: minimist "0.0.8" +module-deps@^4.0.8: + version "4.1.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" + concat-stream "~1.5.0" + defined "^1.0.0" + detective "^4.0.0" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.1.3" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + +moment@^2.18.1, moment@^2.9.0: + version "2.18.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" + +morris.js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/morris.js/-/morris.js-0.5.0.tgz#725767135cfae059aae75999bb2ce6a1c5d1b44b" + mout@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/mout/-/mout-1.0.0.tgz#9bdf1d4af57d66d47cb353a6335a3281098e1501" @@ -2252,6 +2703,10 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" +os-browserify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" + os-browserify@~0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" @@ -2277,6 +2732,22 @@ osenv@0, osenv@^0.1.3, osenv@^0.1.4: os-homedir "^1.0.0" os-tmpdir "^1.0.0" +pace@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/pace/-/pace-0.0.4.tgz#d66405d5f5bc12d25441a6e26c878dbc69e77a77" + dependencies: + charm "~0.1.0" + +pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + dependencies: + path-platform "~0.11.15" + parse-asn1@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712" @@ -2324,6 +2795,14 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -2473,7 +2952,7 @@ punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" -punycode@^1.4.1, punycode@~1.4.0: +punycode@^1.3.2, punycode@^1.4.1, punycode@~1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -2490,7 +2969,7 @@ qs@6.4.0, qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -querystring-es3@~0.2.1: +querystring-es3@~0.2.0, querystring-es3@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" @@ -2525,6 +3004,12 @@ range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" +raphael@^2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/raphael/-/raphael-2.2.7.tgz#231b19141f8d086986d8faceb66f8b562ee2c810" + dependencies: + eve-raphael "0.5.0" + rc@^1.1.7: version "1.2.1" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" @@ -2540,6 +3025,12 @@ read-components@~0.7.0: dependencies: async-each "~1.0.0" +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" + dependencies: + readable-stream "^2.0.2" + read-pkg-up@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" @@ -2567,7 +3058,19 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: string_decoder "~1.0.0" util-deprecate "~1.0.1" -readable-stream@~2.0.5: +readable-stream@^2.1.5, readable-stream@^2.2.6: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +readable-stream@~2.0.0, readable-stream@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" dependencies: @@ -2707,6 +3210,12 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" +resolve@^1.1.3, resolve@^1.1.4: + version "1.4.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" + dependencies: + path-parse "^1.0.5" + right-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" @@ -2730,6 +3239,10 @@ safe-buffer@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + sass-brunch@^2.10.4: version "2.10.4" resolved "https://registry.yarnpkg.com/sass-brunch/-/sass-brunch-2.10.4.tgz#36bb0f08f223df7dac1363bc05ad5ac32d3013d8" @@ -2757,6 +3270,13 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" +select2@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/select2/-/select2-4.0.3.tgz#207733fe91eacb9cb1a13f12463401f472449e0f" + dependencies: + almond "~0.3.1" + jquery-mousewheel "~3.1.13" + select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" @@ -2818,6 +3338,29 @@ sha.js@^2.4.0, sha.js@^2.4.8: dependencies: inherits "^2.0.1" +sha.js@~2.4.4: + version "2.4.9" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + signal-exit@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -2836,6 +3379,15 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slimscroll@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/slimscroll/-/slimscroll-0.9.1.tgz#f675cdc601d80ada20f16004d227d156fd1187b2" + dependencies: + browserify ">=3.46.0" + classie ">=0.0.1" + domhelper "~0.9.0" + util-extend "^1.0.1" + sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -2858,6 +3410,10 @@ source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" +source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + spdx-correct@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" @@ -2891,13 +3447,30 @@ sshpk@^1.7.0: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" -stream-browserify@~2.0.1: +stream-browserify@^2.0.0, stream-browserify@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" dependencies: inherits "~2.0.1" readable-stream "^2.0.2" +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + +stream-http@^2.0.0: + version "2.7.2" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.7.2.tgz#40a050ec8dc3b53b33d9909415c02c0bf1abfbad" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.2.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + stream-http@~2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.1.1.tgz#3b880303babe036d6f6b43127d4dcd6f8893e1db" @@ -2907,6 +3480,13 @@ stream-http@~2.1.0: to-arraybuffer "^1.0.0" xtend "^4.0.0" +stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" + string-hash@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -2929,6 +3509,12 @@ string_decoder@~1.0.0: dependencies: safe-buffer "^5.0.1" +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -2955,6 +3541,12 @@ strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + dependencies: + minimist "^1.1.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -2965,6 +3557,12 @@ supports-color@^3.1.2, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" +syntax-error@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.3.0.tgz#1ed9266c4d40be75dc55bf9bb1cb77062bb96ca1" + dependencies: + acorn "^4.0.3" + tar-pack@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" @@ -2986,7 +3584,18 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" -timers-browserify@~1.4.2: +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timers-browserify@^1.0.1, timers-browserify@~1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" dependencies: @@ -3045,6 +3654,10 @@ type-is@~1.6.15: media-typer "0.3.0" mime-types "~2.1.15" +typedarray@~0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + uglify-js-brunch@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/uglify-js-brunch/-/uglify-js-brunch-2.0.1.tgz#bf55ba28df5e4ee5083bf7e3964d88eb4aabca13" @@ -3068,6 +3681,10 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" +umd@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.1.tgz#8ae556e11011f63c2596708a8837259f01b3d60e" + unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -3089,7 +3706,11 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -util@0.10.3, util@~0.10.3: +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + +util@0.10.3, util@~0.10.1, util@~0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" dependencies: @@ -3120,7 +3741,7 @@ verror@1.3.6: dependencies: extsprintf "1.0.2" -vm-browserify@~0.0.4: +vm-browserify@~0.0.1, vm-browserify@~0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" dependencies: @@ -3165,7 +3786,7 @@ wrappy@1, wrappy@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -xtend@^4.0.0: +xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From 8a9b6f7254aa434902c246bca260f65924425e1e Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sat, 30 Sep 2017 16:19:29 +0200 Subject: [PATCH 04/55] updated brunch config to include dashboard --- brunch-config.js | 10 +- priv/static/css/toolbar.css | 6726 ++++++++++- priv/static/js/toolbar.js | 21234 +++++++++++++++++++++++++++++++++- 3 files changed, 27956 insertions(+), 14 deletions(-) diff --git a/brunch-config.js b/brunch-config.js index 8f5b76e..83b3650 100644 --- a/brunch-config.js +++ b/brunch-config.js @@ -2,13 +2,16 @@ exports.config = { // See http://brunch.io/#documentation for docs. files: { javascripts: { - joinTo: { - "js/toolbar.js": /^(web\/static\/js\/toolbar)|^node_modules/, + // build output file based on required dependencies in entrypoint + entryPoints: { + "web/static/js/dashboard.js": "js/dashboard.js", + "web/static/js/toolbar.js": "js/toolbar.js", } }, stylesheets: { joinTo: { "css/toolbar.css": /^(web\/static\/css\/toolbar)|^node_modules/, + "css/dashboard.css": /^(web\/static\/css\/dashboard)|^node_modules/, }, order: { after: /prism/ @@ -66,7 +69,8 @@ exports.config = { modules: { autoRequire: { - "js/toolbar.js": ["web/static/js/toolbar"] + "js/toolbar.js": ["web/static/js/toolbar"], + "js/dashboard.js": ["web/static/js/dashboard"] } }, diff --git a/priv/static/css/toolbar.css b/priv/static/css/toolbar.css index f395efd..63e4e35 100644 --- a/priv/static/css/toolbar.css +++ b/priv/static/css/toolbar.css @@ -1,5 +1,6727 @@ -#ex-debug-toolbar{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857;color:#333;background-color:#fff/*! +@charset "UTF-8"; +#ex-debug-toolbar { + /** + * modified version of eric meyer's reset 2.0 + * http://meyerweb.com/eric/tools/css/reset/ + */ + /** + * basic reset + */ + /** + * HTML5 display-role reset for older browsers + */ + /** + * modified version of normalize.css 3.0.2 + * http://necolas.github.io/normalize.css/ + */ + /** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + /** + * HTML5 display definitions + * ============================================================================= + */ + /** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + /** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + /** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + /** + * Links + * ============================================================================= + */ + /** + * Remove the gray background color from active links in IE 10. + */ + /** + * Improve readability when focused and also mouse hovered in all browsers. + */ + /** + * Text-level semantics + * ============================================================================= + */ + /** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + /** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + /** + * 1. Address styling not present in Safari and Chrome. + * 2. Set previously resetted italic font-style + */ + /** + * Address styling not present in IE 8/9. + */ + /** + * Address inconsistent and variable font size in all browsers. + */ + /** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + /** + * Embedded content + * ============================================================================= + */ + /** + * Remove border when inside `a` element in IE 8/9/10. + */ + /** + * Correct overflow not hidden in IE 9/10/11. + */ + /** + * Grouping content + * ============================================================================= + */ + /** + * Address differences between Firefox and other browsers. + */ + /** + * Contain overflow in all browsers. + */ + /** + * Address odd `em`-unit font size rendering in all browsers. + */ + /** + * Forms + * ============================================================================= + */ + /** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + /** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + /** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + /** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + /** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + /** + * Re-set default cursor for disabled elements. + */ + /** + * Remove inner padding and border in Firefox 4+. + */ + /** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + /** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + /** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + /** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + /** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + /** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + /** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857; + color: #333333; + background-color: #fff; + /*! * 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 *//*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */}#ex-debug-toolbar ::before{all:unset}#ex-debug-toolbar ::after{all:unset}#ex-debug-toolbar ::hover{all:unset}#ex-debug-toolbar ::visited{all:unset}#ex-debug-toolbar ::link{all:unset}#ex-debug-toolbar ::active{all:unset}#ex-debug-toolbar *{max-width:inherit;max-height:inherit}#ex-debug-toolbar .container-fluid *{background:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar a,#ex-debug-toolbar abbr,#ex-debug-toolbar acronym,#ex-debug-toolbar address,#ex-debug-toolbar applet,#ex-debug-toolbar article,#ex-debug-toolbar aside,#ex-debug-toolbar audio,#ex-debug-toolbar b,#ex-debug-toolbar big,#ex-debug-toolbar blockquote,#ex-debug-toolbar body,#ex-debug-toolbar canvas,#ex-debug-toolbar caption,#ex-debug-toolbar center,#ex-debug-toolbar cite,#ex-debug-toolbar code,#ex-debug-toolbar dd,#ex-debug-toolbar del,#ex-debug-toolbar details,#ex-debug-toolbar dfn,#ex-debug-toolbar div,#ex-debug-toolbar dl,#ex-debug-toolbar dt,#ex-debug-toolbar em,#ex-debug-toolbar embed,#ex-debug-toolbar fieldset,#ex-debug-toolbar figcaption,#ex-debug-toolbar figure,#ex-debug-toolbar footer,#ex-debug-toolbar form,#ex-debug-toolbar h1,#ex-debug-toolbar h2,#ex-debug-toolbar h3,#ex-debug-toolbar h4,#ex-debug-toolbar h5,#ex-debug-toolbar h6,#ex-debug-toolbar header,#ex-debug-toolbar html,#ex-debug-toolbar i,#ex-debug-toolbar iframe,#ex-debug-toolbar img,#ex-debug-toolbar ins,#ex-debug-toolbar kbd,#ex-debug-toolbar label,#ex-debug-toolbar legend,#ex-debug-toolbar li,#ex-debug-toolbar main,#ex-debug-toolbar mark,#ex-debug-toolbar menu,#ex-debug-toolbar nav,#ex-debug-toolbar object,#ex-debug-toolbar ol,#ex-debug-toolbar output,#ex-debug-toolbar p,#ex-debug-toolbar pre,#ex-debug-toolbar q,#ex-debug-toolbar ruby,#ex-debug-toolbar s,#ex-debug-toolbar samp,#ex-debug-toolbar section,#ex-debug-toolbar small,#ex-debug-toolbar span,#ex-debug-toolbar strike,#ex-debug-toolbar strong,#ex-debug-toolbar sub,#ex-debug-toolbar summary,#ex-debug-toolbar sup,#ex-debug-toolbar table,#ex-debug-toolbar tbody,#ex-debug-toolbar td,#ex-debug-toolbar tfoot,#ex-debug-toolbar th,#ex-debug-toolbar thead,#ex-debug-toolbar time,#ex-debug-toolbar tr,#ex-debug-toolbar tt,#ex-debug-toolbar u,#ex-debug-toolbar ul,#ex-debug-toolbar var,#ex-debug-toolbar video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}#ex-debug-toolbar article,#ex-debug-toolbar aside,#ex-debug-toolbar details,#ex-debug-toolbar figcaption,#ex-debug-toolbar figure,#ex-debug-toolbar footer,#ex-debug-toolbar header,#ex-debug-toolbar main,#ex-debug-toolbar menu,#ex-debug-toolbar nav,#ex-debug-toolbar section,#ex-debug-toolbar summary{display:block}#ex-debug-toolbar body{line-height:1}#ex-debug-toolbar ol,#ex-debug-toolbar ul{list-style:none}#ex-debug-toolbar blockquote,#ex-debug-toolbar q{quotes:none}#ex-debug-toolbar blockquote:after,#ex-debug-toolbar blockquote:before,#ex-debug-toolbar q:after,#ex-debug-toolbar q:before{content:'';content:none}#ex-debug-toolbar table{border-collapse:collapse;border-spacing:0}#ex-debug-toolbar html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}#ex-debug-toolbar audio,#ex-debug-toolbar canvas,#ex-debug-toolbar progress,#ex-debug-toolbar video{display:inline-block;vertical-align:baseline}#ex-debug-toolbar audio:not([controls]){display:none;height:0}#ex-debug-toolbar [hidden],#ex-debug-toolbar template{display:none}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar a{background-color:transparent}#ex-debug-toolbar .navbar-nav.nav>li>span:active,#ex-debug-toolbar .navbar-nav.nav>li>span:hover,#ex-debug-toolbar a:active,#ex-debug-toolbar a:hover{outline:0}#ex-debug-toolbar abbr[title]{border-bottom:1px dotted}#ex-debug-toolbar b,#ex-debug-toolbar strong{font-weight:700}#ex-debug-toolbar dfn,#ex-debug-toolbar em,#ex-debug-toolbar i{font-style:italic}#ex-debug-toolbar mark{background:#ff0;color:#000}#ex-debug-toolbar small{font-size:80%}#ex-debug-toolbar sub,#ex-debug-toolbar sup{font-size:75%;line-height:0;position:relative}#ex-debug-toolbar sup{top:-.5em}#ex-debug-toolbar sub{bottom:-.25em}#ex-debug-toolbar img{border:0}#ex-debug-toolbar svg:not(:root){overflow:hidden}#ex-debug-toolbar hr{box-sizing:content-box;height:0}#ex-debug-toolbar pre{overflow:auto}#ex-debug-toolbar code,#ex-debug-toolbar kbd,#ex-debug-toolbar pre,#ex-debug-toolbar samp{font-family:monospace,monospace}#ex-debug-toolbar button,#ex-debug-toolbar input,#ex-debug-toolbar optgroup,#ex-debug-toolbar select,#ex-debug-toolbar textarea{color:inherit;font:inherit;margin:0}#ex-debug-toolbar button{overflow:visible}#ex-debug-toolbar button,#ex-debug-toolbar select{text-transform:none}#ex-debug-toolbar button,#ex-debug-toolbar html input[type=button],#ex-debug-toolbar input[type=reset],#ex-debug-toolbar input[type=submit]{-webkit-appearance:button;cursor:pointer}#ex-debug-toolbar button[disabled],#ex-debug-toolbar html input[disabled]{cursor:default}#ex-debug-toolbar button::-moz-focus-inner,#ex-debug-toolbar input::-moz-focus-inner{border:0;padding:0}#ex-debug-toolbar input{line-height:normal}#ex-debug-toolbar input[type=checkbox],#ex-debug-toolbar input[type=radio]{padding:0}#ex-debug-toolbar input[type=number]::-webkit-inner-spin-button,#ex-debug-toolbar input[type=number]::-webkit-outer-spin-button{height:auto}#ex-debug-toolbar input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}#ex-debug-toolbar input[type=search]::-webkit-search-cancel-button,#ex-debug-toolbar input[type=search]::-webkit-search-decoration{-webkit-appearance:none}#ex-debug-toolbar textarea{overflow:auto}#ex-debug-toolbar optgroup{font-weight:700}#ex-debug-toolbar html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}#ex-debug-toolbar body{margin:0}#ex-debug-toolbar article,#ex-debug-toolbar aside,#ex-debug-toolbar details,#ex-debug-toolbar figcaption,#ex-debug-toolbar figure,#ex-debug-toolbar footer,#ex-debug-toolbar header,#ex-debug-toolbar hgroup,#ex-debug-toolbar main,#ex-debug-toolbar menu,#ex-debug-toolbar nav,#ex-debug-toolbar section,#ex-debug-toolbar summary{display:block}#ex-debug-toolbar audio,#ex-debug-toolbar canvas,#ex-debug-toolbar progress,#ex-debug-toolbar video{display:inline-block;vertical-align:baseline}#ex-debug-toolbar audio:not([controls]){display:none;height:0}#ex-debug-toolbar [hidden],#ex-debug-toolbar template{display:none}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar a{background-color:transparent}#ex-debug-toolbar .navbar-nav.nav>li>span:active,#ex-debug-toolbar .navbar-nav.nav>li>span:hover,#ex-debug-toolbar a:active,#ex-debug-toolbar a:hover{outline:0}#ex-debug-toolbar abbr[title]{border-bottom:1px dotted}#ex-debug-toolbar b,#ex-debug-toolbar strong{font-weight:700}#ex-debug-toolbar dfn{font-style:italic}#ex-debug-toolbar h1{font-size:2em;margin:.67em 0}#ex-debug-toolbar mark{background:#ff0;color:#000}#ex-debug-toolbar small{font-size:80%}#ex-debug-toolbar sub,#ex-debug-toolbar sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}#ex-debug-toolbar sup{top:-.5em}#ex-debug-toolbar sub{bottom:-.25em}#ex-debug-toolbar img{border:0}#ex-debug-toolbar svg:not(:root){overflow:hidden}#ex-debug-toolbar figure{margin:1em 40px}#ex-debug-toolbar hr{box-sizing:content-box;height:0}#ex-debug-toolbar pre{overflow:auto}#ex-debug-toolbar code,#ex-debug-toolbar kbd,#ex-debug-toolbar pre,#ex-debug-toolbar samp{font-family:monospace,monospace;font-size:1em}#ex-debug-toolbar button,#ex-debug-toolbar input,#ex-debug-toolbar optgroup,#ex-debug-toolbar select,#ex-debug-toolbar textarea{color:inherit;font:inherit;margin:0}#ex-debug-toolbar button{overflow:visible}#ex-debug-toolbar button,#ex-debug-toolbar select{text-transform:none}#ex-debug-toolbar button,#ex-debug-toolbar html input[type=button],#ex-debug-toolbar input[type=reset],#ex-debug-toolbar input[type=submit]{-webkit-appearance:button;cursor:pointer}#ex-debug-toolbar button[disabled],#ex-debug-toolbar html input[disabled]{cursor:default}#ex-debug-toolbar button::-moz-focus-inner,#ex-debug-toolbar input::-moz-focus-inner{border:0;padding:0}#ex-debug-toolbar input{line-height:normal}#ex-debug-toolbar input[type=checkbox],#ex-debug-toolbar input[type=radio]{box-sizing:border-box;padding:0}#ex-debug-toolbar input[type=number]::-webkit-inner-spin-button,#ex-debug-toolbar input[type=number]::-webkit-outer-spin-button{height:auto}#ex-debug-toolbar input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}#ex-debug-toolbar input[type=search]::-webkit-search-cancel-button,#ex-debug-toolbar input[type=search]::-webkit-search-decoration{-webkit-appearance:none}#ex-debug-toolbar fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}#ex-debug-toolbar legend{border:0;padding:0}#ex-debug-toolbar textarea{overflow:auto}#ex-debug-toolbar optgroup{font-weight:700}#ex-debug-toolbar table{border-collapse:collapse;border-spacing:0}#ex-debug-toolbar td,#ex-debug-toolbar th{padding:0}@media print{#ex-debug-toolbar *,#ex-debug-toolbar :after,#ex-debug-toolbar :before{background:0 0!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar .navbar-nav.nav>li>span:visited,#ex-debug-toolbar a,#ex-debug-toolbar a:visited{text-decoration:underline}#ex-debug-toolbar .navbar-nav.nav>li>span[href]:after,#ex-debug-toolbar a[href]:after{content:" (" attr(href) ")"}#ex-debug-toolbar abbr[title]:after{content:" (" attr(title) ")"}#ex-debug-toolbar .navbar-nav.nav>li>span[href^="#"]:after,#ex-debug-toolbar .navbar-nav.nav>li>span[href^="javascript:"]:after,#ex-debug-toolbar a[href^="#"]:after,#ex-debug-toolbar a[href^="javascript:"]:after{content:""}#ex-debug-toolbar blockquote,#ex-debug-toolbar pre{border:1px solid #999;page-break-inside:avoid}#ex-debug-toolbar thead{display:table-header-group}#ex-debug-toolbar img,#ex-debug-toolbar tr{page-break-inside:avoid}#ex-debug-toolbar img{max-width:100%!important}#ex-debug-toolbar h2,#ex-debug-toolbar h3,#ex-debug-toolbar p{orphans:3;widows:3}#ex-debug-toolbar h2,#ex-debug-toolbar h3{page-break-after:avoid}#ex-debug-toolbar .navbar{display:none}#ex-debug-toolbar .btn>.caret,#ex-debug-toolbar .dropup>.btn>.caret{border-top-color:#000!important}#ex-debug-toolbar .label{border:1px solid #000}#ex-debug-toolbar .table{border-collapse:collapse!important}#ex-debug-toolbar .table td,#ex-debug-toolbar .table th{background-color:#fff!important}#ex-debug-toolbar .table-bordered td,#ex-debug-toolbar .table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/bootstrap/glyphicons-halflings-regular.eot);src:url(../fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix) format("embedded-opentype"),url(../fonts/bootstrap/glyphicons-halflings-regular.woff2) format("woff2"),url(../fonts/bootstrap/glyphicons-halflings-regular.woff) format("woff"),url(../fonts/bootstrap/glyphicons-halflings-regular.ttf) format("truetype"),url(../fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format("svg")}#ex-debug-toolbar .glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#ex-debug-toolbar .glyphicon-asterisk:before{content:"\002a"}#ex-debug-toolbar .glyphicon-plus:before{content:"\002b"}#ex-debug-toolbar .glyphicon-eur:before,#ex-debug-toolbar .glyphicon-euro:before{content:"\20ac"}#ex-debug-toolbar .glyphicon-minus:before{content:"\2212"}#ex-debug-toolbar .glyphicon-cloud:before{content:"\2601"}#ex-debug-toolbar .glyphicon-envelope:before{content:"\2709"}#ex-debug-toolbar .glyphicon-pencil:before{content:"\270f"}#ex-debug-toolbar .glyphicon-glass:before{content:"\e001"}#ex-debug-toolbar .glyphicon-music:before{content:"\e002"}#ex-debug-toolbar .glyphicon-search:before{content:"\e003"}#ex-debug-toolbar .glyphicon-heart:before{content:"\e005"}#ex-debug-toolbar .glyphicon-star:before{content:"\e006"}#ex-debug-toolbar .glyphicon-star-empty:before{content:"\e007"}#ex-debug-toolbar .glyphicon-user:before{content:"\e008"}#ex-debug-toolbar .glyphicon-film:before{content:"\e009"}#ex-debug-toolbar .glyphicon-th-large:before{content:"\e010"}#ex-debug-toolbar .glyphicon-th:before{content:"\e011"}#ex-debug-toolbar .glyphicon-th-list:before{content:"\e012"}#ex-debug-toolbar .glyphicon-ok:before{content:"\e013"}#ex-debug-toolbar .glyphicon-remove:before{content:"\e014"}#ex-debug-toolbar .glyphicon-zoom-in:before{content:"\e015"}#ex-debug-toolbar .glyphicon-zoom-out:before{content:"\e016"}#ex-debug-toolbar .glyphicon-off:before{content:"\e017"}#ex-debug-toolbar .glyphicon-signal:before{content:"\e018"}#ex-debug-toolbar .glyphicon-cog:before{content:"\e019"}#ex-debug-toolbar .glyphicon-trash:before{content:"\e020"}#ex-debug-toolbar .glyphicon-home:before{content:"\e021"}#ex-debug-toolbar .glyphicon-file:before{content:"\e022"}#ex-debug-toolbar .glyphicon-time:before{content:"\e023"}#ex-debug-toolbar .glyphicon-road:before{content:"\e024"}#ex-debug-toolbar .glyphicon-download-alt:before{content:"\e025"}#ex-debug-toolbar .glyphicon-download:before{content:"\e026"}#ex-debug-toolbar .glyphicon-upload:before{content:"\e027"}#ex-debug-toolbar .glyphicon-inbox:before{content:"\e028"}#ex-debug-toolbar .glyphicon-play-circle:before{content:"\e029"}#ex-debug-toolbar .glyphicon-repeat:before{content:"\e030"}#ex-debug-toolbar .glyphicon-refresh:before{content:"\e031"}#ex-debug-toolbar .glyphicon-list-alt:before{content:"\e032"}#ex-debug-toolbar .glyphicon-lock:before{content:"\e033"}#ex-debug-toolbar .glyphicon-flag:before{content:"\e034"}#ex-debug-toolbar .glyphicon-headphones:before{content:"\e035"}#ex-debug-toolbar .glyphicon-volume-off:before{content:"\e036"}#ex-debug-toolbar .glyphicon-volume-down:before{content:"\e037"}#ex-debug-toolbar .glyphicon-volume-up:before{content:"\e038"}#ex-debug-toolbar .glyphicon-qrcode:before{content:"\e039"}#ex-debug-toolbar .glyphicon-barcode:before{content:"\e040"}#ex-debug-toolbar .glyphicon-tag:before{content:"\e041"}#ex-debug-toolbar .glyphicon-tags:before{content:"\e042"}#ex-debug-toolbar .glyphicon-book:before{content:"\e043"}#ex-debug-toolbar .glyphicon-bookmark:before{content:"\e044"}#ex-debug-toolbar .glyphicon-print:before{content:"\e045"}#ex-debug-toolbar .glyphicon-camera:before{content:"\e046"}#ex-debug-toolbar .glyphicon-font:before{content:"\e047"}#ex-debug-toolbar .glyphicon-bold:before{content:"\e048"}#ex-debug-toolbar .glyphicon-italic:before{content:"\e049"}#ex-debug-toolbar .glyphicon-text-height:before{content:"\e050"}#ex-debug-toolbar .glyphicon-text-width:before{content:"\e051"}#ex-debug-toolbar .glyphicon-align-left:before{content:"\e052"}#ex-debug-toolbar .glyphicon-align-center:before{content:"\e053"}#ex-debug-toolbar .glyphicon-align-right:before{content:"\e054"}#ex-debug-toolbar .glyphicon-align-justify:before{content:"\e055"}#ex-debug-toolbar .glyphicon-list:before{content:"\e056"}#ex-debug-toolbar .glyphicon-indent-left:before{content:"\e057"}#ex-debug-toolbar .glyphicon-indent-right:before{content:"\e058"}#ex-debug-toolbar .glyphicon-facetime-video:before{content:"\e059"}#ex-debug-toolbar .glyphicon-picture:before{content:"\e060"}#ex-debug-toolbar .glyphicon-map-marker:before{content:"\e062"}#ex-debug-toolbar .glyphicon-adjust:before{content:"\e063"}#ex-debug-toolbar .glyphicon-tint:before{content:"\e064"}#ex-debug-toolbar .glyphicon-edit:before{content:"\e065"}#ex-debug-toolbar .glyphicon-share:before{content:"\e066"}#ex-debug-toolbar .glyphicon-check:before{content:"\e067"}#ex-debug-toolbar .glyphicon-move:before{content:"\e068"}#ex-debug-toolbar .glyphicon-step-backward:before{content:"\e069"}#ex-debug-toolbar .glyphicon-fast-backward:before{content:"\e070"}#ex-debug-toolbar .glyphicon-backward:before{content:"\e071"}#ex-debug-toolbar .glyphicon-play:before{content:"\e072"}#ex-debug-toolbar .glyphicon-pause:before{content:"\e073"}#ex-debug-toolbar .glyphicon-stop:before{content:"\e074"}#ex-debug-toolbar .glyphicon-forward:before{content:"\e075"}#ex-debug-toolbar .glyphicon-fast-forward:before{content:"\e076"}#ex-debug-toolbar .glyphicon-step-forward:before{content:"\e077"}#ex-debug-toolbar .glyphicon-eject:before{content:"\e078"}#ex-debug-toolbar .glyphicon-chevron-left:before{content:"\e079"}#ex-debug-toolbar .glyphicon-chevron-right:before{content:"\e080"}#ex-debug-toolbar .glyphicon-plus-sign:before{content:"\e081"}#ex-debug-toolbar .glyphicon-minus-sign:before{content:"\e082"}#ex-debug-toolbar .glyphicon-remove-sign:before{content:"\e083"}#ex-debug-toolbar .glyphicon-ok-sign:before{content:"\e084"}#ex-debug-toolbar .glyphicon-question-sign:before{content:"\e085"}#ex-debug-toolbar .glyphicon-info-sign:before{content:"\e086"}#ex-debug-toolbar .glyphicon-screenshot:before{content:"\e087"}#ex-debug-toolbar .glyphicon-remove-circle:before{content:"\e088"}#ex-debug-toolbar .glyphicon-ok-circle:before{content:"\e089"}#ex-debug-toolbar .glyphicon-ban-circle:before{content:"\e090"}#ex-debug-toolbar .glyphicon-arrow-left:before{content:"\e091"}#ex-debug-toolbar .glyphicon-arrow-right:before{content:"\e092"}#ex-debug-toolbar .glyphicon-arrow-up:before{content:"\e093"}#ex-debug-toolbar .glyphicon-arrow-down:before{content:"\e094"}#ex-debug-toolbar .glyphicon-share-alt:before{content:"\e095"}#ex-debug-toolbar .glyphicon-resize-full:before{content:"\e096"}#ex-debug-toolbar .glyphicon-resize-small:before{content:"\e097"}#ex-debug-toolbar .glyphicon-exclamation-sign:before{content:"\e101"}#ex-debug-toolbar .glyphicon-gift:before{content:"\e102"}#ex-debug-toolbar .glyphicon-leaf:before{content:"\e103"}#ex-debug-toolbar .glyphicon-fire:before{content:"\e104"}#ex-debug-toolbar .glyphicon-eye-open:before{content:"\e105"}#ex-debug-toolbar .glyphicon-eye-close:before{content:"\e106"}#ex-debug-toolbar .glyphicon-warning-sign:before{content:"\e107"}#ex-debug-toolbar .glyphicon-plane:before{content:"\e108"}#ex-debug-toolbar .glyphicon-calendar:before{content:"\e109"}#ex-debug-toolbar .glyphicon-random:before{content:"\e110"}#ex-debug-toolbar .glyphicon-comment:before{content:"\e111"}#ex-debug-toolbar .glyphicon-magnet:before{content:"\e112"}#ex-debug-toolbar .glyphicon-chevron-up:before{content:"\e113"}#ex-debug-toolbar .glyphicon-chevron-down:before{content:"\e114"}#ex-debug-toolbar .glyphicon-retweet:before{content:"\e115"}#ex-debug-toolbar .glyphicon-shopping-cart:before{content:"\e116"}#ex-debug-toolbar .glyphicon-folder-close:before{content:"\e117"}#ex-debug-toolbar .glyphicon-folder-open:before{content:"\e118"}#ex-debug-toolbar .glyphicon-resize-vertical:before{content:"\e119"}#ex-debug-toolbar .glyphicon-resize-horizontal:before{content:"\e120"}#ex-debug-toolbar .glyphicon-hdd:before{content:"\e121"}#ex-debug-toolbar .glyphicon-bullhorn:before{content:"\e122"}#ex-debug-toolbar .glyphicon-bell:before{content:"\e123"}#ex-debug-toolbar .glyphicon-certificate:before{content:"\e124"}#ex-debug-toolbar .glyphicon-thumbs-up:before{content:"\e125"}#ex-debug-toolbar .glyphicon-thumbs-down:before{content:"\e126"}#ex-debug-toolbar .glyphicon-hand-right:before{content:"\e127"}#ex-debug-toolbar .glyphicon-hand-left:before{content:"\e128"}#ex-debug-toolbar .glyphicon-hand-up:before{content:"\e129"}#ex-debug-toolbar .glyphicon-hand-down:before{content:"\e130"}#ex-debug-toolbar .glyphicon-circle-arrow-right:before{content:"\e131"}#ex-debug-toolbar .glyphicon-circle-arrow-left:before{content:"\e132"}#ex-debug-toolbar .glyphicon-circle-arrow-up:before{content:"\e133"}#ex-debug-toolbar .glyphicon-circle-arrow-down:before{content:"\e134"}#ex-debug-toolbar .glyphicon-globe:before{content:"\e135"}#ex-debug-toolbar .glyphicon-wrench:before{content:"\e136"}#ex-debug-toolbar .glyphicon-tasks:before{content:"\e137"}#ex-debug-toolbar .glyphicon-filter:before{content:"\e138"}#ex-debug-toolbar .glyphicon-briefcase:before{content:"\e139"}#ex-debug-toolbar .glyphicon-fullscreen:before{content:"\e140"}#ex-debug-toolbar .glyphicon-dashboard:before{content:"\e141"}#ex-debug-toolbar .glyphicon-paperclip:before{content:"\e142"}#ex-debug-toolbar .glyphicon-heart-empty:before{content:"\e143"}#ex-debug-toolbar .glyphicon-link:before{content:"\e144"}#ex-debug-toolbar .glyphicon-phone:before{content:"\e145"}#ex-debug-toolbar .glyphicon-pushpin:before{content:"\e146"}#ex-debug-toolbar .glyphicon-usd:before{content:"\e148"}#ex-debug-toolbar .glyphicon-gbp:before{content:"\e149"}#ex-debug-toolbar .glyphicon-sort:before{content:"\e150"}#ex-debug-toolbar .glyphicon-sort-by-alphabet:before{content:"\e151"}#ex-debug-toolbar .glyphicon-sort-by-alphabet-alt:before{content:"\e152"}#ex-debug-toolbar .glyphicon-sort-by-order:before{content:"\e153"}#ex-debug-toolbar .glyphicon-sort-by-order-alt:before{content:"\e154"}#ex-debug-toolbar .glyphicon-sort-by-attributes:before{content:"\e155"}#ex-debug-toolbar .glyphicon-sort-by-attributes-alt:before{content:"\e156"}#ex-debug-toolbar .glyphicon-unchecked:before{content:"\e157"}#ex-debug-toolbar .glyphicon-expand:before{content:"\e158"}#ex-debug-toolbar .glyphicon-collapse-down:before{content:"\e159"}#ex-debug-toolbar .glyphicon-collapse-up:before{content:"\e160"}#ex-debug-toolbar .glyphicon-log-in:before{content:"\e161"}#ex-debug-toolbar .glyphicon-flash:before{content:"\e162"}#ex-debug-toolbar .glyphicon-log-out:before{content:"\e163"}#ex-debug-toolbar .glyphicon-new-window:before{content:"\e164"}#ex-debug-toolbar .glyphicon-record:before{content:"\e165"}#ex-debug-toolbar .glyphicon-save:before{content:"\e166"}#ex-debug-toolbar .glyphicon-open:before{content:"\e167"}#ex-debug-toolbar .glyphicon-saved:before{content:"\e168"}#ex-debug-toolbar .glyphicon-import:before{content:"\e169"}#ex-debug-toolbar .glyphicon-export:before{content:"\e170"}#ex-debug-toolbar .glyphicon-send:before{content:"\e171"}#ex-debug-toolbar .glyphicon-floppy-disk:before{content:"\e172"}#ex-debug-toolbar .glyphicon-floppy-saved:before{content:"\e173"}#ex-debug-toolbar .glyphicon-floppy-remove:before{content:"\e174"}#ex-debug-toolbar .glyphicon-floppy-save:before{content:"\e175"}#ex-debug-toolbar .glyphicon-floppy-open:before{content:"\e176"}#ex-debug-toolbar .glyphicon-credit-card:before{content:"\e177"}#ex-debug-toolbar .glyphicon-transfer:before{content:"\e178"}#ex-debug-toolbar .glyphicon-cutlery:before{content:"\e179"}#ex-debug-toolbar .glyphicon-header:before{content:"\e180"}#ex-debug-toolbar .glyphicon-compressed:before{content:"\e181"}#ex-debug-toolbar .glyphicon-earphone:before{content:"\e182"}#ex-debug-toolbar .glyphicon-phone-alt:before{content:"\e183"}#ex-debug-toolbar .glyphicon-tower:before{content:"\e184"}#ex-debug-toolbar .glyphicon-stats:before{content:"\e185"}#ex-debug-toolbar .glyphicon-sd-video:before{content:"\e186"}#ex-debug-toolbar .glyphicon-hd-video:before{content:"\e187"}#ex-debug-toolbar .glyphicon-subtitles:before{content:"\e188"}#ex-debug-toolbar .glyphicon-sound-stereo:before{content:"\e189"}#ex-debug-toolbar .glyphicon-sound-dolby:before{content:"\e190"}#ex-debug-toolbar .glyphicon-sound-5-1:before{content:"\e191"}#ex-debug-toolbar .glyphicon-sound-6-1:before{content:"\e192"}#ex-debug-toolbar .glyphicon-sound-7-1:before{content:"\e193"}#ex-debug-toolbar .glyphicon-copyright-mark:before{content:"\e194"}#ex-debug-toolbar .glyphicon-registration-mark:before{content:"\e195"}#ex-debug-toolbar .glyphicon-cloud-download:before{content:"\e197"}#ex-debug-toolbar .glyphicon-cloud-upload:before{content:"\e198"}#ex-debug-toolbar .glyphicon-tree-conifer:before{content:"\e199"}#ex-debug-toolbar .glyphicon-tree-deciduous:before{content:"\e200"}#ex-debug-toolbar .glyphicon-cd:before{content:"\e201"}#ex-debug-toolbar .glyphicon-save-file:before{content:"\e202"}#ex-debug-toolbar .glyphicon-open-file:before{content:"\e203"}#ex-debug-toolbar .glyphicon-level-up:before{content:"\e204"}#ex-debug-toolbar .glyphicon-copy:before{content:"\e205"}#ex-debug-toolbar .glyphicon-paste:before{content:"\e206"}#ex-debug-toolbar .glyphicon-alert:before{content:"\e209"}#ex-debug-toolbar .glyphicon-equalizer:before{content:"\e210"}#ex-debug-toolbar .glyphicon-king:before{content:"\e211"}#ex-debug-toolbar .glyphicon-queen:before{content:"\e212"}#ex-debug-toolbar .glyphicon-pawn:before{content:"\e213"}#ex-debug-toolbar .glyphicon-bishop:before{content:"\e214"}#ex-debug-toolbar .glyphicon-knight:before{content:"\e215"}#ex-debug-toolbar .glyphicon-baby-formula:before{content:"\e216"}#ex-debug-toolbar .glyphicon-tent:before{content:"\26fa"}#ex-debug-toolbar .glyphicon-blackboard:before{content:"\e218"}#ex-debug-toolbar .glyphicon-bed:before{content:"\e219"}#ex-debug-toolbar .glyphicon-apple:before{content:"\f8ff"}#ex-debug-toolbar .glyphicon-erase:before{content:"\e221"}#ex-debug-toolbar .glyphicon-hourglass:before{content:"\231b"}#ex-debug-toolbar .glyphicon-lamp:before{content:"\e223"}#ex-debug-toolbar .glyphicon-duplicate:before{content:"\e224"}#ex-debug-toolbar .glyphicon-piggy-bank:before{content:"\e225"}#ex-debug-toolbar .glyphicon-scissors:before{content:"\e226"}#ex-debug-toolbar .glyphicon-bitcoin:before{content:"\e227"}#ex-debug-toolbar .glyphicon-btc:before{content:"\e227"}#ex-debug-toolbar .glyphicon-xbt:before{content:"\e227"}#ex-debug-toolbar .glyphicon-yen:before{content:"\00a5"}#ex-debug-toolbar .glyphicon-jpy:before{content:"\00a5"}#ex-debug-toolbar .glyphicon-ruble:before{content:"\20bd"}#ex-debug-toolbar .glyphicon-rub:before{content:"\20bd"}#ex-debug-toolbar .glyphicon-scale:before{content:"\e230"}#ex-debug-toolbar .glyphicon-ice-lolly:before{content:"\e231"}#ex-debug-toolbar .glyphicon-ice-lolly-tasted:before{content:"\e232"}#ex-debug-toolbar .glyphicon-education:before{content:"\e233"}#ex-debug-toolbar .glyphicon-option-horizontal:before{content:"\e234"}#ex-debug-toolbar .glyphicon-option-vertical:before{content:"\e235"}#ex-debug-toolbar .glyphicon-menu-hamburger:before{content:"\e236"}#ex-debug-toolbar .glyphicon-modal-window:before{content:"\e237"}#ex-debug-toolbar .glyphicon-oil:before{content:"\e238"}#ex-debug-toolbar .glyphicon-grain:before{content:"\e239"}#ex-debug-toolbar .glyphicon-sunglasses:before{content:"\e240"}#ex-debug-toolbar .glyphicon-text-size:before{content:"\e241"}#ex-debug-toolbar .glyphicon-text-color:before{content:"\e242"}#ex-debug-toolbar .glyphicon-text-background:before{content:"\e243"}#ex-debug-toolbar .glyphicon-object-align-top:before{content:"\e244"}#ex-debug-toolbar .glyphicon-object-align-bottom:before{content:"\e245"}#ex-debug-toolbar .glyphicon-object-align-horizontal:before{content:"\e246"}#ex-debug-toolbar .glyphicon-object-align-left:before{content:"\e247"}#ex-debug-toolbar .glyphicon-object-align-vertical:before{content:"\e248"}#ex-debug-toolbar .glyphicon-object-align-right:before{content:"\e249"}#ex-debug-toolbar .glyphicon-triangle-right:before{content:"\e250"}#ex-debug-toolbar .glyphicon-triangle-left:before{content:"\e251"}#ex-debug-toolbar .glyphicon-triangle-bottom:before{content:"\e252"}#ex-debug-toolbar .glyphicon-triangle-top:before{content:"\e253"}#ex-debug-toolbar .glyphicon-console:before{content:"\e254"}#ex-debug-toolbar .glyphicon-superscript:before{content:"\e255"}#ex-debug-toolbar .glyphicon-subscript:before{content:"\e256"}#ex-debug-toolbar .glyphicon-menu-left:before{content:"\e257"}#ex-debug-toolbar .glyphicon-menu-right:before{content:"\e258"}#ex-debug-toolbar .glyphicon-menu-down:before{content:"\e259"}#ex-debug-toolbar .glyphicon-menu-up:before{content:"\e260"}#ex-debug-toolbar *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#ex-debug-toolbar :after,#ex-debug-toolbar :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#ex-debug-toolbar html{font-size:10px;-webkit-tap-highlight-color:transparent}#ex-debug-toolbar body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857;color:#333;background-color:#fff}#ex-debug-toolbar button,#ex-debug-toolbar input,#ex-debug-toolbar select,#ex-debug-toolbar textarea{font-family:inherit;font-size:inherit;line-height:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar a{color:#337ab7;text-decoration:none}#ex-debug-toolbar .navbar-nav.nav>li>span:focus,#ex-debug-toolbar .navbar-nav.nav>li>span:hover,#ex-debug-toolbar a:focus,#ex-debug-toolbar a:hover{color:#23527c;text-decoration:underline}#ex-debug-toolbar .navbar-nav.nav>li>span:focus,#ex-debug-toolbar a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}#ex-debug-toolbar figure{margin:0}#ex-debug-toolbar img{vertical-align:middle}#ex-debug-toolbar .img-responsive{display:block;max-width:100%;height:auto}#ex-debug-toolbar .img-rounded{border-radius:6px}#ex-debug-toolbar .img-thumbnail{padding:4px;line-height:1.42857;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;display:inline-block;max-width:100%;height:auto}#ex-debug-toolbar .img-circle{border-radius:50%}#ex-debug-toolbar hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}#ex-debug-toolbar .sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}#ex-debug-toolbar .sr-only-focusable:active,#ex-debug-toolbar .sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}#ex-debug-toolbar [role=button]{cursor:pointer}#ex-debug-toolbar .h1,#ex-debug-toolbar .h2,#ex-debug-toolbar .h3,#ex-debug-toolbar .h4,#ex-debug-toolbar .h5,#ex-debug-toolbar .h6,#ex-debug-toolbar h1,#ex-debug-toolbar h2,#ex-debug-toolbar h3,#ex-debug-toolbar h4,#ex-debug-toolbar h5,#ex-debug-toolbar h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}#ex-debug-toolbar .h1 .small,#ex-debug-toolbar .h1 small,#ex-debug-toolbar .h2 .small,#ex-debug-toolbar .h2 small,#ex-debug-toolbar .h3 .small,#ex-debug-toolbar .h3 small,#ex-debug-toolbar .h4 .small,#ex-debug-toolbar .h4 small,#ex-debug-toolbar .h5 .small,#ex-debug-toolbar .h5 small,#ex-debug-toolbar .h6 .small,#ex-debug-toolbar .h6 small,#ex-debug-toolbar h1 .small,#ex-debug-toolbar h1 small,#ex-debug-toolbar h2 .small,#ex-debug-toolbar h2 small,#ex-debug-toolbar h3 .small,#ex-debug-toolbar h3 small,#ex-debug-toolbar h4 .small,#ex-debug-toolbar h4 small,#ex-debug-toolbar h5 .small,#ex-debug-toolbar h5 small,#ex-debug-toolbar h6 .small,#ex-debug-toolbar h6 small{font-weight:400;line-height:1;color:#777}#ex-debug-toolbar .h1,#ex-debug-toolbar .h2,#ex-debug-toolbar .h3,#ex-debug-toolbar h1,#ex-debug-toolbar h2,#ex-debug-toolbar h3{margin-top:20px;margin-bottom:10px}#ex-debug-toolbar .h1 .small,#ex-debug-toolbar .h1 small,#ex-debug-toolbar .h2 .small,#ex-debug-toolbar .h2 small,#ex-debug-toolbar .h3 .small,#ex-debug-toolbar .h3 small,#ex-debug-toolbar h1 .small,#ex-debug-toolbar h1 small,#ex-debug-toolbar h2 .small,#ex-debug-toolbar h2 small,#ex-debug-toolbar h3 .small,#ex-debug-toolbar h3 small{font-size:65%}#ex-debug-toolbar .h4,#ex-debug-toolbar .h5,#ex-debug-toolbar .h6,#ex-debug-toolbar h4,#ex-debug-toolbar h5,#ex-debug-toolbar h6{margin-top:10px;margin-bottom:10px}#ex-debug-toolbar .h4 .small,#ex-debug-toolbar .h4 small,#ex-debug-toolbar .h5 .small,#ex-debug-toolbar .h5 small,#ex-debug-toolbar .h6 .small,#ex-debug-toolbar .h6 small,#ex-debug-toolbar h4 .small,#ex-debug-toolbar h4 small,#ex-debug-toolbar h5 .small,#ex-debug-toolbar h5 small,#ex-debug-toolbar h6 .small,#ex-debug-toolbar h6 small{font-size:75%}#ex-debug-toolbar .h1,#ex-debug-toolbar h1{font-size:36px}#ex-debug-toolbar .h2,#ex-debug-toolbar h2{font-size:30px}#ex-debug-toolbar .h3,#ex-debug-toolbar h3{font-size:24px}#ex-debug-toolbar .h4,#ex-debug-toolbar h4{font-size:18px}#ex-debug-toolbar .h5,#ex-debug-toolbar h5{font-size:14px}#ex-debug-toolbar .h6,#ex-debug-toolbar h6{font-size:12px}#ex-debug-toolbar p{margin:0 0 10px}#ex-debug-toolbar .lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){#ex-debug-toolbar .lead{font-size:21px}}#ex-debug-toolbar .small,#ex-debug-toolbar small{font-size:85%}#ex-debug-toolbar .mark,#ex-debug-toolbar mark{background-color:#fcf8e3;padding:.2em}#ex-debug-toolbar .text-left{text-align:left}#ex-debug-toolbar .text-right{text-align:right}#ex-debug-toolbar .text-center{text-align:center}#ex-debug-toolbar .text-justify{text-align:justify}#ex-debug-toolbar .text-nowrap{white-space:nowrap}#ex-debug-toolbar .text-lowercase{text-transform:lowercase}#ex-debug-toolbar .initialism,#ex-debug-toolbar .text-uppercase{text-transform:uppercase}#ex-debug-toolbar .text-capitalize{text-transform:capitalize}#ex-debug-toolbar .text-muted{color:#777}#ex-debug-toolbar .text-primary{color:#337ab7}#ex-debug-toolbar .navbar-nav.nav>li>span.text-primary:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.text-primary:hover,#ex-debug-toolbar a.text-primary:focus,#ex-debug-toolbar a.text-primary:hover{color:#286090}#ex-debug-toolbar .text-success{color:#3c763d}#ex-debug-toolbar .navbar-nav.nav>li>span.text-success:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.text-success:hover,#ex-debug-toolbar a.text-success:focus,#ex-debug-toolbar a.text-success:hover{color:#2b542c}#ex-debug-toolbar .text-info{color:#31708f}#ex-debug-toolbar .navbar-nav.nav>li>span.text-info:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.text-info:hover,#ex-debug-toolbar a.text-info:focus,#ex-debug-toolbar a.text-info:hover{color:#245269}#ex-debug-toolbar .text-warning{color:#8a6d3b}#ex-debug-toolbar .navbar-nav.nav>li>span.text-warning:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.text-warning:hover,#ex-debug-toolbar a.text-warning:focus,#ex-debug-toolbar a.text-warning:hover{color:#66512c}#ex-debug-toolbar .text-danger{color:#a94442}#ex-debug-toolbar .navbar-nav.nav>li>span.text-danger:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.text-danger:hover,#ex-debug-toolbar a.text-danger:focus,#ex-debug-toolbar a.text-danger:hover{color:#843534}#ex-debug-toolbar .bg-primary{color:#fff}#ex-debug-toolbar .bg-primary{background-color:#337ab7}#ex-debug-toolbar .navbar-nav.nav>li>span.bg-primary:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.bg-primary:hover,#ex-debug-toolbar a.bg-primary:focus,#ex-debug-toolbar a.bg-primary:hover{background-color:#286090}#ex-debug-toolbar .bg-success{background-color:#dff0d8}#ex-debug-toolbar .navbar-nav.nav>li>span.bg-success:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.bg-success:hover,#ex-debug-toolbar a.bg-success:focus,#ex-debug-toolbar a.bg-success:hover{background-color:#c1e2b3}#ex-debug-toolbar .bg-info{background-color:#d9edf7}#ex-debug-toolbar .navbar-nav.nav>li>span.bg-info:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.bg-info:hover,#ex-debug-toolbar a.bg-info:focus,#ex-debug-toolbar a.bg-info:hover{background-color:#afd9ee}#ex-debug-toolbar .bg-warning{background-color:#fcf8e3}#ex-debug-toolbar .navbar-nav.nav>li>span.bg-warning:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.bg-warning:hover,#ex-debug-toolbar a.bg-warning:focus,#ex-debug-toolbar a.bg-warning:hover{background-color:#f7ecb5}#ex-debug-toolbar .bg-danger{background-color:#f2dede}#ex-debug-toolbar .navbar-nav.nav>li>span.bg-danger:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.bg-danger:hover,#ex-debug-toolbar a.bg-danger:focus,#ex-debug-toolbar a.bg-danger:hover{background-color:#e4b9b9}#ex-debug-toolbar .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}#ex-debug-toolbar ol,#ex-debug-toolbar ul{margin-top:0;margin-bottom:10px}#ex-debug-toolbar ol ol,#ex-debug-toolbar ol ul,#ex-debug-toolbar ul ol,#ex-debug-toolbar ul ul{margin-bottom:0}#ex-debug-toolbar .list-unstyled{padding-left:0;list-style:none}#ex-debug-toolbar .list-inline{padding-left:0;list-style:none;margin-left:-5px}#ex-debug-toolbar .list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}#ex-debug-toolbar dl{margin-top:0;margin-bottom:20px}#ex-debug-toolbar dd,#ex-debug-toolbar dt{line-height:1.42857}#ex-debug-toolbar dt{font-weight:700}#ex-debug-toolbar dd{margin-left:0}#ex-debug-toolbar .dl-horizontal dd:after,#ex-debug-toolbar .dl-horizontal dd:before{content:" ";display:table}#ex-debug-toolbar .dl-horizontal dd:after{clear:both}@media (min-width:768px){#ex-debug-toolbar .dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}#ex-debug-toolbar .dl-horizontal dd{margin-left:180px}}#ex-debug-toolbar abbr[data-original-title],#ex-debug-toolbar abbr[title]{cursor:help;border-bottom:1px dotted #777}#ex-debug-toolbar .initialism{font-size:90%}#ex-debug-toolbar blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}#ex-debug-toolbar blockquote ol:last-child,#ex-debug-toolbar blockquote p:last-child,#ex-debug-toolbar blockquote ul:last-child{margin-bottom:0}#ex-debug-toolbar blockquote .small,#ex-debug-toolbar blockquote footer,#ex-debug-toolbar blockquote small{display:block;font-size:80%;line-height:1.42857;color:#777}#ex-debug-toolbar blockquote .small:before,#ex-debug-toolbar blockquote footer:before,#ex-debug-toolbar blockquote small:before{content:'\2014 \00A0'}#ex-debug-toolbar .blockquote-reverse,#ex-debug-toolbar blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}#ex-debug-toolbar .blockquote-reverse .small:before,#ex-debug-toolbar .blockquote-reverse footer:before,#ex-debug-toolbar .blockquote-reverse small:before,#ex-debug-toolbar blockquote.pull-right .small:before,#ex-debug-toolbar blockquote.pull-right footer:before,#ex-debug-toolbar blockquote.pull-right small:before{content:''}#ex-debug-toolbar .blockquote-reverse .small:after,#ex-debug-toolbar .blockquote-reverse footer:after,#ex-debug-toolbar .blockquote-reverse small:after,#ex-debug-toolbar blockquote.pull-right .small:after,#ex-debug-toolbar blockquote.pull-right footer:after,#ex-debug-toolbar blockquote.pull-right small:after{content:'\00A0 \2014'}#ex-debug-toolbar address{margin-bottom:20px;font-style:normal;line-height:1.42857}#ex-debug-toolbar code,#ex-debug-toolbar kbd,#ex-debug-toolbar pre,#ex-debug-toolbar samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}#ex-debug-toolbar code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}#ex-debug-toolbar kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}#ex-debug-toolbar kbd kbd{padding:0;font-size:100%;font-weight:700;box-shadow:none}#ex-debug-toolbar pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}#ex-debug-toolbar pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}#ex-debug-toolbar .pre-scrollable{max-height:340px;overflow-y:scroll}#ex-debug-toolbar .container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}#ex-debug-toolbar .container:after,#ex-debug-toolbar .container:before{content:" ";display:table}#ex-debug-toolbar .container:after{clear:both}@media (min-width:768px){#ex-debug-toolbar .container{width:750px}}@media (min-width:992px){#ex-debug-toolbar .container{width:970px}}@media (min-width:1200px){#ex-debug-toolbar .container{width:1170px}}#ex-debug-toolbar .container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}#ex-debug-toolbar .container-fluid:after,#ex-debug-toolbar .container-fluid:before{content:" ";display:table}#ex-debug-toolbar .container-fluid:after{clear:both}#ex-debug-toolbar .row{margin-left:-15px;margin-right:-15px}#ex-debug-toolbar .row:after,#ex-debug-toolbar .row:before{content:" ";display:table}#ex-debug-toolbar .row:after{clear:both}#ex-debug-toolbar .col-lg-1,#ex-debug-toolbar .col-lg-10,#ex-debug-toolbar .col-lg-11,#ex-debug-toolbar .col-lg-12,#ex-debug-toolbar .col-lg-2,#ex-debug-toolbar .col-lg-3,#ex-debug-toolbar .col-lg-4,#ex-debug-toolbar .col-lg-5,#ex-debug-toolbar .col-lg-6,#ex-debug-toolbar .col-lg-7,#ex-debug-toolbar .col-lg-8,#ex-debug-toolbar .col-lg-9,#ex-debug-toolbar .col-md-1,#ex-debug-toolbar .col-md-10,#ex-debug-toolbar .col-md-11,#ex-debug-toolbar .col-md-12,#ex-debug-toolbar .col-md-2,#ex-debug-toolbar .col-md-3,#ex-debug-toolbar .col-md-4,#ex-debug-toolbar .col-md-5,#ex-debug-toolbar .col-md-6,#ex-debug-toolbar .col-md-7,#ex-debug-toolbar .col-md-8,#ex-debug-toolbar .col-md-9,#ex-debug-toolbar .col-sm-1,#ex-debug-toolbar .col-sm-10,#ex-debug-toolbar .col-sm-11,#ex-debug-toolbar .col-sm-12,#ex-debug-toolbar .col-sm-2,#ex-debug-toolbar .col-sm-3,#ex-debug-toolbar .col-sm-4,#ex-debug-toolbar .col-sm-5,#ex-debug-toolbar .col-sm-6,#ex-debug-toolbar .col-sm-7,#ex-debug-toolbar .col-sm-8,#ex-debug-toolbar .col-sm-9,#ex-debug-toolbar .col-xs-1,#ex-debug-toolbar .col-xs-10,#ex-debug-toolbar .col-xs-11,#ex-debug-toolbar .col-xs-12,#ex-debug-toolbar .col-xs-2,#ex-debug-toolbar .col-xs-3,#ex-debug-toolbar .col-xs-4,#ex-debug-toolbar .col-xs-5,#ex-debug-toolbar .col-xs-6,#ex-debug-toolbar .col-xs-7,#ex-debug-toolbar .col-xs-8,#ex-debug-toolbar .col-xs-9{position:relative;min-height:1px;padding-left:15px;padding-right:15px}#ex-debug-toolbar .col-xs-1,#ex-debug-toolbar .col-xs-10,#ex-debug-toolbar .col-xs-11,#ex-debug-toolbar .col-xs-12,#ex-debug-toolbar .col-xs-2,#ex-debug-toolbar .col-xs-3,#ex-debug-toolbar .col-xs-4,#ex-debug-toolbar .col-xs-5,#ex-debug-toolbar .col-xs-6,#ex-debug-toolbar .col-xs-7,#ex-debug-toolbar .col-xs-8,#ex-debug-toolbar .col-xs-9{float:left}#ex-debug-toolbar .col-xs-1{width:8.33333%}#ex-debug-toolbar .col-xs-2{width:16.66667%}#ex-debug-toolbar .col-xs-3{width:25%}#ex-debug-toolbar .col-xs-4{width:33.33333%}#ex-debug-toolbar .col-xs-5{width:41.66667%}#ex-debug-toolbar .col-xs-6{width:50%}#ex-debug-toolbar .col-xs-7{width:58.33333%}#ex-debug-toolbar .col-xs-8{width:66.66667%}#ex-debug-toolbar .col-xs-9{width:75%}#ex-debug-toolbar .col-xs-10{width:83.33333%}#ex-debug-toolbar .col-xs-11{width:91.66667%}#ex-debug-toolbar .col-xs-12{width:100%}#ex-debug-toolbar .col-xs-pull-0{right:auto}#ex-debug-toolbar .col-xs-pull-1{right:8.33333%}#ex-debug-toolbar .col-xs-pull-2{right:16.66667%}#ex-debug-toolbar .col-xs-pull-3{right:25%}#ex-debug-toolbar .col-xs-pull-4{right:33.33333%}#ex-debug-toolbar .col-xs-pull-5{right:41.66667%}#ex-debug-toolbar .col-xs-pull-6{right:50%}#ex-debug-toolbar .col-xs-pull-7{right:58.33333%}#ex-debug-toolbar .col-xs-pull-8{right:66.66667%}#ex-debug-toolbar .col-xs-pull-9{right:75%}#ex-debug-toolbar .col-xs-pull-10{right:83.33333%}#ex-debug-toolbar .col-xs-pull-11{right:91.66667%}#ex-debug-toolbar .col-xs-pull-12{right:100%}#ex-debug-toolbar .col-xs-push-0{left:auto}#ex-debug-toolbar .col-xs-push-1{left:8.33333%}#ex-debug-toolbar .col-xs-push-2{left:16.66667%}#ex-debug-toolbar .col-xs-push-3{left:25%}#ex-debug-toolbar .col-xs-push-4{left:33.33333%}#ex-debug-toolbar .col-xs-push-5{left:41.66667%}#ex-debug-toolbar .col-xs-push-6{left:50%}#ex-debug-toolbar .col-xs-push-7{left:58.33333%}#ex-debug-toolbar .col-xs-push-8{left:66.66667%}#ex-debug-toolbar .col-xs-push-9{left:75%}#ex-debug-toolbar .col-xs-push-10{left:83.33333%}#ex-debug-toolbar .col-xs-push-11{left:91.66667%}#ex-debug-toolbar .col-xs-push-12{left:100%}#ex-debug-toolbar .col-xs-offset-0{margin-left:0}#ex-debug-toolbar .col-xs-offset-1{margin-left:8.33333%}#ex-debug-toolbar .col-xs-offset-2{margin-left:16.66667%}#ex-debug-toolbar .col-xs-offset-3{margin-left:25%}#ex-debug-toolbar .col-xs-offset-4{margin-left:33.33333%}#ex-debug-toolbar .col-xs-offset-5{margin-left:41.66667%}#ex-debug-toolbar .col-xs-offset-6{margin-left:50%}#ex-debug-toolbar .col-xs-offset-7{margin-left:58.33333%}#ex-debug-toolbar .col-xs-offset-8{margin-left:66.66667%}#ex-debug-toolbar .col-xs-offset-9{margin-left:75%}#ex-debug-toolbar .col-xs-offset-10{margin-left:83.33333%}#ex-debug-toolbar .col-xs-offset-11{margin-left:91.66667%}#ex-debug-toolbar .col-xs-offset-12{margin-left:100%}@media (min-width:768px){#ex-debug-toolbar .col-sm-1,#ex-debug-toolbar .col-sm-10,#ex-debug-toolbar .col-sm-11,#ex-debug-toolbar .col-sm-12,#ex-debug-toolbar .col-sm-2,#ex-debug-toolbar .col-sm-3,#ex-debug-toolbar .col-sm-4,#ex-debug-toolbar .col-sm-5,#ex-debug-toolbar .col-sm-6,#ex-debug-toolbar .col-sm-7,#ex-debug-toolbar .col-sm-8,#ex-debug-toolbar .col-sm-9{float:left}#ex-debug-toolbar .col-sm-1{width:8.33333%}#ex-debug-toolbar .col-sm-2{width:16.66667%}#ex-debug-toolbar .col-sm-3{width:25%}#ex-debug-toolbar .col-sm-4{width:33.33333%}#ex-debug-toolbar .col-sm-5{width:41.66667%}#ex-debug-toolbar .col-sm-6{width:50%}#ex-debug-toolbar .col-sm-7{width:58.33333%}#ex-debug-toolbar .col-sm-8{width:66.66667%}#ex-debug-toolbar .col-sm-9{width:75%}#ex-debug-toolbar .col-sm-10{width:83.33333%}#ex-debug-toolbar .col-sm-11{width:91.66667%}#ex-debug-toolbar .col-sm-12{width:100%}#ex-debug-toolbar .col-sm-pull-0{right:auto}#ex-debug-toolbar .col-sm-pull-1{right:8.33333%}#ex-debug-toolbar .col-sm-pull-2{right:16.66667%}#ex-debug-toolbar .col-sm-pull-3{right:25%}#ex-debug-toolbar .col-sm-pull-4{right:33.33333%}#ex-debug-toolbar .col-sm-pull-5{right:41.66667%}#ex-debug-toolbar .col-sm-pull-6{right:50%}#ex-debug-toolbar .col-sm-pull-7{right:58.33333%}#ex-debug-toolbar .col-sm-pull-8{right:66.66667%}#ex-debug-toolbar .col-sm-pull-9{right:75%}#ex-debug-toolbar .col-sm-pull-10{right:83.33333%}#ex-debug-toolbar .col-sm-pull-11{right:91.66667%}#ex-debug-toolbar .col-sm-pull-12{right:100%}#ex-debug-toolbar .col-sm-push-0{left:auto}#ex-debug-toolbar .col-sm-push-1{left:8.33333%}#ex-debug-toolbar .col-sm-push-2{left:16.66667%}#ex-debug-toolbar .col-sm-push-3{left:25%}#ex-debug-toolbar .col-sm-push-4{left:33.33333%}#ex-debug-toolbar .col-sm-push-5{left:41.66667%}#ex-debug-toolbar .col-sm-push-6{left:50%}#ex-debug-toolbar .col-sm-push-7{left:58.33333%}#ex-debug-toolbar .col-sm-push-8{left:66.66667%}#ex-debug-toolbar .col-sm-push-9{left:75%}#ex-debug-toolbar .col-sm-push-10{left:83.33333%}#ex-debug-toolbar .col-sm-push-11{left:91.66667%}#ex-debug-toolbar .col-sm-push-12{left:100%}#ex-debug-toolbar .col-sm-offset-0{margin-left:0}#ex-debug-toolbar .col-sm-offset-1{margin-left:8.33333%}#ex-debug-toolbar .col-sm-offset-2{margin-left:16.66667%}#ex-debug-toolbar .col-sm-offset-3{margin-left:25%}#ex-debug-toolbar .col-sm-offset-4{margin-left:33.33333%}#ex-debug-toolbar .col-sm-offset-5{margin-left:41.66667%}#ex-debug-toolbar .col-sm-offset-6{margin-left:50%}#ex-debug-toolbar .col-sm-offset-7{margin-left:58.33333%}#ex-debug-toolbar .col-sm-offset-8{margin-left:66.66667%}#ex-debug-toolbar .col-sm-offset-9{margin-left:75%}#ex-debug-toolbar .col-sm-offset-10{margin-left:83.33333%}#ex-debug-toolbar .col-sm-offset-11{margin-left:91.66667%}#ex-debug-toolbar .col-sm-offset-12{margin-left:100%}}@media (min-width:992px){#ex-debug-toolbar .col-md-1,#ex-debug-toolbar .col-md-10,#ex-debug-toolbar .col-md-11,#ex-debug-toolbar .col-md-12,#ex-debug-toolbar .col-md-2,#ex-debug-toolbar .col-md-3,#ex-debug-toolbar .col-md-4,#ex-debug-toolbar .col-md-5,#ex-debug-toolbar .col-md-6,#ex-debug-toolbar .col-md-7,#ex-debug-toolbar .col-md-8,#ex-debug-toolbar .col-md-9{float:left}#ex-debug-toolbar .col-md-1{width:8.33333%}#ex-debug-toolbar .col-md-2{width:16.66667%}#ex-debug-toolbar .col-md-3{width:25%}#ex-debug-toolbar .col-md-4{width:33.33333%}#ex-debug-toolbar .col-md-5{width:41.66667%}#ex-debug-toolbar .col-md-6{width:50%}#ex-debug-toolbar .col-md-7{width:58.33333%}#ex-debug-toolbar .col-md-8{width:66.66667%}#ex-debug-toolbar .col-md-9{width:75%}#ex-debug-toolbar .col-md-10{width:83.33333%}#ex-debug-toolbar .col-md-11{width:91.66667%}#ex-debug-toolbar .col-md-12{width:100%}#ex-debug-toolbar .col-md-pull-0{right:auto}#ex-debug-toolbar .col-md-pull-1{right:8.33333%}#ex-debug-toolbar .col-md-pull-2{right:16.66667%}#ex-debug-toolbar .col-md-pull-3{right:25%}#ex-debug-toolbar .col-md-pull-4{right:33.33333%}#ex-debug-toolbar .col-md-pull-5{right:41.66667%}#ex-debug-toolbar .col-md-pull-6{right:50%}#ex-debug-toolbar .col-md-pull-7{right:58.33333%}#ex-debug-toolbar .col-md-pull-8{right:66.66667%}#ex-debug-toolbar .col-md-pull-9{right:75%}#ex-debug-toolbar .col-md-pull-10{right:83.33333%}#ex-debug-toolbar .col-md-pull-11{right:91.66667%}#ex-debug-toolbar .col-md-pull-12{right:100%}#ex-debug-toolbar .col-md-push-0{left:auto}#ex-debug-toolbar .col-md-push-1{left:8.33333%}#ex-debug-toolbar .col-md-push-2{left:16.66667%}#ex-debug-toolbar .col-md-push-3{left:25%}#ex-debug-toolbar .col-md-push-4{left:33.33333%}#ex-debug-toolbar .col-md-push-5{left:41.66667%}#ex-debug-toolbar .col-md-push-6{left:50%}#ex-debug-toolbar .col-md-push-7{left:58.33333%}#ex-debug-toolbar .col-md-push-8{left:66.66667%}#ex-debug-toolbar .col-md-push-9{left:75%}#ex-debug-toolbar .col-md-push-10{left:83.33333%}#ex-debug-toolbar .col-md-push-11{left:91.66667%}#ex-debug-toolbar .col-md-push-12{left:100%}#ex-debug-toolbar .col-md-offset-0{margin-left:0}#ex-debug-toolbar .col-md-offset-1{margin-left:8.33333%}#ex-debug-toolbar .col-md-offset-2{margin-left:16.66667%}#ex-debug-toolbar .col-md-offset-3{margin-left:25%}#ex-debug-toolbar .col-md-offset-4{margin-left:33.33333%}#ex-debug-toolbar .col-md-offset-5{margin-left:41.66667%}#ex-debug-toolbar .col-md-offset-6{margin-left:50%}#ex-debug-toolbar .col-md-offset-7{margin-left:58.33333%}#ex-debug-toolbar .col-md-offset-8{margin-left:66.66667%}#ex-debug-toolbar .col-md-offset-9{margin-left:75%}#ex-debug-toolbar .col-md-offset-10{margin-left:83.33333%}#ex-debug-toolbar .col-md-offset-11{margin-left:91.66667%}#ex-debug-toolbar .col-md-offset-12{margin-left:100%}}@media (min-width:1200px){#ex-debug-toolbar .col-lg-1,#ex-debug-toolbar .col-lg-10,#ex-debug-toolbar .col-lg-11,#ex-debug-toolbar .col-lg-12,#ex-debug-toolbar .col-lg-2,#ex-debug-toolbar .col-lg-3,#ex-debug-toolbar .col-lg-4,#ex-debug-toolbar .col-lg-5,#ex-debug-toolbar .col-lg-6,#ex-debug-toolbar .col-lg-7,#ex-debug-toolbar .col-lg-8,#ex-debug-toolbar .col-lg-9{float:left}#ex-debug-toolbar .col-lg-1{width:8.33333%}#ex-debug-toolbar .col-lg-2{width:16.66667%}#ex-debug-toolbar .col-lg-3{width:25%}#ex-debug-toolbar .col-lg-4{width:33.33333%}#ex-debug-toolbar .col-lg-5{width:41.66667%}#ex-debug-toolbar .col-lg-6{width:50%}#ex-debug-toolbar .col-lg-7{width:58.33333%}#ex-debug-toolbar .col-lg-8{width:66.66667%}#ex-debug-toolbar .col-lg-9{width:75%}#ex-debug-toolbar .col-lg-10{width:83.33333%}#ex-debug-toolbar .col-lg-11{width:91.66667%}#ex-debug-toolbar .col-lg-12{width:100%}#ex-debug-toolbar .col-lg-pull-0{right:auto}#ex-debug-toolbar .col-lg-pull-1{right:8.33333%}#ex-debug-toolbar .col-lg-pull-2{right:16.66667%}#ex-debug-toolbar .col-lg-pull-3{right:25%}#ex-debug-toolbar .col-lg-pull-4{right:33.33333%}#ex-debug-toolbar .col-lg-pull-5{right:41.66667%}#ex-debug-toolbar .col-lg-pull-6{right:50%}#ex-debug-toolbar .col-lg-pull-7{right:58.33333%}#ex-debug-toolbar .col-lg-pull-8{right:66.66667%}#ex-debug-toolbar .col-lg-pull-9{right:75%}#ex-debug-toolbar .col-lg-pull-10{right:83.33333%}#ex-debug-toolbar .col-lg-pull-11{right:91.66667%}#ex-debug-toolbar .col-lg-pull-12{right:100%}#ex-debug-toolbar .col-lg-push-0{left:auto}#ex-debug-toolbar .col-lg-push-1{left:8.33333%}#ex-debug-toolbar .col-lg-push-2{left:16.66667%}#ex-debug-toolbar .col-lg-push-3{left:25%}#ex-debug-toolbar .col-lg-push-4{left:33.33333%}#ex-debug-toolbar .col-lg-push-5{left:41.66667%}#ex-debug-toolbar .col-lg-push-6{left:50%}#ex-debug-toolbar .col-lg-push-7{left:58.33333%}#ex-debug-toolbar .col-lg-push-8{left:66.66667%}#ex-debug-toolbar .col-lg-push-9{left:75%}#ex-debug-toolbar .col-lg-push-10{left:83.33333%}#ex-debug-toolbar .col-lg-push-11{left:91.66667%}#ex-debug-toolbar .col-lg-push-12{left:100%}#ex-debug-toolbar .col-lg-offset-0{margin-left:0}#ex-debug-toolbar .col-lg-offset-1{margin-left:8.33333%}#ex-debug-toolbar .col-lg-offset-2{margin-left:16.66667%}#ex-debug-toolbar .col-lg-offset-3{margin-left:25%}#ex-debug-toolbar .col-lg-offset-4{margin-left:33.33333%}#ex-debug-toolbar .col-lg-offset-5{margin-left:41.66667%}#ex-debug-toolbar .col-lg-offset-6{margin-left:50%}#ex-debug-toolbar .col-lg-offset-7{margin-left:58.33333%}#ex-debug-toolbar .col-lg-offset-8{margin-left:66.66667%}#ex-debug-toolbar .col-lg-offset-9{margin-left:75%}#ex-debug-toolbar .col-lg-offset-10{margin-left:83.33333%}#ex-debug-toolbar .col-lg-offset-11{margin-left:91.66667%}#ex-debug-toolbar .col-lg-offset-12{margin-left:100%}}#ex-debug-toolbar table{background-color:transparent}#ex-debug-toolbar caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}#ex-debug-toolbar th{text-align:left}#ex-debug-toolbar .table{width:100%;max-width:100%;margin-bottom:20px}#ex-debug-toolbar .table>tbody>tr>td,#ex-debug-toolbar .table>tbody>tr>th,#ex-debug-toolbar .table>tfoot>tr>td,#ex-debug-toolbar .table>tfoot>tr>th,#ex-debug-toolbar .table>thead>tr>td,#ex-debug-toolbar .table>thead>tr>th{padding:8px;line-height:1.42857;vertical-align:top;border-top:1px solid #ddd}#ex-debug-toolbar .table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}#ex-debug-toolbar .table>caption+thead>tr:first-child>td,#ex-debug-toolbar .table>caption+thead>tr:first-child>th,#ex-debug-toolbar .table>colgroup+thead>tr:first-child>td,#ex-debug-toolbar .table>colgroup+thead>tr:first-child>th,#ex-debug-toolbar .table>thead:first-child>tr:first-child>td,#ex-debug-toolbar .table>thead:first-child>tr:first-child>th{border-top:0}#ex-debug-toolbar .table>tbody+tbody{border-top:2px solid #ddd}#ex-debug-toolbar .table .table{background-color:#fff}#ex-debug-toolbar .table-condensed>tbody>tr>td,#ex-debug-toolbar .table-condensed>tbody>tr>th,#ex-debug-toolbar .table-condensed>tfoot>tr>td,#ex-debug-toolbar .table-condensed>tfoot>tr>th,#ex-debug-toolbar .table-condensed>thead>tr>td,#ex-debug-toolbar .table-condensed>thead>tr>th{padding:5px}#ex-debug-toolbar .table-bordered{border:1px solid #ddd}#ex-debug-toolbar .table-bordered>tbody>tr>td,#ex-debug-toolbar .table-bordered>tbody>tr>th,#ex-debug-toolbar .table-bordered>tfoot>tr>td,#ex-debug-toolbar .table-bordered>tfoot>tr>th,#ex-debug-toolbar .table-bordered>thead>tr>td,#ex-debug-toolbar .table-bordered>thead>tr>th{border:1px solid #ddd}#ex-debug-toolbar .table-bordered>thead>tr>td,#ex-debug-toolbar .table-bordered>thead>tr>th{border-bottom-width:2px}#ex-debug-toolbar .table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}#ex-debug-toolbar .table-hover>tbody>tr:hover{background-color:#f5f5f5}#ex-debug-toolbar table col[class*=col-]{position:static;float:none;display:table-column}#ex-debug-toolbar table td[class*=col-],#ex-debug-toolbar table th[class*=col-]{position:static;float:none;display:table-cell}#ex-debug-toolbar .table>tbody>tr.active>td,#ex-debug-toolbar .table>tbody>tr.active>th,#ex-debug-toolbar .table>tbody>tr>td.active,#ex-debug-toolbar .table>tbody>tr>th.active,#ex-debug-toolbar .table>tfoot>tr.active>td,#ex-debug-toolbar .table>tfoot>tr.active>th,#ex-debug-toolbar .table>tfoot>tr>td.active,#ex-debug-toolbar .table>tfoot>tr>th.active,#ex-debug-toolbar .table>thead>tr.active>td,#ex-debug-toolbar .table>thead>tr.active>th,#ex-debug-toolbar .table>thead>tr>td.active,#ex-debug-toolbar .table>thead>tr>th.active{background-color:#f5f5f5}#ex-debug-toolbar .table-hover>tbody>tr.active:hover>td,#ex-debug-toolbar .table-hover>tbody>tr.active:hover>th,#ex-debug-toolbar .table-hover>tbody>tr:hover>.active,#ex-debug-toolbar .table-hover>tbody>tr>td.active:hover,#ex-debug-toolbar .table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}#ex-debug-toolbar .table>tbody>tr.success>td,#ex-debug-toolbar .table>tbody>tr.success>th,#ex-debug-toolbar .table>tbody>tr>td.success,#ex-debug-toolbar .table>tbody>tr>th.success,#ex-debug-toolbar .table>tfoot>tr.success>td,#ex-debug-toolbar .table>tfoot>tr.success>th,#ex-debug-toolbar .table>tfoot>tr>td.success,#ex-debug-toolbar .table>tfoot>tr>th.success,#ex-debug-toolbar .table>thead>tr.success>td,#ex-debug-toolbar .table>thead>tr.success>th,#ex-debug-toolbar .table>thead>tr>td.success,#ex-debug-toolbar .table>thead>tr>th.success{background-color:#dff0d8}#ex-debug-toolbar .table-hover>tbody>tr.success:hover>td,#ex-debug-toolbar .table-hover>tbody>tr.success:hover>th,#ex-debug-toolbar .table-hover>tbody>tr:hover>.success,#ex-debug-toolbar .table-hover>tbody>tr>td.success:hover,#ex-debug-toolbar .table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}#ex-debug-toolbar .table>tbody>tr.info>td,#ex-debug-toolbar .table>tbody>tr.info>th,#ex-debug-toolbar .table>tbody>tr>td.info,#ex-debug-toolbar .table>tbody>tr>th.info,#ex-debug-toolbar .table>tfoot>tr.info>td,#ex-debug-toolbar .table>tfoot>tr.info>th,#ex-debug-toolbar .table>tfoot>tr>td.info,#ex-debug-toolbar .table>tfoot>tr>th.info,#ex-debug-toolbar .table>thead>tr.info>td,#ex-debug-toolbar .table>thead>tr.info>th,#ex-debug-toolbar .table>thead>tr>td.info,#ex-debug-toolbar .table>thead>tr>th.info{background-color:#d9edf7}#ex-debug-toolbar .table-hover>tbody>tr.info:hover>td,#ex-debug-toolbar .table-hover>tbody>tr.info:hover>th,#ex-debug-toolbar .table-hover>tbody>tr:hover>.info,#ex-debug-toolbar .table-hover>tbody>tr>td.info:hover,#ex-debug-toolbar .table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}#ex-debug-toolbar .table>tbody>tr.warning>td,#ex-debug-toolbar .table>tbody>tr.warning>th,#ex-debug-toolbar .table>tbody>tr>td.warning,#ex-debug-toolbar .table>tbody>tr>th.warning,#ex-debug-toolbar .table>tfoot>tr.warning>td,#ex-debug-toolbar .table>tfoot>tr.warning>th,#ex-debug-toolbar .table>tfoot>tr>td.warning,#ex-debug-toolbar .table>tfoot>tr>th.warning,#ex-debug-toolbar .table>thead>tr.warning>td,#ex-debug-toolbar .table>thead>tr.warning>th,#ex-debug-toolbar .table>thead>tr>td.warning,#ex-debug-toolbar .table>thead>tr>th.warning{background-color:#fcf8e3}#ex-debug-toolbar .table-hover>tbody>tr.warning:hover>td,#ex-debug-toolbar .table-hover>tbody>tr.warning:hover>th,#ex-debug-toolbar .table-hover>tbody>tr:hover>.warning,#ex-debug-toolbar .table-hover>tbody>tr>td.warning:hover,#ex-debug-toolbar .table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}#ex-debug-toolbar .table>tbody>tr.danger>td,#ex-debug-toolbar .table>tbody>tr.danger>th,#ex-debug-toolbar .table>tbody>tr>td.danger,#ex-debug-toolbar .table>tbody>tr>th.danger,#ex-debug-toolbar .table>tfoot>tr.danger>td,#ex-debug-toolbar .table>tfoot>tr.danger>th,#ex-debug-toolbar .table>tfoot>tr>td.danger,#ex-debug-toolbar .table>tfoot>tr>th.danger,#ex-debug-toolbar .table>thead>tr.danger>td,#ex-debug-toolbar .table>thead>tr.danger>th,#ex-debug-toolbar .table>thead>tr>td.danger,#ex-debug-toolbar .table>thead>tr>th.danger{background-color:#f2dede}#ex-debug-toolbar .table-hover>tbody>tr.danger:hover>td,#ex-debug-toolbar .table-hover>tbody>tr.danger:hover>th,#ex-debug-toolbar .table-hover>tbody>tr:hover>.danger,#ex-debug-toolbar .table-hover>tbody>tr>td.danger:hover,#ex-debug-toolbar .table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}#ex-debug-toolbar .table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){#ex-debug-toolbar .table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}#ex-debug-toolbar .table-responsive>.table{margin-bottom:0}#ex-debug-toolbar .table-responsive>.table>tbody>tr>td,#ex-debug-toolbar .table-responsive>.table>tbody>tr>th,#ex-debug-toolbar .table-responsive>.table>tfoot>tr>td,#ex-debug-toolbar .table-responsive>.table>tfoot>tr>th,#ex-debug-toolbar .table-responsive>.table>thead>tr>td,#ex-debug-toolbar .table-responsive>.table>thead>tr>th{white-space:nowrap}#ex-debug-toolbar .table-responsive>.table-bordered{border:0}#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr>td:first-child,#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr>th:first-child,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr>td:first-child,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr>th:first-child,#ex-debug-toolbar .table-responsive>.table-bordered>thead>tr>td:first-child,#ex-debug-toolbar .table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr>td:last-child,#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr>th:last-child,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr>td:last-child,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr>th:last-child,#ex-debug-toolbar .table-responsive>.table-bordered>thead>tr>td:last-child,#ex-debug-toolbar .table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr:last-child>td,#ex-debug-toolbar .table-responsive>.table-bordered>tbody>tr:last-child>th,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr:last-child>td,#ex-debug-toolbar .table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}#ex-debug-toolbar fieldset{padding:0;margin:0;border:0;min-width:0}#ex-debug-toolbar 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}#ex-debug-toolbar label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}#ex-debug-toolbar input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#ex-debug-toolbar input[type=checkbox],#ex-debug-toolbar input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}#ex-debug-toolbar input[type=file]{display:block}#ex-debug-toolbar input[type=range]{display:block;width:100%}#ex-debug-toolbar select[multiple],#ex-debug-toolbar select[size]{height:auto}#ex-debug-toolbar input[type=file]:focus,#ex-debug-toolbar input[type=checkbox]:focus,#ex-debug-toolbar input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}#ex-debug-toolbar output{display:block;padding-top:7px;font-size:14px;line-height:1.42857;color:#555}#ex-debug-toolbar .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857;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,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}#ex-debug-toolbar .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)}#ex-debug-toolbar .form-control::-moz-placeholder{color:#999;opacity:1}#ex-debug-toolbar .form-control:-ms-input-placeholder{color:#999}#ex-debug-toolbar .form-control::-webkit-input-placeholder{color:#999}#ex-debug-toolbar .form-control::-ms-expand{border:0;background-color:transparent}#ex-debug-toolbar .form-control[disabled],#ex-debug-toolbar .form-control[readonly],fieldset[disabled] #ex-debug-toolbar .form-control{background-color:#eee;opacity:1}#ex-debug-toolbar .form-control[disabled],fieldset[disabled] #ex-debug-toolbar .form-control{cursor:not-allowed}#ex-debug-toolbar textarea.form-control{height:auto}#ex-debug-toolbar input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){#ex-debug-toolbar input[type=date].form-control,#ex-debug-toolbar input[type=time].form-control,#ex-debug-toolbar input[type=datetime-local].form-control,#ex-debug-toolbar input[type=month].form-control{line-height:34px}#ex-debug-toolbar .input-group-sm>.input-group-btn>input[type=date].btn,#ex-debug-toolbar .input-group-sm>.input-group-btn>input[type=time].btn,#ex-debug-toolbar .input-group-sm>.input-group-btn>input[type=datetime-local].btn,#ex-debug-toolbar .input-group-sm>.input-group-btn>input[type=month].btn,#ex-debug-toolbar .input-group-sm>input[type=date].form-control,#ex-debug-toolbar .input-group-sm>input[type=date].input-group-addon,#ex-debug-toolbar .input-group-sm>input[type=time].form-control,#ex-debug-toolbar .input-group-sm>input[type=time].input-group-addon,#ex-debug-toolbar .input-group-sm>input[type=datetime-local].form-control,#ex-debug-toolbar .input-group-sm>input[type=datetime-local].input-group-addon,#ex-debug-toolbar .input-group-sm>input[type=month].form-control,#ex-debug-toolbar .input-group-sm>input[type=month].input-group-addon,#ex-debug-toolbar input[type=date].input-sm,#ex-debug-toolbar input[type=time].input-sm,#ex-debug-toolbar input[type=datetime-local].input-sm,#ex-debug-toolbar input[type=month].input-sm,.input-group-sm #ex-debug-toolbar input[type=date],.input-group-sm #ex-debug-toolbar input[type=time],.input-group-sm #ex-debug-toolbar input[type=datetime-local],.input-group-sm #ex-debug-toolbar input[type=month]{line-height:30px}#ex-debug-toolbar .input-group-lg>.input-group-btn>input[type=date].btn,#ex-debug-toolbar .input-group-lg>.input-group-btn>input[type=time].btn,#ex-debug-toolbar .input-group-lg>.input-group-btn>input[type=datetime-local].btn,#ex-debug-toolbar .input-group-lg>.input-group-btn>input[type=month].btn,#ex-debug-toolbar .input-group-lg>input[type=date].form-control,#ex-debug-toolbar .input-group-lg>input[type=date].input-group-addon,#ex-debug-toolbar .input-group-lg>input[type=time].form-control,#ex-debug-toolbar .input-group-lg>input[type=time].input-group-addon,#ex-debug-toolbar .input-group-lg>input[type=datetime-local].form-control,#ex-debug-toolbar .input-group-lg>input[type=datetime-local].input-group-addon,#ex-debug-toolbar .input-group-lg>input[type=month].form-control,#ex-debug-toolbar .input-group-lg>input[type=month].input-group-addon,#ex-debug-toolbar input[type=date].input-lg,#ex-debug-toolbar input[type=time].input-lg,#ex-debug-toolbar input[type=datetime-local].input-lg,#ex-debug-toolbar input[type=month].input-lg,.input-group-lg #ex-debug-toolbar input[type=date],.input-group-lg #ex-debug-toolbar input[type=time],.input-group-lg #ex-debug-toolbar input[type=datetime-local],.input-group-lg #ex-debug-toolbar input[type=month]{line-height:46px}}#ex-debug-toolbar .form-group{margin-bottom:15px}#ex-debug-toolbar .checkbox,#ex-debug-toolbar .radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}#ex-debug-toolbar .checkbox label,#ex-debug-toolbar .radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}#ex-debug-toolbar .checkbox input[type=checkbox],#ex-debug-toolbar .checkbox-inline input[type=checkbox],#ex-debug-toolbar .radio input[type=radio],#ex-debug-toolbar .radio-inline input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px\9}#ex-debug-toolbar .checkbox+.checkbox,#ex-debug-toolbar .radio+.radio{margin-top:-5px}#ex-debug-toolbar .checkbox-inline,#ex-debug-toolbar .radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}#ex-debug-toolbar .checkbox-inline+.checkbox-inline,#ex-debug-toolbar .radio-inline+.radio-inline{margin-top:0;margin-left:10px}#ex-debug-toolbar input[type=checkbox].disabled,#ex-debug-toolbar input[type=checkbox][disabled],#ex-debug-toolbar input[type=radio].disabled,#ex-debug-toolbar input[type=radio][disabled],fieldset[disabled] #ex-debug-toolbar input[type=checkbox],fieldset[disabled] #ex-debug-toolbar input[type=radio]{cursor:not-allowed}#ex-debug-toolbar .checkbox-inline.disabled,#ex-debug-toolbar .radio-inline.disabled,fieldset[disabled] #ex-debug-toolbar .checkbox-inline,fieldset[disabled] #ex-debug-toolbar .radio-inline{cursor:not-allowed}#ex-debug-toolbar .checkbox.disabled label,#ex-debug-toolbar .radio.disabled label,fieldset[disabled] #ex-debug-toolbar .checkbox label,fieldset[disabled] #ex-debug-toolbar .radio label{cursor:not-allowed}#ex-debug-toolbar .form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:34px}#ex-debug-toolbar .form-control-static.input-lg,#ex-debug-toolbar .form-control-static.input-sm,#ex-debug-toolbar .input-group-lg>.form-control-static.form-control,#ex-debug-toolbar .input-group-lg>.form-control-static.input-group-addon,#ex-debug-toolbar .input-group-lg>.input-group-btn>.form-control-static.btn,#ex-debug-toolbar .input-group-sm>.form-control-static.form-control,#ex-debug-toolbar .input-group-sm>.form-control-static.input-group-addon,#ex-debug-toolbar .input-group-sm>.input-group-btn>.form-control-static.btn{padding-left:0;padding-right:0}#ex-debug-toolbar .input-group-sm>.form-control,#ex-debug-toolbar .input-group-sm>.input-group-addon,#ex-debug-toolbar .input-group-sm>.input-group-btn>.btn,#ex-debug-toolbar .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}#ex-debug-toolbar .input-group-sm>.input-group-btn>select.btn,#ex-debug-toolbar .input-group-sm>select.form-control,#ex-debug-toolbar .input-group-sm>select.input-group-addon,#ex-debug-toolbar select.input-sm{height:30px;line-height:30px}#ex-debug-toolbar .input-group-sm>.input-group-btn>select[multiple].btn,#ex-debug-toolbar .input-group-sm>.input-group-btn>textarea.btn,#ex-debug-toolbar .input-group-sm>select[multiple].form-control,#ex-debug-toolbar .input-group-sm>select[multiple].input-group-addon,#ex-debug-toolbar .input-group-sm>textarea.form-control,#ex-debug-toolbar .input-group-sm>textarea.input-group-addon,#ex-debug-toolbar select[multiple].input-sm,#ex-debug-toolbar textarea.input-sm{height:auto}#ex-debug-toolbar .form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}#ex-debug-toolbar .form-group-sm select.form-control{height:30px;line-height:30px}#ex-debug-toolbar .form-group-sm select[multiple].form-control,#ex-debug-toolbar .form-group-sm textarea.form-control{height:auto}#ex-debug-toolbar .form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}#ex-debug-toolbar .input-group-lg>.form-control,#ex-debug-toolbar .input-group-lg>.input-group-addon,#ex-debug-toolbar .input-group-lg>.input-group-btn>.btn,#ex-debug-toolbar .input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33333;border-radius:6px}#ex-debug-toolbar .input-group-lg>.input-group-btn>select.btn,#ex-debug-toolbar .input-group-lg>select.form-control,#ex-debug-toolbar .input-group-lg>select.input-group-addon,#ex-debug-toolbar select.input-lg{height:46px;line-height:46px}#ex-debug-toolbar .input-group-lg>.input-group-btn>select[multiple].btn,#ex-debug-toolbar .input-group-lg>.input-group-btn>textarea.btn,#ex-debug-toolbar .input-group-lg>select[multiple].form-control,#ex-debug-toolbar .input-group-lg>select[multiple].input-group-addon,#ex-debug-toolbar .input-group-lg>textarea.form-control,#ex-debug-toolbar .input-group-lg>textarea.input-group-addon,#ex-debug-toolbar select[multiple].input-lg,#ex-debug-toolbar textarea.input-lg{height:auto}#ex-debug-toolbar .form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.33333;border-radius:6px}#ex-debug-toolbar .form-group-lg select.form-control{height:46px;line-height:46px}#ex-debug-toolbar .form-group-lg select[multiple].form-control,#ex-debug-toolbar .form-group-lg textarea.form-control{height:auto}#ex-debug-toolbar .form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.33333}#ex-debug-toolbar .has-feedback{position:relative}#ex-debug-toolbar .has-feedback .form-control{padding-right:42.5px}#ex-debug-toolbar .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}#ex-debug-toolbar .form-group-lg .form-control+.form-control-feedback,#ex-debug-toolbar .input-group-lg+.form-control-feedback,#ex-debug-toolbar .input-group-lg>.form-control+.form-control-feedback,#ex-debug-toolbar .input-group-lg>.input-group-addon+.form-control-feedback,#ex-debug-toolbar .input-group-lg>.input-group-btn>.btn+.form-control-feedback,#ex-debug-toolbar .input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}#ex-debug-toolbar .form-group-sm .form-control+.form-control-feedback,#ex-debug-toolbar .input-group-sm+.form-control-feedback,#ex-debug-toolbar .input-group-sm>.form-control+.form-control-feedback,#ex-debug-toolbar .input-group-sm>.input-group-addon+.form-control-feedback,#ex-debug-toolbar .input-group-sm>.input-group-btn>.btn+.form-control-feedback,#ex-debug-toolbar .input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}#ex-debug-toolbar .has-success .checkbox,#ex-debug-toolbar .has-success .checkbox-inline,#ex-debug-toolbar .has-success .control-label,#ex-debug-toolbar .has-success .help-block,#ex-debug-toolbar .has-success .radio,#ex-debug-toolbar .has-success .radio-inline,#ex-debug-toolbar .has-success.checkbox label,#ex-debug-toolbar .has-success.checkbox-inline label,#ex-debug-toolbar .has-success.radio label,#ex-debug-toolbar .has-success.radio-inline label{color:#3c763d}#ex-debug-toolbar .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)}#ex-debug-toolbar .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}#ex-debug-toolbar .has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}#ex-debug-toolbar .has-success .form-control-feedback{color:#3c763d}#ex-debug-toolbar .has-warning .checkbox,#ex-debug-toolbar .has-warning .checkbox-inline,#ex-debug-toolbar .has-warning .control-label,#ex-debug-toolbar .has-warning .help-block,#ex-debug-toolbar .has-warning .radio,#ex-debug-toolbar .has-warning .radio-inline,#ex-debug-toolbar .has-warning.checkbox label,#ex-debug-toolbar .has-warning.checkbox-inline label,#ex-debug-toolbar .has-warning.radio label,#ex-debug-toolbar .has-warning.radio-inline label{color:#8a6d3b}#ex-debug-toolbar .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)}#ex-debug-toolbar .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}#ex-debug-toolbar .has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}#ex-debug-toolbar .has-warning .form-control-feedback{color:#8a6d3b}#ex-debug-toolbar .has-error .checkbox,#ex-debug-toolbar .has-error .checkbox-inline,#ex-debug-toolbar .has-error .control-label,#ex-debug-toolbar .has-error .help-block,#ex-debug-toolbar .has-error .radio,#ex-debug-toolbar .has-error .radio-inline,#ex-debug-toolbar .has-error.checkbox label,#ex-debug-toolbar .has-error.checkbox-inline label,#ex-debug-toolbar .has-error.radio label,#ex-debug-toolbar .has-error.radio-inline label{color:#a94442}#ex-debug-toolbar .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)}#ex-debug-toolbar .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}#ex-debug-toolbar .has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}#ex-debug-toolbar .has-error .form-control-feedback{color:#a94442}#ex-debug-toolbar .has-feedback label~.form-control-feedback{top:25px}#ex-debug-toolbar .has-feedback label.sr-only~.form-control-feedback{top:0}#ex-debug-toolbar .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){#ex-debug-toolbar .form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}#ex-debug-toolbar .form-inline .form-control-static{display:inline-block}#ex-debug-toolbar .form-inline .input-group{display:inline-table;vertical-align:middle}#ex-debug-toolbar .form-inline .input-group .form-control,#ex-debug-toolbar .form-inline .input-group .input-group-addon,#ex-debug-toolbar .form-inline .input-group .input-group-btn{width:auto}#ex-debug-toolbar .form-inline .input-group>.form-control{width:100%}#ex-debug-toolbar .form-inline .control-label{margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .form-inline .checkbox,#ex-debug-toolbar .form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .form-inline .checkbox label,#ex-debug-toolbar .form-inline .radio label{padding-left:0}#ex-debug-toolbar .form-inline .checkbox input[type=checkbox],#ex-debug-toolbar .form-inline .radio input[type=radio]{position:relative;margin-left:0}#ex-debug-toolbar .form-inline .has-feedback .form-control-feedback{top:0}}#ex-debug-toolbar .form-horizontal .checkbox,#ex-debug-toolbar .form-horizontal .checkbox-inline,#ex-debug-toolbar .form-horizontal .radio,#ex-debug-toolbar .form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}#ex-debug-toolbar .form-horizontal .checkbox,#ex-debug-toolbar .form-horizontal .radio{min-height:27px}#ex-debug-toolbar .form-horizontal .form-group{margin-left:-15px;margin-right:-15px}#ex-debug-toolbar .form-horizontal .form-group:after,#ex-debug-toolbar .form-horizontal .form-group:before{content:" ";display:table}#ex-debug-toolbar .form-horizontal .form-group:after{clear:both}@media (min-width:768px){#ex-debug-toolbar .form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}#ex-debug-toolbar .form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){#ex-debug-toolbar .form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){#ex-debug-toolbar .form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}#ex-debug-toolbar .btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.42857;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#ex-debug-toolbar .btn.active.focus,#ex-debug-toolbar .btn.active:focus,#ex-debug-toolbar .btn.focus,#ex-debug-toolbar .btn:active.focus,#ex-debug-toolbar .btn:active:focus,#ex-debug-toolbar .btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}#ex-debug-toolbar .btn.focus,#ex-debug-toolbar .btn:focus,#ex-debug-toolbar .btn:hover{color:#333;text-decoration:none}#ex-debug-toolbar .btn.active,#ex-debug-toolbar .btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}#ex-debug-toolbar .btn.disabled,#ex-debug-toolbar .btn[disabled],fieldset[disabled] #ex-debug-toolbar .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}#ex-debug-toolbar .navbar-nav.nav>li>span.btn.disabled,#ex-debug-toolbar a.btn.disabled,fieldset[disabled] #ex-debug-toolbar .navbar-nav.nav>li>span.btn,fieldset[disabled] #ex-debug-toolbar a.btn{pointer-events:none}#ex-debug-toolbar .btn-default{color:#333;background-color:#fff;border-color:#ccc}#ex-debug-toolbar .btn-default.focus,#ex-debug-toolbar .btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}#ex-debug-toolbar .btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}#ex-debug-toolbar .btn-default.active,#ex-debug-toolbar .btn-default:active,.open>#ex-debug-toolbar .btn-default.dropdown-toggle{color:#333;background-color:#e6e6e6;border-color:#adadad}#ex-debug-toolbar .btn-default.active.focus,#ex-debug-toolbar .btn-default.active:focus,#ex-debug-toolbar .btn-default.active:hover,#ex-debug-toolbar .btn-default:active.focus,#ex-debug-toolbar .btn-default:active:focus,#ex-debug-toolbar .btn-default:active:hover,.open>#ex-debug-toolbar .btn-default.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-default.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-default.dropdown-toggle:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}#ex-debug-toolbar .btn-default.active,#ex-debug-toolbar .btn-default:active,.open>#ex-debug-toolbar .btn-default.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-default.disabled.focus,#ex-debug-toolbar .btn-default.disabled:focus,#ex-debug-toolbar .btn-default.disabled:hover,#ex-debug-toolbar .btn-default[disabled].focus,#ex-debug-toolbar .btn-default[disabled]:focus,#ex-debug-toolbar .btn-default[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-default.focus,fieldset[disabled] #ex-debug-toolbar .btn-default:focus,fieldset[disabled] #ex-debug-toolbar .btn-default:hover{background-color:#fff;border-color:#ccc}#ex-debug-toolbar .btn-default .badge{color:#fff;background-color:#333}#ex-debug-toolbar .btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}#ex-debug-toolbar .btn-primary.focus,#ex-debug-toolbar .btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}#ex-debug-toolbar .btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}#ex-debug-toolbar .btn-primary.active,#ex-debug-toolbar .btn-primary:active,.open>#ex-debug-toolbar .btn-primary.dropdown-toggle{color:#fff;background-color:#286090;border-color:#204d74}#ex-debug-toolbar .btn-primary.active.focus,#ex-debug-toolbar .btn-primary.active:focus,#ex-debug-toolbar .btn-primary.active:hover,#ex-debug-toolbar .btn-primary:active.focus,#ex-debug-toolbar .btn-primary:active:focus,#ex-debug-toolbar .btn-primary:active:hover,.open>#ex-debug-toolbar .btn-primary.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-primary.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-primary.dropdown-toggle:hover{color:#fff;background-color:#204d74;border-color:#122b40}#ex-debug-toolbar .btn-primary.active,#ex-debug-toolbar .btn-primary:active,.open>#ex-debug-toolbar .btn-primary.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-primary.disabled.focus,#ex-debug-toolbar .btn-primary.disabled:focus,#ex-debug-toolbar .btn-primary.disabled:hover,#ex-debug-toolbar .btn-primary[disabled].focus,#ex-debug-toolbar .btn-primary[disabled]:focus,#ex-debug-toolbar .btn-primary[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-primary.focus,fieldset[disabled] #ex-debug-toolbar .btn-primary:focus,fieldset[disabled] #ex-debug-toolbar .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}#ex-debug-toolbar .btn-primary .badge{color:#337ab7;background-color:#fff}#ex-debug-toolbar .btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}#ex-debug-toolbar .btn-success.focus,#ex-debug-toolbar .btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}#ex-debug-toolbar .btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}#ex-debug-toolbar .btn-success.active,#ex-debug-toolbar .btn-success:active,.open>#ex-debug-toolbar .btn-success.dropdown-toggle{color:#fff;background-color:#449d44;border-color:#398439}#ex-debug-toolbar .btn-success.active.focus,#ex-debug-toolbar .btn-success.active:focus,#ex-debug-toolbar .btn-success.active:hover,#ex-debug-toolbar .btn-success:active.focus,#ex-debug-toolbar .btn-success:active:focus,#ex-debug-toolbar .btn-success:active:hover,.open>#ex-debug-toolbar .btn-success.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-success.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-success.dropdown-toggle:hover{color:#fff;background-color:#398439;border-color:#255625}#ex-debug-toolbar .btn-success.active,#ex-debug-toolbar .btn-success:active,.open>#ex-debug-toolbar .btn-success.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-success.disabled.focus,#ex-debug-toolbar .btn-success.disabled:focus,#ex-debug-toolbar .btn-success.disabled:hover,#ex-debug-toolbar .btn-success[disabled].focus,#ex-debug-toolbar .btn-success[disabled]:focus,#ex-debug-toolbar .btn-success[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-success.focus,fieldset[disabled] #ex-debug-toolbar .btn-success:focus,fieldset[disabled] #ex-debug-toolbar .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}#ex-debug-toolbar .btn-success .badge{color:#5cb85c;background-color:#fff}#ex-debug-toolbar .btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}#ex-debug-toolbar .btn-info.focus,#ex-debug-toolbar .btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}#ex-debug-toolbar .btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}#ex-debug-toolbar .btn-info.active,#ex-debug-toolbar .btn-info:active,.open>#ex-debug-toolbar .btn-info.dropdown-toggle{color:#fff;background-color:#31b0d5;border-color:#269abc}#ex-debug-toolbar .btn-info.active.focus,#ex-debug-toolbar .btn-info.active:focus,#ex-debug-toolbar .btn-info.active:hover,#ex-debug-toolbar .btn-info:active.focus,#ex-debug-toolbar .btn-info:active:focus,#ex-debug-toolbar .btn-info:active:hover,.open>#ex-debug-toolbar .btn-info.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-info.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-info.dropdown-toggle:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}#ex-debug-toolbar .btn-info.active,#ex-debug-toolbar .btn-info:active,.open>#ex-debug-toolbar .btn-info.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-info.disabled.focus,#ex-debug-toolbar .btn-info.disabled:focus,#ex-debug-toolbar .btn-info.disabled:hover,#ex-debug-toolbar .btn-info[disabled].focus,#ex-debug-toolbar .btn-info[disabled]:focus,#ex-debug-toolbar .btn-info[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-info.focus,fieldset[disabled] #ex-debug-toolbar .btn-info:focus,fieldset[disabled] #ex-debug-toolbar .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}#ex-debug-toolbar .btn-info .badge{color:#5bc0de;background-color:#fff}#ex-debug-toolbar .btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}#ex-debug-toolbar .btn-warning.focus,#ex-debug-toolbar .btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}#ex-debug-toolbar .btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}#ex-debug-toolbar .btn-warning.active,#ex-debug-toolbar .btn-warning:active,.open>#ex-debug-toolbar .btn-warning.dropdown-toggle{color:#fff;background-color:#ec971f;border-color:#d58512}#ex-debug-toolbar .btn-warning.active.focus,#ex-debug-toolbar .btn-warning.active:focus,#ex-debug-toolbar .btn-warning.active:hover,#ex-debug-toolbar .btn-warning:active.focus,#ex-debug-toolbar .btn-warning:active:focus,#ex-debug-toolbar .btn-warning:active:hover,.open>#ex-debug-toolbar .btn-warning.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-warning.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-warning.dropdown-toggle:hover{color:#fff;background-color:#d58512;border-color:#985f0d}#ex-debug-toolbar .btn-warning.active,#ex-debug-toolbar .btn-warning:active,.open>#ex-debug-toolbar .btn-warning.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-warning.disabled.focus,#ex-debug-toolbar .btn-warning.disabled:focus,#ex-debug-toolbar .btn-warning.disabled:hover,#ex-debug-toolbar .btn-warning[disabled].focus,#ex-debug-toolbar .btn-warning[disabled]:focus,#ex-debug-toolbar .btn-warning[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-warning.focus,fieldset[disabled] #ex-debug-toolbar .btn-warning:focus,fieldset[disabled] #ex-debug-toolbar .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}#ex-debug-toolbar .btn-warning .badge{color:#f0ad4e;background-color:#fff}#ex-debug-toolbar .btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}#ex-debug-toolbar .btn-danger.focus,#ex-debug-toolbar .btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}#ex-debug-toolbar .btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}#ex-debug-toolbar .btn-danger.active,#ex-debug-toolbar .btn-danger:active,.open>#ex-debug-toolbar .btn-danger.dropdown-toggle{color:#fff;background-color:#c9302c;border-color:#ac2925}#ex-debug-toolbar .btn-danger.active.focus,#ex-debug-toolbar .btn-danger.active:focus,#ex-debug-toolbar .btn-danger.active:hover,#ex-debug-toolbar .btn-danger:active.focus,#ex-debug-toolbar .btn-danger:active:focus,#ex-debug-toolbar .btn-danger:active:hover,.open>#ex-debug-toolbar .btn-danger.dropdown-toggle.focus,.open>#ex-debug-toolbar .btn-danger.dropdown-toggle:focus,.open>#ex-debug-toolbar .btn-danger.dropdown-toggle:hover{color:#fff;background-color:#ac2925;border-color:#761c19}#ex-debug-toolbar .btn-danger.active,#ex-debug-toolbar .btn-danger:active,.open>#ex-debug-toolbar .btn-danger.dropdown-toggle{background-image:none}#ex-debug-toolbar .btn-danger.disabled.focus,#ex-debug-toolbar .btn-danger.disabled:focus,#ex-debug-toolbar .btn-danger.disabled:hover,#ex-debug-toolbar .btn-danger[disabled].focus,#ex-debug-toolbar .btn-danger[disabled]:focus,#ex-debug-toolbar .btn-danger[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-danger.focus,fieldset[disabled] #ex-debug-toolbar .btn-danger:focus,fieldset[disabled] #ex-debug-toolbar .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}#ex-debug-toolbar .btn-danger .badge{color:#d9534f;background-color:#fff}#ex-debug-toolbar .btn-link{color:#337ab7;font-weight:400;border-radius:0}#ex-debug-toolbar .btn-link,#ex-debug-toolbar .btn-link.active,#ex-debug-toolbar .btn-link:active,#ex-debug-toolbar .btn-link[disabled],fieldset[disabled] #ex-debug-toolbar .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}#ex-debug-toolbar .btn-link,#ex-debug-toolbar .btn-link:active,#ex-debug-toolbar .btn-link:focus,#ex-debug-toolbar .btn-link:hover{border-color:transparent}#ex-debug-toolbar .btn-link:focus,#ex-debug-toolbar .btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}#ex-debug-toolbar .btn-link[disabled]:focus,#ex-debug-toolbar .btn-link[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .btn-link:focus,fieldset[disabled] #ex-debug-toolbar .btn-link:hover{color:#777;text-decoration:none}#ex-debug-toolbar .btn-group-lg>.btn,#ex-debug-toolbar .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33333;border-radius:6px}#ex-debug-toolbar .btn-group-sm>.btn,#ex-debug-toolbar .btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}#ex-debug-toolbar .btn-group-xs>.btn,#ex-debug-toolbar .btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}#ex-debug-toolbar .btn-block{display:block;width:100%}#ex-debug-toolbar .btn-block+.btn-block{margin-top:5px}#ex-debug-toolbar input[type=button].btn-block,#ex-debug-toolbar input[type=reset].btn-block,#ex-debug-toolbar input[type=submit].btn-block{width:100%}#ex-debug-toolbar .fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}#ex-debug-toolbar .fade.in{opacity:1}#ex-debug-toolbar .collapse{display:none}#ex-debug-toolbar .collapse.in{display:block}#ex-debug-toolbar tr.collapse.in{display:table-row}#ex-debug-toolbar tbody.collapse.in{display:table-row-group}#ex-debug-toolbar .collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}#ex-debug-toolbar .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}#ex-debug-toolbar .dropdown,#ex-debug-toolbar .dropup{position:relative}#ex-debug-toolbar .dropdown-toggle:focus{outline:0}#ex-debug-toolbar .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:#fff;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);background-clip:padding-box}#ex-debug-toolbar .dropdown-menu.pull-right{right:0;left:auto}#ex-debug-toolbar .dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}#ex-debug-toolbar .dropdown-menu>li>a,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li>span{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857;color:#333;white-space:nowrap}#ex-debug-toolbar .dropdown-menu>li>a:focus,#ex-debug-toolbar .dropdown-menu>li>a:hover,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li>span:focus,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li>span:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}#ex-debug-toolbar .dropdown-menu>.active>a,#ex-debug-toolbar .dropdown-menu>.active>a:focus,#ex-debug-toolbar .dropdown-menu>.active>a:hover,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.active>span,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.active>span:hover{color:#fff;text-decoration:none;outline:0;background-color:#337ab7}#ex-debug-toolbar .dropdown-menu>.disabled>a,#ex-debug-toolbar .dropdown-menu>.disabled>a:focus,#ex-debug-toolbar .dropdown-menu>.disabled>a:hover,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.disabled>span,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.disabled>span:focus,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.disabled>span:hover{color:#777}#ex-debug-toolbar .dropdown-menu>.disabled>a:focus,#ex-debug-toolbar .dropdown-menu>.disabled>a:hover,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.disabled>span:focus,#ex-debug-toolbar .navbar-nav.nav.dropdown-menu>li.disabled>span:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}#ex-debug-toolbar .open>.dropdown-menu{display:block}#ex-debug-toolbar .navbar-nav.nav>li.open>span,#ex-debug-toolbar .open>a{outline:0}#ex-debug-toolbar .dropdown-menu-right{left:auto;right:0}#ex-debug-toolbar .dropdown-menu-left{left:0;right:auto}#ex-debug-toolbar .dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857;color:#777;white-space:nowrap}#ex-debug-toolbar .dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}#ex-debug-toolbar .pull-right>.dropdown-menu{right:0;left:auto}#ex-debug-toolbar .dropup .caret,#ex-debug-toolbar .navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9;content:""}#ex-debug-toolbar .dropup .dropdown-menu,#ex-debug-toolbar .navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){#ex-debug-toolbar .navbar-right .dropdown-menu{right:0;left:auto}#ex-debug-toolbar .navbar-right .dropdown-menu-left{left:0;right:auto}}#ex-debug-toolbar .btn-group,#ex-debug-toolbar .btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}#ex-debug-toolbar .btn-group-vertical>.btn,#ex-debug-toolbar .btn-group>.btn{position:relative;float:left}#ex-debug-toolbar .btn-group-vertical>.btn.active,#ex-debug-toolbar .btn-group-vertical>.btn:active,#ex-debug-toolbar .btn-group-vertical>.btn:focus,#ex-debug-toolbar .btn-group-vertical>.btn:hover,#ex-debug-toolbar .btn-group>.btn.active,#ex-debug-toolbar .btn-group>.btn:active,#ex-debug-toolbar .btn-group>.btn:focus,#ex-debug-toolbar .btn-group>.btn:hover{z-index:2}#ex-debug-toolbar .btn-group .btn+.btn,#ex-debug-toolbar .btn-group .btn+.btn-group,#ex-debug-toolbar .btn-group .btn-group+.btn,#ex-debug-toolbar .btn-group .btn-group+.btn-group{margin-left:-1px}#ex-debug-toolbar .btn-toolbar{margin-left:-5px}#ex-debug-toolbar .btn-toolbar:after,#ex-debug-toolbar .btn-toolbar:before{content:" ";display:table}#ex-debug-toolbar .btn-toolbar:after{clear:both}#ex-debug-toolbar .btn-toolbar .btn,#ex-debug-toolbar .btn-toolbar .btn-group,#ex-debug-toolbar .btn-toolbar .input-group{float:left}#ex-debug-toolbar .btn-toolbar>.btn,#ex-debug-toolbar .btn-toolbar>.btn-group,#ex-debug-toolbar .btn-toolbar>.input-group{margin-left:5px}#ex-debug-toolbar .btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}#ex-debug-toolbar .btn-group>.btn:first-child{margin-left:0}#ex-debug-toolbar .btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}#ex-debug-toolbar .btn-group>.btn:last-child:not(:first-child),#ex-debug-toolbar .btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}#ex-debug-toolbar .btn-group>.btn-group{float:left}#ex-debug-toolbar .btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}#ex-debug-toolbar .btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,#ex-debug-toolbar .btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}#ex-debug-toolbar .btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}#ex-debug-toolbar .btn-group .dropdown-toggle:active,#ex-debug-toolbar .btn-group.open .dropdown-toggle{outline:0}#ex-debug-toolbar .btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}#ex-debug-toolbar .btn-group-lg.btn-group>.btn+.dropdown-toggle,#ex-debug-toolbar .btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}#ex-debug-toolbar .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)}#ex-debug-toolbar .btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}#ex-debug-toolbar .btn .caret{margin-left:0}#ex-debug-toolbar .btn-group-lg>.btn .caret,#ex-debug-toolbar .btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}#ex-debug-toolbar .dropup .btn-group-lg>.btn .caret,#ex-debug-toolbar .dropup .btn-lg .caret{border-width:0 5px 5px}#ex-debug-toolbar .btn-group-vertical>.btn,#ex-debug-toolbar .btn-group-vertical>.btn-group,#ex-debug-toolbar .btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}#ex-debug-toolbar .btn-group-vertical>.btn-group:after,#ex-debug-toolbar .btn-group-vertical>.btn-group:before{content:" ";display:table}#ex-debug-toolbar .btn-group-vertical>.btn-group:after{clear:both}#ex-debug-toolbar .btn-group-vertical>.btn-group>.btn{float:none}#ex-debug-toolbar .btn-group-vertical>.btn+.btn,#ex-debug-toolbar .btn-group-vertical>.btn+.btn-group,#ex-debug-toolbar .btn-group-vertical>.btn-group+.btn,#ex-debug-toolbar .btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}#ex-debug-toolbar .btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}#ex-debug-toolbar .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}#ex-debug-toolbar .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}#ex-debug-toolbar .btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}#ex-debug-toolbar .btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,#ex-debug-toolbar .btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}#ex-debug-toolbar .btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}#ex-debug-toolbar .btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}#ex-debug-toolbar .btn-group-justified>.btn,#ex-debug-toolbar .btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}#ex-debug-toolbar .btn-group-justified>.btn-group .btn{width:100%}#ex-debug-toolbar .btn-group-justified>.btn-group .dropdown-menu{left:auto}#ex-debug-toolbar [data-toggle=buttons]>.btn input[type=checkbox],#ex-debug-toolbar [data-toggle=buttons]>.btn input[type=radio],#ex-debug-toolbar [data-toggle=buttons]>.btn-group>.btn input[type=checkbox],#ex-debug-toolbar [data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}#ex-debug-toolbar .input-group{position:relative;display:table;border-collapse:separate}#ex-debug-toolbar .input-group[class*=col-]{float:none;padding-left:0;padding-right:0}#ex-debug-toolbar .input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}#ex-debug-toolbar .input-group .form-control:focus{z-index:3}#ex-debug-toolbar .input-group .form-control,#ex-debug-toolbar .input-group-addon,#ex-debug-toolbar .input-group-btn{display:table-cell}#ex-debug-toolbar .input-group .form-control:not(:first-child):not(:last-child),#ex-debug-toolbar .input-group-addon:not(:first-child):not(:last-child),#ex-debug-toolbar .input-group-btn:not(:first-child):not(:last-child){border-radius:0}#ex-debug-toolbar .input-group-addon,#ex-debug-toolbar .input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}#ex-debug-toolbar .input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}#ex-debug-toolbar .input-group-addon.input-sm,#ex-debug-toolbar .input-group-sm>.input-group-addon,#ex-debug-toolbar .input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}#ex-debug-toolbar .input-group-addon.input-lg,#ex-debug-toolbar .input-group-lg>.input-group-addon,#ex-debug-toolbar .input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}#ex-debug-toolbar .input-group-addon input[type=checkbox],#ex-debug-toolbar .input-group-addon input[type=radio]{margin-top:0}#ex-debug-toolbar .input-group .form-control:first-child,#ex-debug-toolbar .input-group-addon:first-child,#ex-debug-toolbar .input-group-btn:first-child>.btn,#ex-debug-toolbar .input-group-btn:first-child>.btn-group>.btn,#ex-debug-toolbar .input-group-btn:first-child>.dropdown-toggle,#ex-debug-toolbar .input-group-btn:last-child>.btn-group:not(:last-child)>.btn,#ex-debug-toolbar .input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}#ex-debug-toolbar .input-group-addon:first-child{border-right:0}#ex-debug-toolbar .input-group .form-control:last-child,#ex-debug-toolbar .input-group-addon:last-child,#ex-debug-toolbar .input-group-btn:first-child>.btn-group:not(:first-child)>.btn,#ex-debug-toolbar .input-group-btn:first-child>.btn:not(:first-child),#ex-debug-toolbar .input-group-btn:last-child>.btn,#ex-debug-toolbar .input-group-btn:last-child>.btn-group>.btn,#ex-debug-toolbar .input-group-btn:last-child>.dropdown-toggle{border-bottom-left-radius:0;border-top-left-radius:0}#ex-debug-toolbar .input-group-addon:last-child{border-left:0}#ex-debug-toolbar .input-group-btn{position:relative;font-size:0;white-space:nowrap}#ex-debug-toolbar .input-group-btn>.btn{position:relative}#ex-debug-toolbar .input-group-btn>.btn+.btn{margin-left:-1px}#ex-debug-toolbar .input-group-btn>.btn:active,#ex-debug-toolbar .input-group-btn>.btn:focus,#ex-debug-toolbar .input-group-btn>.btn:hover{z-index:2}#ex-debug-toolbar .input-group-btn:first-child>.btn,#ex-debug-toolbar .input-group-btn:first-child>.btn-group{margin-right:-1px}#ex-debug-toolbar .input-group-btn:last-child>.btn,#ex-debug-toolbar .input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}#ex-debug-toolbar .nav{margin-bottom:0;padding-left:0;list-style:none}#ex-debug-toolbar .nav:after,#ex-debug-toolbar .nav:before{content:" ";display:table}#ex-debug-toolbar .nav:after{clear:both}#ex-debug-toolbar .nav>li{position:relative;display:block}#ex-debug-toolbar .nav>li>a,#ex-debug-toolbar .navbar-nav.nav>li>span{position:relative;display:block;padding:10px 15px}#ex-debug-toolbar .nav>li>a:focus,#ex-debug-toolbar .nav>li>a:hover,#ex-debug-toolbar .navbar-nav.nav>li>span:focus,#ex-debug-toolbar .navbar-nav.nav>li>span:hover{text-decoration:none;background-color:#eee}#ex-debug-toolbar .nav>li.disabled>a,#ex-debug-toolbar .navbar-nav.nav>li.disabled>span{color:#777}#ex-debug-toolbar .nav>li.disabled>a:focus,#ex-debug-toolbar .nav>li.disabled>a:hover,#ex-debug-toolbar .navbar-nav.nav>li.disabled>span:focus,#ex-debug-toolbar .navbar-nav.nav>li.disabled>span:hover{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}#ex-debug-toolbar .nav .open>a,#ex-debug-toolbar .nav .open>a:focus,#ex-debug-toolbar .nav .open>a:hover,#ex-debug-toolbar .navbar-nav.nav>li.open>span,#ex-debug-toolbar .navbar-nav.nav>li.open>span:focus,#ex-debug-toolbar .navbar-nav.nav>li.open>span:hover{background-color:#eee;border-color:#337ab7}#ex-debug-toolbar .nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}#ex-debug-toolbar .nav>li>a>img,#ex-debug-toolbar .navbar-nav.nav>li>span>img{max-width:none}#ex-debug-toolbar .nav-tabs{border-bottom:1px solid #ddd}#ex-debug-toolbar .nav-tabs>li{float:left;margin-bottom:-1px}#ex-debug-toolbar .nav-tabs>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-tabs>li>span{margin-right:2px;line-height:1.42857;border:1px solid transparent;border-radius:4px 4px 0 0}#ex-debug-toolbar .nav-tabs>li>a:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs>li>span:hover{border-color:#eee #eee #ddd}#ex-debug-toolbar .nav-tabs>li.active>a,#ex-debug-toolbar .nav-tabs>li.active>a:focus,#ex-debug-toolbar .nav-tabs>li.active>a:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-tabs>li.active>span:hover{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}#ex-debug-toolbar .nav-pills>li{float:left}#ex-debug-toolbar .nav-pills>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-pills>li>span{border-radius:4px}#ex-debug-toolbar .nav-pills>li+li{margin-left:2px}#ex-debug-toolbar .nav-pills>li.active>a,#ex-debug-toolbar .nav-pills>li.active>a:focus,#ex-debug-toolbar .nav-pills>li.active>a:hover,#ex-debug-toolbar .navbar-nav.nav.nav-pills>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-pills>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-pills>li.active>span:hover{color:#fff;background-color:#337ab7}#ex-debug-toolbar .nav-stacked>li{float:none}#ex-debug-toolbar .nav-stacked>li+li{margin-top:2px;margin-left:0}#ex-debug-toolbar .nav-justified,#ex-debug-toolbar .nav-tabs.nav-justified{width:100%}#ex-debug-toolbar .nav-justified>li,#ex-debug-toolbar .nav-tabs.nav-justified>li{float:none}#ex-debug-toolbar .nav-justified>li>a,#ex-debug-toolbar .nav-tabs.nav-justified>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-justified>li>span{text-align:center;margin-bottom:5px}#ex-debug-toolbar .nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){#ex-debug-toolbar .nav-justified>li,#ex-debug-toolbar .nav-tabs.nav-justified>li{display:table-cell;width:1%}#ex-debug-toolbar .nav-justified>li>a,#ex-debug-toolbar .nav-tabs.nav-justified>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-justified>li>span{margin-bottom:0}}#ex-debug-toolbar .nav-tabs-justified,#ex-debug-toolbar .nav-tabs.nav-justified{border-bottom:0}#ex-debug-toolbar .nav-tabs-justified>li>a,#ex-debug-toolbar .nav-tabs.nav-justified>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li>span{margin-right:0;border-radius:4px}#ex-debug-toolbar .nav-tabs-justified>.active>a,#ex-debug-toolbar .nav-tabs-justified>.active>a:focus,#ex-debug-toolbar .nav-tabs-justified>.active>a:hover,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a:focus,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span:hover{border:1px solid #ddd}@media (min-width:768px){#ex-debug-toolbar .nav-tabs-justified>li>a,#ex-debug-toolbar .nav-tabs.nav-justified>li>a,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li>span{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}#ex-debug-toolbar .nav-tabs-justified>.active>a,#ex-debug-toolbar .nav-tabs-justified>.active>a:focus,#ex-debug-toolbar .nav-tabs-justified>.active>a:hover,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a:focus,#ex-debug-toolbar .nav-tabs.nav-justified>.active>a:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified>li.active>span:hover,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified>li.active>span:hover{border-bottom-color:#fff}}#ex-debug-toolbar .tab-content>.tab-pane{display:none}#ex-debug-toolbar .tab-content>.active{display:block}#ex-debug-toolbar .nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}#ex-debug-toolbar .navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}#ex-debug-toolbar .navbar:after,#ex-debug-toolbar .navbar:before{content:" ";display:table}#ex-debug-toolbar .navbar:after{clear:both}@media (min-width:768px){#ex-debug-toolbar .navbar{border-radius:4px}}#ex-debug-toolbar .navbar-header:after,#ex-debug-toolbar .navbar-header:before{content:" ";display:table}#ex-debug-toolbar .navbar-header:after{clear:both}@media (min-width:768px){#ex-debug-toolbar .navbar-header{float:left}}#ex-debug-toolbar .navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}#ex-debug-toolbar .navbar-collapse:after,#ex-debug-toolbar .navbar-collapse:before{content:" ";display:table}#ex-debug-toolbar .navbar-collapse:after{clear:both}#ex-debug-toolbar .navbar-collapse.in{overflow-y:auto}@media (min-width:768px){#ex-debug-toolbar .navbar-collapse{width:auto;border-top:0;box-shadow:none}#ex-debug-toolbar .navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}#ex-debug-toolbar .navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom #ex-debug-toolbar .navbar-collapse,.navbar-fixed-top #ex-debug-toolbar .navbar-collapse,.navbar-static-top #ex-debug-toolbar .navbar-collapse{padding-left:0;padding-right:0}}#ex-debug-toolbar .navbar-fixed-bottom .navbar-collapse,#ex-debug-toolbar .navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){#ex-debug-toolbar .navbar-fixed-bottom .navbar-collapse,#ex-debug-toolbar .navbar-fixed-top .navbar-collapse{max-height:200px}}#ex-debug-toolbar .container-fluid>.navbar-collapse,#ex-debug-toolbar .container-fluid>.navbar-header,#ex-debug-toolbar .container>.navbar-collapse,#ex-debug-toolbar .container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){#ex-debug-toolbar .container-fluid>.navbar-collapse,#ex-debug-toolbar .container-fluid>.navbar-header,#ex-debug-toolbar .container>.navbar-collapse,#ex-debug-toolbar .container>.navbar-header{margin-right:0;margin-left:0}}#ex-debug-toolbar .navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){#ex-debug-toolbar .navbar-static-top{border-radius:0}}#ex-debug-toolbar .navbar-fixed-bottom,#ex-debug-toolbar .navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){#ex-debug-toolbar .navbar-fixed-bottom,#ex-debug-toolbar .navbar-fixed-top{border-radius:0}}#ex-debug-toolbar .navbar-fixed-top{top:0;border-width:0 0 1px}#ex-debug-toolbar .navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}#ex-debug-toolbar .navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px;height:50px}#ex-debug-toolbar .navbar-brand:focus,#ex-debug-toolbar .navbar-brand:hover{text-decoration:none}#ex-debug-toolbar .navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container #ex-debug-toolbar .navbar-brand,.navbar>.container-fluid #ex-debug-toolbar .navbar-brand{margin-left:-15px}}#ex-debug-toolbar .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}#ex-debug-toolbar .navbar-toggle:focus{outline:0}#ex-debug-toolbar .navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}#ex-debug-toolbar .navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){#ex-debug-toolbar .navbar-toggle{display:none}}#ex-debug-toolbar .navbar-nav{margin:7.5px -15px}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar .navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){#ex-debug-toolbar .navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}#ex-debug-toolbar .navbar-nav .open .dropdown-menu .dropdown-header,#ex-debug-toolbar .navbar-nav .open .dropdown-menu>li>a,#ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span{padding:5px 15px 5px 25px}#ex-debug-toolbar .navbar-nav .open .dropdown-menu>li>a,#ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span{line-height:20px}#ex-debug-toolbar .navbar-nav .open .dropdown-menu>li>a:focus,#ex-debug-toolbar .navbar-nav .open .dropdown-menu>li>a:hover,#ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:focus,#ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:hover{background-image:none}}@media (min-width:768px){#ex-debug-toolbar .navbar-nav{float:left;margin:0}#ex-debug-toolbar .navbar-nav>li{float:left}#ex-debug-toolbar .navbar-nav.nav>li>span,#ex-debug-toolbar .navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}#ex-debug-toolbar .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,.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);margin-top:8px;margin-bottom:8px}@media (min-width:768px){#ex-debug-toolbar .navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}#ex-debug-toolbar .navbar-form .form-control-static{display:inline-block}#ex-debug-toolbar .navbar-form .input-group{display:inline-table;vertical-align:middle}#ex-debug-toolbar .navbar-form .input-group .form-control,#ex-debug-toolbar .navbar-form .input-group .input-group-addon,#ex-debug-toolbar .navbar-form .input-group .input-group-btn{width:auto}#ex-debug-toolbar .navbar-form .input-group>.form-control{width:100%}#ex-debug-toolbar .navbar-form .control-label{margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .navbar-form .checkbox,#ex-debug-toolbar .navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}#ex-debug-toolbar .navbar-form .checkbox label,#ex-debug-toolbar .navbar-form .radio label{padding-left:0}#ex-debug-toolbar .navbar-form .checkbox input[type=checkbox],#ex-debug-toolbar .navbar-form .radio input[type=radio]{position:relative;margin-left:0}#ex-debug-toolbar .navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){#ex-debug-toolbar .navbar-form .form-group{margin-bottom:5px}#ex-debug-toolbar .navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){#ex-debug-toolbar .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}}#ex-debug-toolbar .navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}#ex-debug-toolbar .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}#ex-debug-toolbar .navbar-btn{margin-top:8px;margin-bottom:8px}#ex-debug-toolbar .btn-group-sm>.navbar-btn.btn,#ex-debug-toolbar .navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}#ex-debug-toolbar .btn-group-xs>.navbar-btn.btn,#ex-debug-toolbar .navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}#ex-debug-toolbar .navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){#ex-debug-toolbar .navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){#ex-debug-toolbar .navbar-left{float:left!important}#ex-debug-toolbar .navbar-right{float:right!important;margin-right:-15px}#ex-debug-toolbar .navbar-right~.navbar-right{margin-right:0}}#ex-debug-toolbar .navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}#ex-debug-toolbar .navbar-default .navbar-brand{color:#777}#ex-debug-toolbar .navbar-default .navbar-brand:focus,#ex-debug-toolbar .navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}#ex-debug-toolbar .navbar-default .navbar-text{color:#777}#ex-debug-toolbar .navbar-default .navbar-nav.nav>li>span,#ex-debug-toolbar .navbar-default .navbar-nav>li>a{color:#777}#ex-debug-toolbar .navbar-default .navbar-nav.nav>li>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li>span:hover,#ex-debug-toolbar .navbar-default .navbar-nav>li>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.active>span,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.active>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.active>span:hover,#ex-debug-toolbar .navbar-default .navbar-nav>.active>a,#ex-debug-toolbar .navbar-default .navbar-nav>.active>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.disabled>span,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.disabled>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.disabled>span:hover,#ex-debug-toolbar .navbar-default .navbar-nav>.disabled>a,#ex-debug-toolbar .navbar-default .navbar-nav>.disabled>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}#ex-debug-toolbar .navbar-default .navbar-toggle{border-color:#ddd}#ex-debug-toolbar .navbar-default .navbar-toggle:focus,#ex-debug-toolbar .navbar-default .navbar-toggle:hover{background-color:#ddd}#ex-debug-toolbar .navbar-default .navbar-toggle .icon-bar{background-color:#888}#ex-debug-toolbar .navbar-default .navbar-collapse,#ex-debug-toolbar .navbar-default .navbar-form{border-color:#e7e7e7}#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.open>span,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.open>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav.nav>li.open>span:hover,#ex-debug-toolbar .navbar-default .navbar-nav>.open>a,#ex-debug-toolbar .navbar-default .navbar-nav>.open>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav>.open>a:hover{background-color:#e7e7e7;color:#555}@media (max-width:767px){#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>li>a,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span{color:#777}#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:hover{color:#333;background-color:transparent}#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.active>a,#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span:hover{color:#555;background-color:#e7e7e7}#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span:focus,#ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span:hover{color:#ccc;background-color:transparent}}#ex-debug-toolbar .navbar-default .navbar-link{color:#777}#ex-debug-toolbar .navbar-default .navbar-link:hover{color:#333}#ex-debug-toolbar .navbar-default .btn-link{color:#777}#ex-debug-toolbar .navbar-default .btn-link:focus,#ex-debug-toolbar .navbar-default .btn-link:hover{color:#333}#ex-debug-toolbar .navbar-default .btn-link[disabled]:focus,#ex-debug-toolbar .navbar-default .btn-link[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .navbar-default .btn-link:focus,fieldset[disabled] #ex-debug-toolbar .navbar-default .btn-link:hover{color:#ccc}#ex-debug-toolbar .navbar-inverse{background-color:#222;border-color:#090909}#ex-debug-toolbar .navbar-inverse .navbar-brand{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .navbar-brand:focus,#ex-debug-toolbar .navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}#ex-debug-toolbar .navbar-inverse .navbar-text{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li>span,#ex-debug-toolbar .navbar-inverse .navbar-nav>li>a{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li>span:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav>li>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.active>span,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.active>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.active>span:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav>.active>a,#ex-debug-toolbar .navbar-inverse .navbar-nav>.active>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#090909}#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.disabled>span,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.disabled>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.disabled>span:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav>.disabled>a,#ex-debug-toolbar .navbar-inverse .navbar-nav>.disabled>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}#ex-debug-toolbar .navbar-inverse .navbar-toggle{border-color:#333}#ex-debug-toolbar .navbar-inverse .navbar-toggle:focus,#ex-debug-toolbar .navbar-inverse .navbar-toggle:hover{background-color:#333}#ex-debug-toolbar .navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}#ex-debug-toolbar .navbar-inverse .navbar-collapse,#ex-debug-toolbar .navbar-inverse .navbar-form{border-color:#101010}#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.open>span,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.open>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav.nav>li.open>span:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav>.open>a,#ex-debug-toolbar .navbar-inverse .navbar-nav>.open>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav>.open>a:hover{background-color:#090909;color:#fff}@media (max-width:767px){#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#090909}#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>li>a,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li>span:hover{color:#fff;background-color:transparent}#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.active>span:hover{color:#fff;background-color:#090909}#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span:focus,#ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu>li.disabled>span:hover{color:#444;background-color:transparent}}#ex-debug-toolbar .navbar-inverse .navbar-link{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .navbar-link:hover{color:#fff}#ex-debug-toolbar .navbar-inverse .btn-link{color:#9d9d9d}#ex-debug-toolbar .navbar-inverse .btn-link:focus,#ex-debug-toolbar .navbar-inverse .btn-link:hover{color:#fff}#ex-debug-toolbar .navbar-inverse .btn-link[disabled]:focus,#ex-debug-toolbar .navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] #ex-debug-toolbar .navbar-inverse .btn-link:focus,fieldset[disabled] #ex-debug-toolbar .navbar-inverse .btn-link:hover{color:#444}#ex-debug-toolbar .breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}#ex-debug-toolbar .breadcrumb>li{display:inline-block}#ex-debug-toolbar .breadcrumb>li+li:before{content:"/ ";padding:0 5px;color:#ccc}#ex-debug-toolbar .breadcrumb>.active{color:#777}#ex-debug-toolbar .pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}#ex-debug-toolbar .pagination>li{display:inline}#ex-debug-toolbar .navbar-nav.nav.pagination>li>span,#ex-debug-toolbar .pagination>li>a,#ex-debug-toolbar .pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.42857;text-decoration:none;color:#337ab7;background-color:#fff;border:1px solid #ddd;margin-left:-1px}#ex-debug-toolbar .navbar-nav.nav.pagination>li:first-child>span,#ex-debug-toolbar .pagination>li:first-child>a,#ex-debug-toolbar .pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}#ex-debug-toolbar .navbar-nav.nav.pagination>li:last-child>span,#ex-debug-toolbar .pagination>li:last-child>a,#ex-debug-toolbar .pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}#ex-debug-toolbar .navbar-nav.nav.pagination>li>span:focus,#ex-debug-toolbar .navbar-nav.nav.pagination>li>span:hover,#ex-debug-toolbar .pagination>li>a:focus,#ex-debug-toolbar .pagination>li>a:hover,#ex-debug-toolbar .pagination>li>span:focus,#ex-debug-toolbar .pagination>li>span:hover{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}#ex-debug-toolbar .navbar-nav.nav.pagination>li.active>span,#ex-debug-toolbar .navbar-nav.nav.pagination>li.active>span:focus,#ex-debug-toolbar .navbar-nav.nav.pagination>li.active>span:hover,#ex-debug-toolbar .pagination>.active>a,#ex-debug-toolbar .pagination>.active>a:focus,#ex-debug-toolbar .pagination>.active>a:hover,#ex-debug-toolbar .pagination>.active>span,#ex-debug-toolbar .pagination>.active>span:focus,#ex-debug-toolbar .pagination>.active>span:hover{z-index:3;color:#fff;background-color:#337ab7;border-color:#337ab7;cursor:default}#ex-debug-toolbar .navbar-nav.nav.pagination>li.disabled>span,#ex-debug-toolbar .navbar-nav.nav.pagination>li.disabled>span:focus,#ex-debug-toolbar .navbar-nav.nav.pagination>li.disabled>span:hover,#ex-debug-toolbar .pagination>.disabled>a,#ex-debug-toolbar .pagination>.disabled>a:focus,#ex-debug-toolbar .pagination>.disabled>a:hover,#ex-debug-toolbar .pagination>.disabled>span,#ex-debug-toolbar .pagination>.disabled>span:focus,#ex-debug-toolbar .pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}#ex-debug-toolbar .navbar-nav.nav.pagination-lg>li>span,#ex-debug-toolbar .pagination-lg>li>a,#ex-debug-toolbar .pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.33333}#ex-debug-toolbar .navbar-nav.nav.pagination-lg>li:first-child>span,#ex-debug-toolbar .pagination-lg>li:first-child>a,#ex-debug-toolbar .pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}#ex-debug-toolbar .navbar-nav.nav.pagination-lg>li:last-child>span,#ex-debug-toolbar .pagination-lg>li:last-child>a,#ex-debug-toolbar .pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}#ex-debug-toolbar .navbar-nav.nav.pagination-sm>li>span,#ex-debug-toolbar .pagination-sm>li>a,#ex-debug-toolbar .pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}#ex-debug-toolbar .navbar-nav.nav.pagination-sm>li:first-child>span,#ex-debug-toolbar .pagination-sm>li:first-child>a,#ex-debug-toolbar .pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}#ex-debug-toolbar .navbar-nav.nav.pagination-sm>li:last-child>span,#ex-debug-toolbar .pagination-sm>li:last-child>a,#ex-debug-toolbar .pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}#ex-debug-toolbar .pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}#ex-debug-toolbar .pager:after,#ex-debug-toolbar .pager:before{content:" ";display:table}#ex-debug-toolbar .pager:after{clear:both}#ex-debug-toolbar .pager li{display:inline}#ex-debug-toolbar .pager .navbar-nav.nav>li>span,#ex-debug-toolbar .pager li>a,#ex-debug-toolbar .pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}#ex-debug-toolbar .pager .navbar-nav.nav>li>span:focus,#ex-debug-toolbar .pager .navbar-nav.nav>li>span:hover,#ex-debug-toolbar .pager li>a:focus,#ex-debug-toolbar .pager li>a:hover{text-decoration:none;background-color:#eee}#ex-debug-toolbar .pager .navbar-nav.nav>li.next>span,#ex-debug-toolbar .pager .next>a,#ex-debug-toolbar .pager .next>span{float:right}#ex-debug-toolbar .pager .navbar-nav.nav>li.previous>span,#ex-debug-toolbar .pager .previous>a,#ex-debug-toolbar .pager .previous>span{float:left}#ex-debug-toolbar .pager .disabled>a,#ex-debug-toolbar .pager .disabled>a:focus,#ex-debug-toolbar .pager .disabled>a:hover,#ex-debug-toolbar .pager .disabled>span,#ex-debug-toolbar .pager .navbar-nav.nav>li.disabled>span,#ex-debug-toolbar .pager .navbar-nav.nav>li.disabled>span:focus,#ex-debug-toolbar .pager .navbar-nav.nav>li.disabled>span:hover{color:#777;background-color:#fff;cursor:not-allowed}#ex-debug-toolbar .label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}#ex-debug-toolbar .label:empty{display:none}.btn #ex-debug-toolbar .label{position:relative;top:-1px}#ex-debug-toolbar .navbar-nav.nav>li>span.label:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.label:hover,#ex-debug-toolbar a.label:focus,#ex-debug-toolbar a.label:hover{color:#fff;text-decoration:none;cursor:pointer}#ex-debug-toolbar .label-default{background-color:#777}#ex-debug-toolbar .label-default[href]:focus,#ex-debug-toolbar .label-default[href]:hover{background-color:#5e5e5e}#ex-debug-toolbar .label-primary{background-color:#337ab7}#ex-debug-toolbar .label-primary[href]:focus,#ex-debug-toolbar .label-primary[href]:hover{background-color:#286090}#ex-debug-toolbar .label-success{background-color:#5cb85c}#ex-debug-toolbar .label-success[href]:focus,#ex-debug-toolbar .label-success[href]:hover{background-color:#449d44}#ex-debug-toolbar .label-info{background-color:#5bc0de}#ex-debug-toolbar .label-info[href]:focus,#ex-debug-toolbar .label-info[href]:hover{background-color:#31b0d5}#ex-debug-toolbar .label-warning{background-color:#f0ad4e}#ex-debug-toolbar .label-warning[href]:focus,#ex-debug-toolbar .label-warning[href]:hover{background-color:#ec971f}#ex-debug-toolbar .label-danger{background-color:#d9534f}#ex-debug-toolbar .label-danger[href]:focus,#ex-debug-toolbar .label-danger[href]:hover{background-color:#c9302c}#ex-debug-toolbar .badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}#ex-debug-toolbar .badge:empty{display:none}.btn #ex-debug-toolbar .badge{position:relative;top:-1px}#ex-debug-toolbar .btn-group-xs>.btn #ex-debug-toolbar .badge,.btn-group-xs>.btn #ex-debug-toolbar .badge,.btn-xs #ex-debug-toolbar .badge{top:0;padding:1px 5px}#ex-debug-toolbar .navbar-nav.nav.nav-pills>li.active>span>#ex-debug-toolbar .badge,.list-group-item.active>#ex-debug-toolbar .badge,.nav-pills>.active>a>#ex-debug-toolbar .badge{color:#337ab7;background-color:#fff}.list-group-item>#ex-debug-toolbar .badge{float:right}.list-group-item>#ex-debug-toolbar .badge+#ex-debug-toolbar .badge{margin-right:5px}#ex-debug-toolbar .navbar-nav.nav.nav-pills>li>span>#ex-debug-toolbar .badge,.nav-pills>li>a>#ex-debug-toolbar .badge{margin-left:3px}#ex-debug-toolbar .navbar-nav.nav>li>span.badge:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.badge:hover,#ex-debug-toolbar a.badge:focus,#ex-debug-toolbar a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}#ex-debug-toolbar .jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}#ex-debug-toolbar .jumbotron .h1,#ex-debug-toolbar .jumbotron h1{color:inherit}#ex-debug-toolbar .jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}#ex-debug-toolbar .jumbotron>hr{border-top-color:#d5d5d5}.container #ex-debug-toolbar .jumbotron,.container-fluid #ex-debug-toolbar .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}#ex-debug-toolbar .jumbotron .container{max-width:100%}@media screen and (min-width:768px){#ex-debug-toolbar .jumbotron{padding-top:48px;padding-bottom:48px}.container #ex-debug-toolbar .jumbotron,.container-fluid #ex-debug-toolbar .jumbotron{padding-left:60px;padding-right:60px}#ex-debug-toolbar .jumbotron .h1,#ex-debug-toolbar .jumbotron h1{font-size:63px}}#ex-debug-toolbar .thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857;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}#ex-debug-toolbar .thumbnail .navbar-nav.nav>li>span>img,#ex-debug-toolbar .thumbnail a>img,#ex-debug-toolbar .thumbnail>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}#ex-debug-toolbar .thumbnail .caption{padding:9px;color:#333}#ex-debug-toolbar .navbar-nav.nav>li>span.thumbnail.active,#ex-debug-toolbar .navbar-nav.nav>li>span.thumbnail:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.thumbnail:hover,#ex-debug-toolbar a.thumbnail.active,#ex-debug-toolbar a.thumbnail:focus,#ex-debug-toolbar a.thumbnail:hover{border-color:#337ab7}#ex-debug-toolbar .alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}#ex-debug-toolbar .alert h4{margin-top:0;color:inherit}#ex-debug-toolbar .alert .alert-link{font-weight:700}#ex-debug-toolbar .alert>p,#ex-debug-toolbar .alert>ul{margin-bottom:0}#ex-debug-toolbar .alert>p+p{margin-top:5px}#ex-debug-toolbar .alert-dismissable,#ex-debug-toolbar .alert-dismissible{padding-right:35px}#ex-debug-toolbar .alert-dismissable .close,#ex-debug-toolbar .alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}#ex-debug-toolbar .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}#ex-debug-toolbar .alert-success hr{border-top-color:#c9e2b3}#ex-debug-toolbar .alert-success .alert-link{color:#2b542c}#ex-debug-toolbar .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}#ex-debug-toolbar .alert-info hr{border-top-color:#a6e1ec}#ex-debug-toolbar .alert-info .alert-link{color:#245269}#ex-debug-toolbar .alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}#ex-debug-toolbar .alert-warning hr{border-top-color:#f7e1b5}#ex-debug-toolbar .alert-warning .alert-link{color:#66512c}#ex-debug-toolbar .alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}#ex-debug-toolbar .alert-danger hr{border-top-color:#e4b9c0}#ex-debug-toolbar .alert-danger .alert-link{color:#843534}@-webkit-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}}#ex-debug-toolbar .progress{overflow:hidden;height:20px;margin-bottom:20px;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)}#ex-debug-toolbar .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}#ex-debug-toolbar .progress-bar-striped,#ex-debug-toolbar .progress-striped .progress-bar{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);background-size:40px 40px}#ex-debug-toolbar .progress-bar.active,#ex-debug-toolbar .progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}#ex-debug-toolbar .progress-bar-success{background-color:#5cb85c}.progress-striped #ex-debug-toolbar .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)}#ex-debug-toolbar .progress-bar-info{background-color:#5bc0de}.progress-striped #ex-debug-toolbar .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)}#ex-debug-toolbar .progress-bar-warning{background-color:#f0ad4e}.progress-striped #ex-debug-toolbar .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)}#ex-debug-toolbar .progress-bar-danger{background-color:#d9534f}.progress-striped #ex-debug-toolbar .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)}#ex-debug-toolbar .media{margin-top:15px}#ex-debug-toolbar .media:first-child{margin-top:0}#ex-debug-toolbar .media,#ex-debug-toolbar .media-body{zoom:1;overflow:hidden}#ex-debug-toolbar .media-body{width:10000px}#ex-debug-toolbar .media-object{display:block}#ex-debug-toolbar .media-object.img-thumbnail{max-width:none}#ex-debug-toolbar .media-right,#ex-debug-toolbar .media>.pull-right{padding-left:10px}#ex-debug-toolbar .media-left,#ex-debug-toolbar .media>.pull-left{padding-right:10px}#ex-debug-toolbar .media-body,#ex-debug-toolbar .media-left,#ex-debug-toolbar .media-right{display:table-cell;vertical-align:top}#ex-debug-toolbar .media-middle{vertical-align:middle}#ex-debug-toolbar .media-bottom{vertical-align:bottom}#ex-debug-toolbar .media-heading{margin-top:0;margin-bottom:5px}#ex-debug-toolbar .media-list{padding-left:0;list-style:none}#ex-debug-toolbar .list-group{margin-bottom:20px;padding-left:0}#ex-debug-toolbar .list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}#ex-debug-toolbar .list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}#ex-debug-toolbar .list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item,#ex-debug-toolbar a.list-group-item,#ex-debug-toolbar button.list-group-item{color:#555}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item .list-group-item-heading,#ex-debug-toolbar a.list-group-item .list-group-item-heading,#ex-debug-toolbar button.list-group-item .list-group-item-heading{color:#333}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item:hover,#ex-debug-toolbar a.list-group-item:focus,#ex-debug-toolbar a.list-group-item:hover,#ex-debug-toolbar button.list-group-item:focus,#ex-debug-toolbar button.list-group-item:hover{text-decoration:none;color:#555;background-color:#f5f5f5}#ex-debug-toolbar button.list-group-item{width:100%;text-align:left}#ex-debug-toolbar .list-group-item.disabled,#ex-debug-toolbar .list-group-item.disabled:focus,#ex-debug-toolbar .list-group-item.disabled:hover{background-color:#eee;color:#777;cursor:not-allowed}#ex-debug-toolbar .list-group-item.disabled .list-group-item-heading,#ex-debug-toolbar .list-group-item.disabled:focus .list-group-item-heading,#ex-debug-toolbar .list-group-item.disabled:hover .list-group-item-heading{color:inherit}#ex-debug-toolbar .list-group-item.disabled .list-group-item-text,#ex-debug-toolbar .list-group-item.disabled:focus .list-group-item-text,#ex-debug-toolbar .list-group-item.disabled:hover .list-group-item-text{color:#777}#ex-debug-toolbar .list-group-item.active,#ex-debug-toolbar .list-group-item.active:focus,#ex-debug-toolbar .list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}#ex-debug-toolbar .list-group-item.active .list-group-item-heading,#ex-debug-toolbar .list-group-item.active .list-group-item-heading>.small,#ex-debug-toolbar .list-group-item.active .list-group-item-heading>small,#ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading,#ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading>.small,#ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading>small,#ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading,#ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading>.small,#ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading>small{color:inherit}#ex-debug-toolbar .list-group-item.active .list-group-item-text,#ex-debug-toolbar .list-group-item.active:focus .list-group-item-text,#ex-debug-toolbar .list-group-item.active:hover .list-group-item-text{color:#c7ddef}#ex-debug-toolbar .list-group-item-success{color:#3c763d;background-color:#dff0d8}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success,#ex-debug-toolbar a.list-group-item-success,#ex-debug-toolbar button.list-group-item-success{color:#3c763d}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success .list-group-item-heading,#ex-debug-toolbar a.list-group-item-success .list-group-item-heading,#ex-debug-toolbar button.list-group-item-success .list-group-item-heading{color:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success:hover,#ex-debug-toolbar a.list-group-item-success:focus,#ex-debug-toolbar a.list-group-item-success:hover,#ex-debug-toolbar button.list-group-item-success:focus,#ex-debug-toolbar button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success.active,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success.active:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-success.active:hover,#ex-debug-toolbar a.list-group-item-success.active,#ex-debug-toolbar a.list-group-item-success.active:focus,#ex-debug-toolbar a.list-group-item-success.active:hover,#ex-debug-toolbar button.list-group-item-success.active,#ex-debug-toolbar button.list-group-item-success.active:focus,#ex-debug-toolbar button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}#ex-debug-toolbar .list-group-item-info{color:#31708f;background-color:#d9edf7}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info,#ex-debug-toolbar a.list-group-item-info,#ex-debug-toolbar button.list-group-item-info{color:#31708f}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info .list-group-item-heading,#ex-debug-toolbar a.list-group-item-info .list-group-item-heading,#ex-debug-toolbar button.list-group-item-info .list-group-item-heading{color:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info:hover,#ex-debug-toolbar a.list-group-item-info:focus,#ex-debug-toolbar a.list-group-item-info:hover,#ex-debug-toolbar button.list-group-item-info:focus,#ex-debug-toolbar button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info.active,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info.active:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-info.active:hover,#ex-debug-toolbar a.list-group-item-info.active,#ex-debug-toolbar a.list-group-item-info.active:focus,#ex-debug-toolbar a.list-group-item-info.active:hover,#ex-debug-toolbar button.list-group-item-info.active,#ex-debug-toolbar button.list-group-item-info.active:focus,#ex-debug-toolbar button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}#ex-debug-toolbar .list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning,#ex-debug-toolbar a.list-group-item-warning,#ex-debug-toolbar button.list-group-item-warning{color:#8a6d3b}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning .list-group-item-heading,#ex-debug-toolbar a.list-group-item-warning .list-group-item-heading,#ex-debug-toolbar button.list-group-item-warning .list-group-item-heading{color:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning:hover,#ex-debug-toolbar a.list-group-item-warning:focus,#ex-debug-toolbar a.list-group-item-warning:hover,#ex-debug-toolbar button.list-group-item-warning:focus,#ex-debug-toolbar button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning.active,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning.active:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-warning.active:hover,#ex-debug-toolbar a.list-group-item-warning.active,#ex-debug-toolbar a.list-group-item-warning.active:focus,#ex-debug-toolbar a.list-group-item-warning.active:hover,#ex-debug-toolbar button.list-group-item-warning.active,#ex-debug-toolbar button.list-group-item-warning.active:focus,#ex-debug-toolbar button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}#ex-debug-toolbar .list-group-item-danger{color:#a94442;background-color:#f2dede}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger,#ex-debug-toolbar a.list-group-item-danger,#ex-debug-toolbar button.list-group-item-danger{color:#a94442}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger .list-group-item-heading,#ex-debug-toolbar a.list-group-item-danger .list-group-item-heading,#ex-debug-toolbar button.list-group-item-danger .list-group-item-heading{color:inherit}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger:hover,#ex-debug-toolbar a.list-group-item-danger:focus,#ex-debug-toolbar a.list-group-item-danger:hover,#ex-debug-toolbar button.list-group-item-danger:focus,#ex-debug-toolbar button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger.active,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger.active:focus,#ex-debug-toolbar .navbar-nav.nav>li>span.list-group-item-danger.active:hover,#ex-debug-toolbar a.list-group-item-danger.active,#ex-debug-toolbar a.list-group-item-danger.active:focus,#ex-debug-toolbar a.list-group-item-danger.active:hover,#ex-debug-toolbar button.list-group-item-danger.active,#ex-debug-toolbar button.list-group-item-danger.active:focus,#ex-debug-toolbar button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}#ex-debug-toolbar .list-group-item-heading{margin-top:0;margin-bottom:5px}#ex-debug-toolbar .list-group-item-text{margin-bottom:0;line-height:1.3}#ex-debug-toolbar .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)}#ex-debug-toolbar .panel-body{padding:15px}#ex-debug-toolbar .panel-body:after,#ex-debug-toolbar .panel-body:before{content:" ";display:table}#ex-debug-toolbar .panel-body:after{clear:both}#ex-debug-toolbar .panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}#ex-debug-toolbar .panel-heading>.dropdown .dropdown-toggle{color:inherit}#ex-debug-toolbar .panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}#ex-debug-toolbar .navbar-nav.nav.panel-title>li.small>span,#ex-debug-toolbar .navbar-nav.nav>li.panel-title>span,#ex-debug-toolbar .panel-title>.small,#ex-debug-toolbar .panel-title>.small>a,#ex-debug-toolbar .panel-title>a,#ex-debug-toolbar .panel-title>small,#ex-debug-toolbar .panel-title>small>a{color:inherit}#ex-debug-toolbar .panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}#ex-debug-toolbar .panel>.list-group,#ex-debug-toolbar .panel>.panel-collapse>.list-group{margin-bottom:0}#ex-debug-toolbar .panel>.list-group .list-group-item,#ex-debug-toolbar .panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}#ex-debug-toolbar .panel>.list-group:first-child .list-group-item:first-child,#ex-debug-toolbar .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}#ex-debug-toolbar .panel>.list-group:last-child .list-group-item:last-child,#ex-debug-toolbar .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}#ex-debug-toolbar .panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}#ex-debug-toolbar .panel-heading+.list-group .list-group-item:first-child{border-top-width:0}#ex-debug-toolbar .list-group+.panel-footer{border-top-width:0}#ex-debug-toolbar .panel>.panel-collapse>.table,#ex-debug-toolbar .panel>.table,#ex-debug-toolbar .panel>.table-responsive>.table{margin-bottom:0}#ex-debug-toolbar .panel>.panel-collapse>.table caption,#ex-debug-toolbar .panel>.table caption,#ex-debug-toolbar .panel>.table-responsive>.table caption{padding-left:15px;padding-right:15px}#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child,#ex-debug-toolbar .panel>.table:first-child{border-top-right-radius:3px;border-top-left-radius:3px}#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,#ex-debug-toolbar .panel>.table:first-child>tbody:first-child>tr:first-child,#ex-debug-toolbar .panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,#ex-debug-toolbar .panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,#ex-debug-toolbar .panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,#ex-debug-toolbar .panel>.table:first-child>thead:first-child>tr:first-child td:first-child,#ex-debug-toolbar .panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,#ex-debug-toolbar .panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,#ex-debug-toolbar .panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,#ex-debug-toolbar .panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,#ex-debug-toolbar .panel>.table:first-child>thead:first-child>tr:first-child td:last-child,#ex-debug-toolbar .panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child,#ex-debug-toolbar .panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,#ex-debug-toolbar .panel>.table:last-child>tbody:last-child>tr:last-child,#ex-debug-toolbar .panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-left-radius:3px;border-bottom-right-radius:3px}#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,#ex-debug-toolbar .panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,#ex-debug-toolbar .panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,#ex-debug-toolbar .panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,#ex-debug-toolbar .panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,#ex-debug-toolbar .panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,#ex-debug-toolbar .panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,#ex-debug-toolbar .panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,#ex-debug-toolbar .panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,#ex-debug-toolbar .panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}#ex-debug-toolbar .panel>.panel-body+.table,#ex-debug-toolbar .panel>.panel-body+.table-responsive,#ex-debug-toolbar .panel>.table+.panel-body,#ex-debug-toolbar .panel>.table-responsive+.panel-body{border-top:1px solid #ddd}#ex-debug-toolbar .panel>.table>tbody:first-child>tr:first-child td,#ex-debug-toolbar .panel>.table>tbody:first-child>tr:first-child th{border-top:0}#ex-debug-toolbar .panel>.table-bordered,#ex-debug-toolbar .panel>.table-responsive>.table-bordered{border:0}#ex-debug-toolbar .panel>.table-bordered>tbody>tr>td:first-child,#ex-debug-toolbar .panel>.table-bordered>tbody>tr>th:first-child,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr>td:first-child,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr>th:first-child,#ex-debug-toolbar .panel>.table-bordered>thead>tr>td:first-child,#ex-debug-toolbar .panel>.table-bordered>thead>tr>th:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr>td:first-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}#ex-debug-toolbar .panel>.table-bordered>tbody>tr>td:last-child,#ex-debug-toolbar .panel>.table-bordered>tbody>tr>th:last-child,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr>td:last-child,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr>th:last-child,#ex-debug-toolbar .panel>.table-bordered>thead>tr>td:last-child,#ex-debug-toolbar .panel>.table-bordered>thead>tr>th:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr>td:last-child,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}#ex-debug-toolbar .panel>.table-bordered>tbody>tr:first-child>td,#ex-debug-toolbar .panel>.table-bordered>tbody>tr:first-child>th,#ex-debug-toolbar .panel>.table-bordered>thead>tr:first-child>td,#ex-debug-toolbar .panel>.table-bordered>thead>tr:first-child>th,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr:first-child>td,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}#ex-debug-toolbar .panel>.table-bordered>tbody>tr:last-child>td,#ex-debug-toolbar .panel>.table-bordered>tbody>tr:last-child>th,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr:last-child>td,#ex-debug-toolbar .panel>.table-bordered>tfoot>tr:last-child>th,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,#ex-debug-toolbar .panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}#ex-debug-toolbar .panel>.table-responsive{border:0;margin-bottom:0}#ex-debug-toolbar .panel-group{margin-bottom:20px}#ex-debug-toolbar .panel-group .panel{margin-bottom:0;border-radius:4px}#ex-debug-toolbar .panel-group .panel+.panel{margin-top:5px}#ex-debug-toolbar .panel-group .panel-heading{border-bottom:0}#ex-debug-toolbar .panel-group .panel-heading+.panel-collapse>.list-group,#ex-debug-toolbar .panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}#ex-debug-toolbar .panel-group .panel-footer{border-top:0}#ex-debug-toolbar .panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}#ex-debug-toolbar .panel-default{border-color:#ddd}#ex-debug-toolbar .panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}#ex-debug-toolbar .panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}#ex-debug-toolbar .panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}#ex-debug-toolbar .panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}#ex-debug-toolbar .panel-primary{border-color:#337ab7}#ex-debug-toolbar .panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}#ex-debug-toolbar .panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}#ex-debug-toolbar .panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}#ex-debug-toolbar .panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}#ex-debug-toolbar .panel-success{border-color:#d6e9c6}#ex-debug-toolbar .panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}#ex-debug-toolbar .panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}#ex-debug-toolbar .panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}#ex-debug-toolbar .panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}#ex-debug-toolbar .panel-info{border-color:#bce8f1}#ex-debug-toolbar .panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}#ex-debug-toolbar .panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}#ex-debug-toolbar .panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}#ex-debug-toolbar .panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}#ex-debug-toolbar .panel-warning{border-color:#faebcc}#ex-debug-toolbar .panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}#ex-debug-toolbar .panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}#ex-debug-toolbar .panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}#ex-debug-toolbar .panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}#ex-debug-toolbar .panel-danger{border-color:#ebccd1}#ex-debug-toolbar .panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}#ex-debug-toolbar .panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}#ex-debug-toolbar .panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}#ex-debug-toolbar .panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}#ex-debug-toolbar .embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}#ex-debug-toolbar .embed-responsive .embed-responsive-item,#ex-debug-toolbar .embed-responsive embed,#ex-debug-toolbar .embed-responsive iframe,#ex-debug-toolbar .embed-responsive object,#ex-debug-toolbar .embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}#ex-debug-toolbar .embed-responsive-16by9{padding-bottom:56.25%}#ex-debug-toolbar .embed-responsive-4by3{padding-bottom:75%}#ex-debug-toolbar .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)}#ex-debug-toolbar .well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}#ex-debug-toolbar .well-lg{padding:24px;border-radius:6px}#ex-debug-toolbar .well-sm{padding:9px;border-radius:3px}#ex-debug-toolbar .close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}#ex-debug-toolbar .close:focus,#ex-debug-toolbar .close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}#ex-debug-toolbar button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}#ex-debug-toolbar .modal-open{overflow:hidden}#ex-debug-toolbar .modal{display:none;overflow:hidden;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}#ex-debug-toolbar .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 .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}#ex-debug-toolbar .modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}#ex-debug-toolbar .modal-open .modal{overflow-x:hidden;overflow-y:auto}#ex-debug-toolbar .modal-dialog{position:relative;width:auto;margin:10px}#ex-debug-toolbar .modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}#ex-debug-toolbar .modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}#ex-debug-toolbar .modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}#ex-debug-toolbar .modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}#ex-debug-toolbar .modal-header{padding:15px;border-bottom:1px solid #e5e5e5}#ex-debug-toolbar .modal-header:after,#ex-debug-toolbar .modal-header:before{content:" ";display:table}#ex-debug-toolbar .modal-header:after{clear:both}#ex-debug-toolbar .modal-header .close{margin-top:-2px}#ex-debug-toolbar .modal-title{margin:0;line-height:1.42857}#ex-debug-toolbar .modal-body{position:relative;padding:15px}#ex-debug-toolbar .modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}#ex-debug-toolbar .modal-footer:after,#ex-debug-toolbar .modal-footer:before{content:" ";display:table}#ex-debug-toolbar .modal-footer:after{clear:both}#ex-debug-toolbar .modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}#ex-debug-toolbar .modal-footer .btn-group .btn+.btn{margin-left:-1px}#ex-debug-toolbar .modal-footer .btn-block+.btn-block{margin-left:0}#ex-debug-toolbar .modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){#ex-debug-toolbar .modal-dialog{width:600px;margin:30px auto}#ex-debug-toolbar .modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}#ex-debug-toolbar .modal-sm{width:300px}}@media (min-width:992px){#ex-debug-toolbar .modal-lg{width:900px}}#ex-debug-toolbar .tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.42857;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)}#ex-debug-toolbar .tooltip.in{opacity:.9;filter:alpha(opacity=90)}#ex-debug-toolbar .tooltip.top{margin-top:-3px;padding:5px 0}#ex-debug-toolbar .tooltip.right{margin-left:3px;padding:0 5px}#ex-debug-toolbar .tooltip.bottom{margin-top:3px;padding:5px 0}#ex-debug-toolbar .tooltip.left{margin-left:-3px;padding:0 5px}#ex-debug-toolbar .tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}#ex-debug-toolbar .tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}#ex-debug-toolbar .tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}#ex-debug-toolbar .tooltip.top-left .tooltip-arrow{bottom:0;right:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}#ex-debug-toolbar .tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}#ex-debug-toolbar .tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}#ex-debug-toolbar .tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}#ex-debug-toolbar .tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}#ex-debug-toolbar .tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}#ex-debug-toolbar .tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}#ex-debug-toolbar .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:400;letter-spacing:normal;line-break:auto;line-height:1.42857;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:#fff;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)}#ex-debug-toolbar .popover.top{margin-top:-10px}#ex-debug-toolbar .popover.right{margin-left:10px}#ex-debug-toolbar .popover.bottom{margin-top:10px}#ex-debug-toolbar .popover.left{margin-left:-10px}#ex-debug-toolbar .popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}#ex-debug-toolbar .popover-content{padding:9px 14px}#ex-debug-toolbar .popover>.arrow,#ex-debug-toolbar .popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}#ex-debug-toolbar .popover>.arrow{border-width:11px}#ex-debug-toolbar .popover>.arrow:after{border-width:10px;content:""}#ex-debug-toolbar .popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}#ex-debug-toolbar .popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}#ex-debug-toolbar .popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}#ex-debug-toolbar .popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}#ex-debug-toolbar .popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}#ex-debug-toolbar .popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}#ex-debug-toolbar .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)}#ex-debug-toolbar .popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}#ex-debug-toolbar .carousel{position:relative}#ex-debug-toolbar .carousel-inner{position:relative;overflow:hidden;width:100%}#ex-debug-toolbar .carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}#ex-debug-toolbar .carousel-inner>.item>a>img,#ex-debug-toolbar .carousel-inner>.item>img,#ex-debug-toolbar .navbar-nav.nav.carousel-inner>li.item>span>img{display:block;max-width:100%;height:auto;line-height:1}@media all and (transform-3d),(-webkit-transform-3d){#ex-debug-toolbar .carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-moz-transition:-moz-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;-moz-perspective:1000px;perspective:1000px}#ex-debug-toolbar .carousel-inner>.item.active.right,#ex-debug-toolbar .carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}#ex-debug-toolbar .carousel-inner>.item.active.left,#ex-debug-toolbar .carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}#ex-debug-toolbar .carousel-inner>.item.active,#ex-debug-toolbar .carousel-inner>.item.next.left,#ex-debug-toolbar .carousel-inner>.item.prev.right{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);left:0}}#ex-debug-toolbar .carousel-inner>.active,#ex-debug-toolbar .carousel-inner>.next,#ex-debug-toolbar .carousel-inner>.prev{display:block}#ex-debug-toolbar .carousel-inner>.active{left:0}#ex-debug-toolbar .carousel-inner>.next,#ex-debug-toolbar .carousel-inner>.prev{position:absolute;top:0;width:100%}#ex-debug-toolbar .carousel-inner>.next{left:100%}#ex-debug-toolbar .carousel-inner>.prev{left:-100%}#ex-debug-toolbar .carousel-inner>.next.left,#ex-debug-toolbar .carousel-inner>.prev.right{left:0}#ex-debug-toolbar .carousel-inner>.active.left{left:-100%}#ex-debug-toolbar .carousel-inner>.active.right{left:100%}#ex-debug-toolbar .carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:transparent}#ex-debug-toolbar .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:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}#ex-debug-toolbar .carousel-control.right{left:auto;right:0;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:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}#ex-debug-toolbar .carousel-control:focus,#ex-debug-toolbar .carousel-control:hover{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}#ex-debug-toolbar .carousel-control .glyphicon-chevron-left,#ex-debug-toolbar .carousel-control .glyphicon-chevron-right,#ex-debug-toolbar .carousel-control .icon-next,#ex-debug-toolbar .carousel-control .icon-prev{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}#ex-debug-toolbar .carousel-control .glyphicon-chevron-left,#ex-debug-toolbar .carousel-control .icon-prev{left:50%;margin-left:-10px}#ex-debug-toolbar .carousel-control .glyphicon-chevron-right,#ex-debug-toolbar .carousel-control .icon-next{right:50%;margin-right:-10px}#ex-debug-toolbar .carousel-control .icon-next,#ex-debug-toolbar .carousel-control .icon-prev{width:20px;height:20px;line-height:1;font-family:serif}#ex-debug-toolbar .carousel-control .icon-prev:before{content:'\2039'}#ex-debug-toolbar .carousel-control .icon-next:before{content:'\203a'}#ex-debug-toolbar .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}#ex-debug-toolbar .carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000\9;background-color:transparent}#ex-debug-toolbar .carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}#ex-debug-toolbar .carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}#ex-debug-toolbar .carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){#ex-debug-toolbar .carousel-control .glyphicon-chevron-left,#ex-debug-toolbar .carousel-control .glyphicon-chevron-right,#ex-debug-toolbar .carousel-control .icon-next,#ex-debug-toolbar .carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}#ex-debug-toolbar .carousel-control .glyphicon-chevron-left,#ex-debug-toolbar .carousel-control .icon-prev{margin-left:-10px}#ex-debug-toolbar .carousel-control .glyphicon-chevron-right,#ex-debug-toolbar .carousel-control .icon-next{margin-right:-10px}#ex-debug-toolbar .carousel-caption{left:20%;right:20%;padding-bottom:30px}#ex-debug-toolbar .carousel-indicators{bottom:20px}}#ex-debug-toolbar .clearfix:after,#ex-debug-toolbar .clearfix:before{content:" ";display:table}#ex-debug-toolbar .clearfix:after{clear:both}#ex-debug-toolbar .center-block{display:block;margin-left:auto;margin-right:auto}#ex-debug-toolbar .pull-right{float:right!important}#ex-debug-toolbar .pull-left{float:left!important}#ex-debug-toolbar .hide{display:none!important}#ex-debug-toolbar .show{display:block!important}#ex-debug-toolbar .invisible{visibility:hidden}#ex-debug-toolbar .text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}#ex-debug-toolbar .hidden{display:none!important}#ex-debug-toolbar .affix{position:fixed}@-ms-viewport{width:device-width}#ex-debug-toolbar .visible-xs{display:none!important}#ex-debug-toolbar .visible-sm{display:none!important}#ex-debug-toolbar .visible-md{display:none!important}#ex-debug-toolbar .visible-lg{display:none!important}#ex-debug-toolbar .visible-lg-block,#ex-debug-toolbar .visible-lg-inline,#ex-debug-toolbar .visible-lg-inline-block,#ex-debug-toolbar .visible-md-block,#ex-debug-toolbar .visible-md-inline,#ex-debug-toolbar .visible-md-inline-block,#ex-debug-toolbar .visible-sm-block,#ex-debug-toolbar .visible-sm-inline,#ex-debug-toolbar .visible-sm-inline-block,#ex-debug-toolbar .visible-xs-block,#ex-debug-toolbar .visible-xs-inline,#ex-debug-toolbar .visible-xs-inline-block{display:none!important}@media (max-width:767px){#ex-debug-toolbar .visible-xs{display:block!important}#ex-debug-toolbar table.visible-xs{display:table!important}#ex-debug-toolbar tr.visible-xs{display:table-row!important}#ex-debug-toolbar td.visible-xs,#ex-debug-toolbar th.visible-xs{display:table-cell!important}}@media (max-width:767px){#ex-debug-toolbar .visible-xs-block{display:block!important}}@media (max-width:767px){#ex-debug-toolbar .visible-xs-inline{display:inline!important}}@media (max-width:767px){#ex-debug-toolbar .visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){#ex-debug-toolbar .visible-sm{display:block!important}#ex-debug-toolbar table.visible-sm{display:table!important}#ex-debug-toolbar tr.visible-sm{display:table-row!important}#ex-debug-toolbar td.visible-sm,#ex-debug-toolbar th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){#ex-debug-toolbar .visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){#ex-debug-toolbar .visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){#ex-debug-toolbar .visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){#ex-debug-toolbar .visible-md{display:block!important}#ex-debug-toolbar table.visible-md{display:table!important}#ex-debug-toolbar tr.visible-md{display:table-row!important}#ex-debug-toolbar td.visible-md,#ex-debug-toolbar th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){#ex-debug-toolbar .visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){#ex-debug-toolbar .visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){#ex-debug-toolbar .visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){#ex-debug-toolbar .visible-lg{display:block!important}#ex-debug-toolbar table.visible-lg{display:table!important}#ex-debug-toolbar tr.visible-lg{display:table-row!important}#ex-debug-toolbar td.visible-lg,#ex-debug-toolbar th.visible-lg{display:table-cell!important}}@media (min-width:1200px){#ex-debug-toolbar .visible-lg-block{display:block!important}}@media (min-width:1200px){#ex-debug-toolbar .visible-lg-inline{display:inline!important}}@media (min-width:1200px){#ex-debug-toolbar .visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){#ex-debug-toolbar .hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){#ex-debug-toolbar .hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){#ex-debug-toolbar .hidden-md{display:none!important}}@media (min-width:1200px){#ex-debug-toolbar .hidden-lg{display:none!important}}#ex-debug-toolbar .visible-print{display:none!important}@media print{#ex-debug-toolbar .visible-print{display:block!important}#ex-debug-toolbar table.visible-print{display:table!important}#ex-debug-toolbar tr.visible-print{display:table-row!important}#ex-debug-toolbar td.visible-print,#ex-debug-toolbar th.visible-print{display:table-cell!important}}#ex-debug-toolbar .visible-print-block{display:none!important}@media print{#ex-debug-toolbar .visible-print-block{display:block!important}}#ex-debug-toolbar .visible-print-inline{display:none!important}@media print{#ex-debug-toolbar .visible-print-inline{display:inline!important}}#ex-debug-toolbar .visible-print-inline-block{display:none!important}@media print{#ex-debug-toolbar .visible-print-inline-block{display:inline-block!important}}@media print{#ex-debug-toolbar .hidden-print{display:none!important}}#ex-debug-toolbar code[class*=language-],#ex-debug-toolbar pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}#ex-debug-toolbar code[class*=language-] ::-moz-selection,#ex-debug-toolbar code[class*=language-]::-moz-selection,#ex-debug-toolbar pre[class*=language-] ::-moz-selection,#ex-debug-toolbar pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}#ex-debug-toolbar code[class*=language-] ::selection,#ex-debug-toolbar code[class*=language-]::selection,#ex-debug-toolbar pre[class*=language-] ::selection,#ex-debug-toolbar pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{#ex-debug-toolbar code[class*=language-],#ex-debug-toolbar pre[class*=language-]{text-shadow:none}}#ex-debug-toolbar pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}#ex-debug-toolbar :not(pre)>code[class*=language-],#ex-debug-toolbar pre[class*=language-]{background:#f5f2f0}#ex-debug-toolbar :not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}#ex-debug-toolbar .token.cdata,#ex-debug-toolbar .token.comment,#ex-debug-toolbar .token.doctype,#ex-debug-toolbar .token.prolog{color:#708090}#ex-debug-toolbar .token.punctuation{color:#999}#ex-debug-toolbar .namespace{opacity:.7}#ex-debug-toolbar .token.boolean,#ex-debug-toolbar .token.constant,#ex-debug-toolbar .token.deleted,#ex-debug-toolbar .token.number,#ex-debug-toolbar .token.property,#ex-debug-toolbar .token.symbol,#ex-debug-toolbar .token.tag{color:#905}#ex-debug-toolbar .token.attr-name,#ex-debug-toolbar .token.builtin,#ex-debug-toolbar .token.char,#ex-debug-toolbar .token.inserted,#ex-debug-toolbar .token.selector,#ex-debug-toolbar .token.string{color:#690}#ex-debug-toolbar .language-css .token.string,#ex-debug-toolbar .style .token.string,#ex-debug-toolbar .token.entity,#ex-debug-toolbar .token.operator,#ex-debug-toolbar .token.url{color:#a67f59;background:rgba(255,255,255,.5)}#ex-debug-toolbar .token.atrule,#ex-debug-toolbar .token.attr-value,#ex-debug-toolbar .token.keyword{color:#07a}#ex-debug-toolbar .token.function{color:#DD4A68}#ex-debug-toolbar .token.important,#ex-debug-toolbar .token.regex,#ex-debug-toolbar .token.variable{color:#e90}#ex-debug-toolbar .token.bold,#ex-debug-toolbar .token.important{font-weight:700}#ex-debug-toolbar .token.italic{font-style:italic}#ex-debug-toolbar .token.entity{cursor:help}#ex-debug-toolbar pre.line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}#ex-debug-toolbar pre.line-numbers>code{position:relative}#ex-debug-toolbar .line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}#ex-debug-toolbar .line-numbers-rows>span{pointer-events:none;display:block;counter-increment:linenumber}#ex-debug-toolbar .line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}#ex-debug-toolbar pre[data-line]{position:relative;padding:1em 0 1em 3em}#ex-debug-toolbar .line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:rgba(153,122,102,.08);background:linear-gradient(to right,rgba(153,122,102,.1) 70%,rgba(153,122,102,0));pointer-events:none;line-height:inherit;white-space:pre}#ex-debug-toolbar .line-highlight:before,#ex-debug-toolbar .line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:rgba(153,122,102,.4);color:#f5f2f0;font:700 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}#ex-debug-toolbar .line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}#ex-debug-toolbar .terminal{background-color:#000;color:#fff;font-family:courier-new,courier,monospace;font-feature-settings:"liga" 0;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}#ex-debug-toolbar .terminal.focus,#ex-debug-toolbar .terminal:focus{outline:0}#ex-debug-toolbar .terminal .xterm-helpers{position:absolute;top:0}#ex-debug-toolbar .terminal .xterm-helper-textarea{position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-10;white-space:nowrap;overflow:hidden;resize:none}#ex-debug-toolbar .terminal .navbar-nav.nav>li>span,#ex-debug-toolbar .terminal a{color:inherit;text-decoration:none}#ex-debug-toolbar .terminal .navbar-nav.nav>li>span:hover,#ex-debug-toolbar .terminal a:hover{cursor:pointer;text-decoration:underline}#ex-debug-toolbar .terminal .navbar-nav.nav>li>span.xterm-invalid-link:hover,#ex-debug-toolbar .terminal a.xterm-invalid-link:hover{cursor:text;text-decoration:none}#ex-debug-toolbar .terminal.focus:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor{background-color:#fff;color:#000}#ex-debug-toolbar .terminal:not(.focus) .terminal-cursor{outline:1px solid #fff;outline-offset:-1px;background-color:transparent}#ex-debug-toolbar .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink-on .terminal-cursor{background-color:transparent;color:inherit}#ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor,#ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor{position:relative}#ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor::before,#ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor::before{content:"";display:block;position:absolute;background-color:#fff}#ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor::before{top:0;bottom:0;left:0;width:1px}#ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor::before{bottom:0;left:0;right:0;height:1px}#ex-debug-toolbar .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before,#ex-debug-toolbar .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before{background-color:transparent}#ex-debug-toolbar .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,#ex-debug-toolbar .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before{background-color:#fff}#ex-debug-toolbar .terminal .composition-view{background:#000;color:#FFF;display:none;position:absolute;white-space:nowrap;z-index:1}#ex-debug-toolbar .terminal .composition-view.active{display:block}#ex-debug-toolbar .terminal .xterm-viewport{background-color:#000;overflow-y:scroll}#ex-debug-toolbar .terminal .xterm-normal-char,#ex-debug-toolbar .terminal .xterm-wide-char{display:inline-block}#ex-debug-toolbar .terminal .xterm-rows{position:absolute;left:0;top:0}#ex-debug-toolbar .terminal .xterm-rows>div{white-space:nowrap}#ex-debug-toolbar .terminal .xterm-scroll-area{visibility:hidden}#ex-debug-toolbar .terminal .xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;left:-9999em}#ex-debug-toolbar .terminal.enable-mouse-events{cursor:default}#ex-debug-toolbar .terminal .xterm-selection{position:absolute;top:0;left:0;z-index:1;opacity:.3;pointer-events:none}#ex-debug-toolbar .terminal .xterm-selection div{position:absolute;background-color:#fff}#ex-debug-toolbar .terminal .xterm-bold{font-weight:700}#ex-debug-toolbar .terminal .xterm-underline{text-decoration:underline}#ex-debug-toolbar .terminal .xterm-blink{text-decoration:blink}#ex-debug-toolbar .terminal .xterm-hidden{visibility:hidden}#ex-debug-toolbar .terminal .xterm-color-0{color:#2e3436}#ex-debug-toolbar .terminal .xterm-bg-color-0{background-color:#2e3436}#ex-debug-toolbar .terminal .xterm-color-1{color:#c00}#ex-debug-toolbar .terminal .xterm-bg-color-1{background-color:#c00}#ex-debug-toolbar .terminal .xterm-color-2{color:#4e9a06}#ex-debug-toolbar .terminal .xterm-bg-color-2{background-color:#4e9a06}#ex-debug-toolbar .terminal .xterm-color-3{color:#c4a000}#ex-debug-toolbar .terminal .xterm-bg-color-3{background-color:#c4a000}#ex-debug-toolbar .terminal .xterm-color-4{color:#3465a4}#ex-debug-toolbar .terminal .xterm-bg-color-4{background-color:#3465a4}#ex-debug-toolbar .terminal .xterm-color-5{color:#75507b}#ex-debug-toolbar .terminal .xterm-bg-color-5{background-color:#75507b}#ex-debug-toolbar .terminal .xterm-color-6{color:#06989a}#ex-debug-toolbar .terminal .xterm-bg-color-6{background-color:#06989a}#ex-debug-toolbar .terminal .xterm-color-7{color:#d3d7cf}#ex-debug-toolbar .terminal .xterm-bg-color-7{background-color:#d3d7cf}#ex-debug-toolbar .terminal .xterm-color-8{color:#555753}#ex-debug-toolbar .terminal .xterm-bg-color-8{background-color:#555753}#ex-debug-toolbar .terminal .xterm-color-9{color:#ef2929}#ex-debug-toolbar .terminal .xterm-bg-color-9{background-color:#ef2929}#ex-debug-toolbar .terminal .xterm-color-10{color:#8ae234}#ex-debug-toolbar .terminal .xterm-bg-color-10{background-color:#8ae234}#ex-debug-toolbar .terminal .xterm-color-11{color:#fce94f}#ex-debug-toolbar .terminal .xterm-bg-color-11{background-color:#fce94f}#ex-debug-toolbar .terminal .xterm-color-12{color:#729fcf}#ex-debug-toolbar .terminal .xterm-bg-color-12{background-color:#729fcf}#ex-debug-toolbar .terminal .xterm-color-13{color:#ad7fa8}#ex-debug-toolbar .terminal .xterm-bg-color-13{background-color:#ad7fa8}#ex-debug-toolbar .terminal .xterm-color-14{color:#34e2e2}#ex-debug-toolbar .terminal .xterm-bg-color-14{background-color:#34e2e2}#ex-debug-toolbar .terminal .xterm-color-15{color:#eeeeec}#ex-debug-toolbar .terminal .xterm-bg-color-15{background-color:#eeeeec}#ex-debug-toolbar .terminal .xterm-color-16{color:#000}#ex-debug-toolbar .terminal .xterm-bg-color-16{background-color:#000}#ex-debug-toolbar .terminal .xterm-color-17{color:#00005f}#ex-debug-toolbar .terminal .xterm-bg-color-17{background-color:#00005f}#ex-debug-toolbar .terminal .xterm-color-18{color:#000087}#ex-debug-toolbar .terminal .xterm-bg-color-18{background-color:#000087}#ex-debug-toolbar .terminal .xterm-color-19{color:#0000af}#ex-debug-toolbar .terminal .xterm-bg-color-19{background-color:#0000af}#ex-debug-toolbar .terminal .xterm-color-20{color:#0000d7}#ex-debug-toolbar .terminal .xterm-bg-color-20{background-color:#0000d7}#ex-debug-toolbar .terminal .xterm-color-21{color:#00f}#ex-debug-toolbar .terminal .xterm-bg-color-21{background-color:#00f}#ex-debug-toolbar .terminal .xterm-color-22{color:#005f00}#ex-debug-toolbar .terminal .xterm-bg-color-22{background-color:#005f00}#ex-debug-toolbar .terminal .xterm-color-23{color:#005f5f}#ex-debug-toolbar .terminal .xterm-bg-color-23{background-color:#005f5f}#ex-debug-toolbar .terminal .xterm-color-24{color:#005f87}#ex-debug-toolbar .terminal .xterm-bg-color-24{background-color:#005f87}#ex-debug-toolbar .terminal .xterm-color-25{color:#005faf}#ex-debug-toolbar .terminal .xterm-bg-color-25{background-color:#005faf}#ex-debug-toolbar .terminal .xterm-color-26{color:#005fd7}#ex-debug-toolbar .terminal .xterm-bg-color-26{background-color:#005fd7}#ex-debug-toolbar .terminal .xterm-color-27{color:#005fff}#ex-debug-toolbar .terminal .xterm-bg-color-27{background-color:#005fff}#ex-debug-toolbar .terminal .xterm-color-28{color:#008700}#ex-debug-toolbar .terminal .xterm-bg-color-28{background-color:#008700}#ex-debug-toolbar .terminal .xterm-color-29{color:#00875f}#ex-debug-toolbar .terminal .xterm-bg-color-29{background-color:#00875f}#ex-debug-toolbar .terminal .xterm-color-30{color:#008787}#ex-debug-toolbar .terminal .xterm-bg-color-30{background-color:#008787}#ex-debug-toolbar .terminal .xterm-color-31{color:#0087af}#ex-debug-toolbar .terminal .xterm-bg-color-31{background-color:#0087af}#ex-debug-toolbar .terminal .xterm-color-32{color:#0087d7}#ex-debug-toolbar .terminal .xterm-bg-color-32{background-color:#0087d7}#ex-debug-toolbar .terminal .xterm-color-33{color:#0087ff}#ex-debug-toolbar .terminal .xterm-bg-color-33{background-color:#0087ff}#ex-debug-toolbar .terminal .xterm-color-34{color:#00af00}#ex-debug-toolbar .terminal .xterm-bg-color-34{background-color:#00af00}#ex-debug-toolbar .terminal .xterm-color-35{color:#00af5f}#ex-debug-toolbar .terminal .xterm-bg-color-35{background-color:#00af5f}#ex-debug-toolbar .terminal .xterm-color-36{color:#00af87}#ex-debug-toolbar .terminal .xterm-bg-color-36{background-color:#00af87}#ex-debug-toolbar .terminal .xterm-color-37{color:#00afaf}#ex-debug-toolbar .terminal .xterm-bg-color-37{background-color:#00afaf}#ex-debug-toolbar .terminal .xterm-color-38{color:#00afd7}#ex-debug-toolbar .terminal .xterm-bg-color-38{background-color:#00afd7}#ex-debug-toolbar .terminal .xterm-color-39{color:#00afff}#ex-debug-toolbar .terminal .xterm-bg-color-39{background-color:#00afff}#ex-debug-toolbar .terminal .xterm-color-40{color:#00d700}#ex-debug-toolbar .terminal .xterm-bg-color-40{background-color:#00d700}#ex-debug-toolbar .terminal .xterm-color-41{color:#00d75f}#ex-debug-toolbar .terminal .xterm-bg-color-41{background-color:#00d75f}#ex-debug-toolbar .terminal .xterm-color-42{color:#00d787}#ex-debug-toolbar .terminal .xterm-bg-color-42{background-color:#00d787}#ex-debug-toolbar .terminal .xterm-color-43{color:#00d7af}#ex-debug-toolbar .terminal .xterm-bg-color-43{background-color:#00d7af}#ex-debug-toolbar .terminal .xterm-color-44{color:#00d7d7}#ex-debug-toolbar .terminal .xterm-bg-color-44{background-color:#00d7d7}#ex-debug-toolbar .terminal .xterm-color-45{color:#00d7ff}#ex-debug-toolbar .terminal .xterm-bg-color-45{background-color:#00d7ff}#ex-debug-toolbar .terminal .xterm-color-46{color:#0f0}#ex-debug-toolbar .terminal .xterm-bg-color-46{background-color:#0f0}#ex-debug-toolbar .terminal .xterm-color-47{color:#00ff5f}#ex-debug-toolbar .terminal .xterm-bg-color-47{background-color:#00ff5f}#ex-debug-toolbar .terminal .xterm-color-48{color:#00ff87}#ex-debug-toolbar .terminal .xterm-bg-color-48{background-color:#00ff87}#ex-debug-toolbar .terminal .xterm-color-49{color:#00ffaf}#ex-debug-toolbar .terminal .xterm-bg-color-49{background-color:#00ffaf}#ex-debug-toolbar .terminal .xterm-color-50{color:#00ffd7}#ex-debug-toolbar .terminal .xterm-bg-color-50{background-color:#00ffd7}#ex-debug-toolbar .terminal .xterm-color-51{color:#0ff}#ex-debug-toolbar .terminal .xterm-bg-color-51{background-color:#0ff}#ex-debug-toolbar .terminal .xterm-color-52{color:#5f0000}#ex-debug-toolbar .terminal .xterm-bg-color-52{background-color:#5f0000}#ex-debug-toolbar .terminal .xterm-color-53{color:#5f005f}#ex-debug-toolbar .terminal .xterm-bg-color-53{background-color:#5f005f}#ex-debug-toolbar .terminal .xterm-color-54{color:#5f0087}#ex-debug-toolbar .terminal .xterm-bg-color-54{background-color:#5f0087}#ex-debug-toolbar .terminal .xterm-color-55{color:#5f00af}#ex-debug-toolbar .terminal .xterm-bg-color-55{background-color:#5f00af}#ex-debug-toolbar .terminal .xterm-color-56{color:#5f00d7}#ex-debug-toolbar .terminal .xterm-bg-color-56{background-color:#5f00d7}#ex-debug-toolbar .terminal .xterm-color-57{color:#5f00ff}#ex-debug-toolbar .terminal .xterm-bg-color-57{background-color:#5f00ff}#ex-debug-toolbar .terminal .xterm-color-58{color:#5f5f00}#ex-debug-toolbar .terminal .xterm-bg-color-58{background-color:#5f5f00}#ex-debug-toolbar .terminal .xterm-color-59{color:#5f5f5f}#ex-debug-toolbar .terminal .xterm-bg-color-59{background-color:#5f5f5f}#ex-debug-toolbar .terminal .xterm-color-60{color:#5f5f87}#ex-debug-toolbar .terminal .xterm-bg-color-60{background-color:#5f5f87}#ex-debug-toolbar .terminal .xterm-color-61{color:#5f5faf}#ex-debug-toolbar .terminal .xterm-bg-color-61{background-color:#5f5faf}#ex-debug-toolbar .terminal .xterm-color-62{color:#5f5fd7}#ex-debug-toolbar .terminal .xterm-bg-color-62{background-color:#5f5fd7}#ex-debug-toolbar .terminal .xterm-color-63{color:#5f5fff}#ex-debug-toolbar .terminal .xterm-bg-color-63{background-color:#5f5fff}#ex-debug-toolbar .terminal .xterm-color-64{color:#5f8700}#ex-debug-toolbar .terminal .xterm-bg-color-64{background-color:#5f8700}#ex-debug-toolbar .terminal .xterm-color-65{color:#5f875f}#ex-debug-toolbar .terminal .xterm-bg-color-65{background-color:#5f875f}#ex-debug-toolbar .terminal .xterm-color-66{color:#5f8787}#ex-debug-toolbar .terminal .xterm-bg-color-66{background-color:#5f8787}#ex-debug-toolbar .terminal .xterm-color-67{color:#5f87af}#ex-debug-toolbar .terminal .xterm-bg-color-67{background-color:#5f87af}#ex-debug-toolbar .terminal .xterm-color-68{color:#5f87d7}#ex-debug-toolbar .terminal .xterm-bg-color-68{background-color:#5f87d7}#ex-debug-toolbar .terminal .xterm-color-69{color:#5f87ff}#ex-debug-toolbar .terminal .xterm-bg-color-69{background-color:#5f87ff}#ex-debug-toolbar .terminal .xterm-color-70{color:#5faf00}#ex-debug-toolbar .terminal .xterm-bg-color-70{background-color:#5faf00}#ex-debug-toolbar .terminal .xterm-color-71{color:#5faf5f}#ex-debug-toolbar .terminal .xterm-bg-color-71{background-color:#5faf5f}#ex-debug-toolbar .terminal .xterm-color-72{color:#5faf87}#ex-debug-toolbar .terminal .xterm-bg-color-72{background-color:#5faf87}#ex-debug-toolbar .terminal .xterm-color-73{color:#5fafaf}#ex-debug-toolbar .terminal .xterm-bg-color-73{background-color:#5fafaf}#ex-debug-toolbar .terminal .xterm-color-74{color:#5fafd7}#ex-debug-toolbar .terminal .xterm-bg-color-74{background-color:#5fafd7}#ex-debug-toolbar .terminal .xterm-color-75{color:#5fafff}#ex-debug-toolbar .terminal .xterm-bg-color-75{background-color:#5fafff}#ex-debug-toolbar .terminal .xterm-color-76{color:#5fd700}#ex-debug-toolbar .terminal .xterm-bg-color-76{background-color:#5fd700}#ex-debug-toolbar .terminal .xterm-color-77{color:#5fd75f}#ex-debug-toolbar .terminal .xterm-bg-color-77{background-color:#5fd75f}#ex-debug-toolbar .terminal .xterm-color-78{color:#5fd787}#ex-debug-toolbar .terminal .xterm-bg-color-78{background-color:#5fd787}#ex-debug-toolbar .terminal .xterm-color-79{color:#5fd7af}#ex-debug-toolbar .terminal .xterm-bg-color-79{background-color:#5fd7af}#ex-debug-toolbar .terminal .xterm-color-80{color:#5fd7d7}#ex-debug-toolbar .terminal .xterm-bg-color-80{background-color:#5fd7d7}#ex-debug-toolbar .terminal .xterm-color-81{color:#5fd7ff}#ex-debug-toolbar .terminal .xterm-bg-color-81{background-color:#5fd7ff}#ex-debug-toolbar .terminal .xterm-color-82{color:#5fff00}#ex-debug-toolbar .terminal .xterm-bg-color-82{background-color:#5fff00}#ex-debug-toolbar .terminal .xterm-color-83{color:#5fff5f}#ex-debug-toolbar .terminal .xterm-bg-color-83{background-color:#5fff5f}#ex-debug-toolbar .terminal .xterm-color-84{color:#5fff87}#ex-debug-toolbar .terminal .xterm-bg-color-84{background-color:#5fff87}#ex-debug-toolbar .terminal .xterm-color-85{color:#5fffaf}#ex-debug-toolbar .terminal .xterm-bg-color-85{background-color:#5fffaf}#ex-debug-toolbar .terminal .xterm-color-86{color:#5fffd7}#ex-debug-toolbar .terminal .xterm-bg-color-86{background-color:#5fffd7}#ex-debug-toolbar .terminal .xterm-color-87{color:#5fffff}#ex-debug-toolbar .terminal .xterm-bg-color-87{background-color:#5fffff}#ex-debug-toolbar .terminal .xterm-color-88{color:#870000}#ex-debug-toolbar .terminal .xterm-bg-color-88{background-color:#870000}#ex-debug-toolbar .terminal .xterm-color-89{color:#87005f}#ex-debug-toolbar .terminal .xterm-bg-color-89{background-color:#87005f}#ex-debug-toolbar .terminal .xterm-color-90{color:#870087}#ex-debug-toolbar .terminal .xterm-bg-color-90{background-color:#870087}#ex-debug-toolbar .terminal .xterm-color-91{color:#8700af}#ex-debug-toolbar .terminal .xterm-bg-color-91{background-color:#8700af}#ex-debug-toolbar .terminal .xterm-color-92{color:#8700d7}#ex-debug-toolbar .terminal .xterm-bg-color-92{background-color:#8700d7}#ex-debug-toolbar .terminal .xterm-color-93{color:#8700ff}#ex-debug-toolbar .terminal .xterm-bg-color-93{background-color:#8700ff}#ex-debug-toolbar .terminal .xterm-color-94{color:#875f00}#ex-debug-toolbar .terminal .xterm-bg-color-94{background-color:#875f00}#ex-debug-toolbar .terminal .xterm-color-95{color:#875f5f}#ex-debug-toolbar .terminal .xterm-bg-color-95{background-color:#875f5f}#ex-debug-toolbar .terminal .xterm-color-96{color:#875f87}#ex-debug-toolbar .terminal .xterm-bg-color-96{background-color:#875f87}#ex-debug-toolbar .terminal .xterm-color-97{color:#875faf}#ex-debug-toolbar .terminal .xterm-bg-color-97{background-color:#875faf}#ex-debug-toolbar .terminal .xterm-color-98{color:#875fd7}#ex-debug-toolbar .terminal .xterm-bg-color-98{background-color:#875fd7}#ex-debug-toolbar .terminal .xterm-color-99{color:#875fff}#ex-debug-toolbar .terminal .xterm-bg-color-99{background-color:#875fff}#ex-debug-toolbar .terminal .xterm-color-100{color:#878700}#ex-debug-toolbar .terminal .xterm-bg-color-100{background-color:#878700}#ex-debug-toolbar .terminal .xterm-color-101{color:#87875f}#ex-debug-toolbar .terminal .xterm-bg-color-101{background-color:#87875f}#ex-debug-toolbar .terminal .xterm-color-102{color:#878787}#ex-debug-toolbar .terminal .xterm-bg-color-102{background-color:#878787}#ex-debug-toolbar .terminal .xterm-color-103{color:#8787af}#ex-debug-toolbar .terminal .xterm-bg-color-103{background-color:#8787af}#ex-debug-toolbar .terminal .xterm-color-104{color:#8787d7}#ex-debug-toolbar .terminal .xterm-bg-color-104{background-color:#8787d7}#ex-debug-toolbar .terminal .xterm-color-105{color:#8787ff}#ex-debug-toolbar .terminal .xterm-bg-color-105{background-color:#8787ff}#ex-debug-toolbar .terminal .xterm-color-106{color:#87af00}#ex-debug-toolbar .terminal .xterm-bg-color-106{background-color:#87af00}#ex-debug-toolbar .terminal .xterm-color-107{color:#87af5f}#ex-debug-toolbar .terminal .xterm-bg-color-107{background-color:#87af5f}#ex-debug-toolbar .terminal .xterm-color-108{color:#87af87}#ex-debug-toolbar .terminal .xterm-bg-color-108{background-color:#87af87}#ex-debug-toolbar .terminal .xterm-color-109{color:#87afaf}#ex-debug-toolbar .terminal .xterm-bg-color-109{background-color:#87afaf}#ex-debug-toolbar .terminal .xterm-color-110{color:#87afd7}#ex-debug-toolbar .terminal .xterm-bg-color-110{background-color:#87afd7}#ex-debug-toolbar .terminal .xterm-color-111{color:#87afff}#ex-debug-toolbar .terminal .xterm-bg-color-111{background-color:#87afff}#ex-debug-toolbar .terminal .xterm-color-112{color:#87d700}#ex-debug-toolbar .terminal .xterm-bg-color-112{background-color:#87d700}#ex-debug-toolbar .terminal .xterm-color-113{color:#87d75f}#ex-debug-toolbar .terminal .xterm-bg-color-113{background-color:#87d75f}#ex-debug-toolbar .terminal .xterm-color-114{color:#87d787}#ex-debug-toolbar .terminal .xterm-bg-color-114{background-color:#87d787}#ex-debug-toolbar .terminal .xterm-color-115{color:#87d7af}#ex-debug-toolbar .terminal .xterm-bg-color-115{background-color:#87d7af}#ex-debug-toolbar .terminal .xterm-color-116{color:#87d7d7}#ex-debug-toolbar .terminal .xterm-bg-color-116{background-color:#87d7d7}#ex-debug-toolbar .terminal .xterm-color-117{color:#87d7ff}#ex-debug-toolbar .terminal .xterm-bg-color-117{background-color:#87d7ff}#ex-debug-toolbar .terminal .xterm-color-118{color:#87ff00}#ex-debug-toolbar .terminal .xterm-bg-color-118{background-color:#87ff00}#ex-debug-toolbar .terminal .xterm-color-119{color:#87ff5f}#ex-debug-toolbar .terminal .xterm-bg-color-119{background-color:#87ff5f}#ex-debug-toolbar .terminal .xterm-color-120{color:#87ff87}#ex-debug-toolbar .terminal .xterm-bg-color-120{background-color:#87ff87}#ex-debug-toolbar .terminal .xterm-color-121{color:#87ffaf}#ex-debug-toolbar .terminal .xterm-bg-color-121{background-color:#87ffaf}#ex-debug-toolbar .terminal .xterm-color-122{color:#87ffd7}#ex-debug-toolbar .terminal .xterm-bg-color-122{background-color:#87ffd7}#ex-debug-toolbar .terminal .xterm-color-123{color:#87ffff}#ex-debug-toolbar .terminal .xterm-bg-color-123{background-color:#87ffff}#ex-debug-toolbar .terminal .xterm-color-124{color:#af0000}#ex-debug-toolbar .terminal .xterm-bg-color-124{background-color:#af0000}#ex-debug-toolbar .terminal .xterm-color-125{color:#af005f}#ex-debug-toolbar .terminal .xterm-bg-color-125{background-color:#af005f}#ex-debug-toolbar .terminal .xterm-color-126{color:#af0087}#ex-debug-toolbar .terminal .xterm-bg-color-126{background-color:#af0087}#ex-debug-toolbar .terminal .xterm-color-127{color:#af00af}#ex-debug-toolbar .terminal .xterm-bg-color-127{background-color:#af00af}#ex-debug-toolbar .terminal .xterm-color-128{color:#af00d7}#ex-debug-toolbar .terminal .xterm-bg-color-128{background-color:#af00d7}#ex-debug-toolbar .terminal .xterm-color-129{color:#af00ff}#ex-debug-toolbar .terminal .xterm-bg-color-129{background-color:#af00ff}#ex-debug-toolbar .terminal .xterm-color-130{color:#af5f00}#ex-debug-toolbar .terminal .xterm-bg-color-130{background-color:#af5f00}#ex-debug-toolbar .terminal .xterm-color-131{color:#af5f5f}#ex-debug-toolbar .terminal .xterm-bg-color-131{background-color:#af5f5f}#ex-debug-toolbar .terminal .xterm-color-132{color:#af5f87}#ex-debug-toolbar .terminal .xterm-bg-color-132{background-color:#af5f87}#ex-debug-toolbar .terminal .xterm-color-133{color:#af5faf}#ex-debug-toolbar .terminal .xterm-bg-color-133{background-color:#af5faf}#ex-debug-toolbar .terminal .xterm-color-134{color:#af5fd7}#ex-debug-toolbar .terminal .xterm-bg-color-134{background-color:#af5fd7}#ex-debug-toolbar .terminal .xterm-color-135{color:#af5fff}#ex-debug-toolbar .terminal .xterm-bg-color-135{background-color:#af5fff}#ex-debug-toolbar .terminal .xterm-color-136{color:#af8700}#ex-debug-toolbar .terminal .xterm-bg-color-136{background-color:#af8700}#ex-debug-toolbar .terminal .xterm-color-137{color:#af875f}#ex-debug-toolbar .terminal .xterm-bg-color-137{background-color:#af875f}#ex-debug-toolbar .terminal .xterm-color-138{color:#af8787}#ex-debug-toolbar .terminal .xterm-bg-color-138{background-color:#af8787}#ex-debug-toolbar .terminal .xterm-color-139{color:#af87af}#ex-debug-toolbar .terminal .xterm-bg-color-139{background-color:#af87af}#ex-debug-toolbar .terminal .xterm-color-140{color:#af87d7}#ex-debug-toolbar .terminal .xterm-bg-color-140{background-color:#af87d7}#ex-debug-toolbar .terminal .xterm-color-141{color:#af87ff}#ex-debug-toolbar .terminal .xterm-bg-color-141{background-color:#af87ff}#ex-debug-toolbar .terminal .xterm-color-142{color:#afaf00}#ex-debug-toolbar .terminal .xterm-bg-color-142{background-color:#afaf00}#ex-debug-toolbar .terminal .xterm-color-143{color:#afaf5f}#ex-debug-toolbar .terminal .xterm-bg-color-143{background-color:#afaf5f}#ex-debug-toolbar .terminal .xterm-color-144{color:#afaf87}#ex-debug-toolbar .terminal .xterm-bg-color-144{background-color:#afaf87}#ex-debug-toolbar .terminal .xterm-color-145{color:#afafaf}#ex-debug-toolbar .terminal .xterm-bg-color-145{background-color:#afafaf}#ex-debug-toolbar .terminal .xterm-color-146{color:#afafd7}#ex-debug-toolbar .terminal .xterm-bg-color-146{background-color:#afafd7}#ex-debug-toolbar .terminal .xterm-color-147{color:#afafff}#ex-debug-toolbar .terminal .xterm-bg-color-147{background-color:#afafff}#ex-debug-toolbar .terminal .xterm-color-148{color:#afd700}#ex-debug-toolbar .terminal .xterm-bg-color-148{background-color:#afd700}#ex-debug-toolbar .terminal .xterm-color-149{color:#afd75f}#ex-debug-toolbar .terminal .xterm-bg-color-149{background-color:#afd75f}#ex-debug-toolbar .terminal .xterm-color-150{color:#afd787}#ex-debug-toolbar .terminal .xterm-bg-color-150{background-color:#afd787}#ex-debug-toolbar .terminal .xterm-color-151{color:#afd7af}#ex-debug-toolbar .terminal .xterm-bg-color-151{background-color:#afd7af}#ex-debug-toolbar .terminal .xterm-color-152{color:#afd7d7}#ex-debug-toolbar .terminal .xterm-bg-color-152{background-color:#afd7d7}#ex-debug-toolbar .terminal .xterm-color-153{color:#afd7ff}#ex-debug-toolbar .terminal .xterm-bg-color-153{background-color:#afd7ff}#ex-debug-toolbar .terminal .xterm-color-154{color:#afff00}#ex-debug-toolbar .terminal .xterm-bg-color-154{background-color:#afff00}#ex-debug-toolbar .terminal .xterm-color-155{color:#afff5f}#ex-debug-toolbar .terminal .xterm-bg-color-155{background-color:#afff5f}#ex-debug-toolbar .terminal .xterm-color-156{color:#afff87}#ex-debug-toolbar .terminal .xterm-bg-color-156{background-color:#afff87}#ex-debug-toolbar .terminal .xterm-color-157{color:#afffaf}#ex-debug-toolbar .terminal .xterm-bg-color-157{background-color:#afffaf}#ex-debug-toolbar .terminal .xterm-color-158{color:#afffd7}#ex-debug-toolbar .terminal .xterm-bg-color-158{background-color:#afffd7}#ex-debug-toolbar .terminal .xterm-color-159{color:#afffff}#ex-debug-toolbar .terminal .xterm-bg-color-159{background-color:#afffff}#ex-debug-toolbar .terminal .xterm-color-160{color:#d70000}#ex-debug-toolbar .terminal .xterm-bg-color-160{background-color:#d70000}#ex-debug-toolbar .terminal .xterm-color-161{color:#d7005f}#ex-debug-toolbar .terminal .xterm-bg-color-161{background-color:#d7005f}#ex-debug-toolbar .terminal .xterm-color-162{color:#d70087}#ex-debug-toolbar .terminal .xterm-bg-color-162{background-color:#d70087}#ex-debug-toolbar .terminal .xterm-color-163{color:#d700af}#ex-debug-toolbar .terminal .xterm-bg-color-163{background-color:#d700af}#ex-debug-toolbar .terminal .xterm-color-164{color:#d700d7}#ex-debug-toolbar .terminal .xterm-bg-color-164{background-color:#d700d7}#ex-debug-toolbar .terminal .xterm-color-165{color:#d700ff}#ex-debug-toolbar .terminal .xterm-bg-color-165{background-color:#d700ff}#ex-debug-toolbar .terminal .xterm-color-166{color:#d75f00}#ex-debug-toolbar .terminal .xterm-bg-color-166{background-color:#d75f00}#ex-debug-toolbar .terminal .xterm-color-167{color:#d75f5f}#ex-debug-toolbar .terminal .xterm-bg-color-167{background-color:#d75f5f}#ex-debug-toolbar .terminal .xterm-color-168{color:#d75f87}#ex-debug-toolbar .terminal .xterm-bg-color-168{background-color:#d75f87}#ex-debug-toolbar .terminal .xterm-color-169{color:#d75faf}#ex-debug-toolbar .terminal .xterm-bg-color-169{background-color:#d75faf}#ex-debug-toolbar .terminal .xterm-color-170{color:#d75fd7}#ex-debug-toolbar .terminal .xterm-bg-color-170{background-color:#d75fd7}#ex-debug-toolbar .terminal .xterm-color-171{color:#d75fff}#ex-debug-toolbar .terminal .xterm-bg-color-171{background-color:#d75fff}#ex-debug-toolbar .terminal .xterm-color-172{color:#d78700}#ex-debug-toolbar .terminal .xterm-bg-color-172{background-color:#d78700}#ex-debug-toolbar .terminal .xterm-color-173{color:#d7875f}#ex-debug-toolbar .terminal .xterm-bg-color-173{background-color:#d7875f}#ex-debug-toolbar .terminal .xterm-color-174{color:#d78787}#ex-debug-toolbar .terminal .xterm-bg-color-174{background-color:#d78787}#ex-debug-toolbar .terminal .xterm-color-175{color:#d787af}#ex-debug-toolbar .terminal .xterm-bg-color-175{background-color:#d787af}#ex-debug-toolbar .terminal .xterm-color-176{color:#d787d7}#ex-debug-toolbar .terminal .xterm-bg-color-176{background-color:#d787d7}#ex-debug-toolbar .terminal .xterm-color-177{color:#d787ff}#ex-debug-toolbar .terminal .xterm-bg-color-177{background-color:#d787ff}#ex-debug-toolbar .terminal .xterm-color-178{color:#d7af00}#ex-debug-toolbar .terminal .xterm-bg-color-178{background-color:#d7af00}#ex-debug-toolbar .terminal .xterm-color-179{color:#d7af5f}#ex-debug-toolbar .terminal .xterm-bg-color-179{background-color:#d7af5f}#ex-debug-toolbar .terminal .xterm-color-180{color:#d7af87}#ex-debug-toolbar .terminal .xterm-bg-color-180{background-color:#d7af87}#ex-debug-toolbar .terminal .xterm-color-181{color:#d7afaf}#ex-debug-toolbar .terminal .xterm-bg-color-181{background-color:#d7afaf}#ex-debug-toolbar .terminal .xterm-color-182{color:#d7afd7}#ex-debug-toolbar .terminal .xterm-bg-color-182{background-color:#d7afd7}#ex-debug-toolbar .terminal .xterm-color-183{color:#d7afff}#ex-debug-toolbar .terminal .xterm-bg-color-183{background-color:#d7afff}#ex-debug-toolbar .terminal .xterm-color-184{color:#d7d700}#ex-debug-toolbar .terminal .xterm-bg-color-184{background-color:#d7d700}#ex-debug-toolbar .terminal .xterm-color-185{color:#d7d75f}#ex-debug-toolbar .terminal .xterm-bg-color-185{background-color:#d7d75f}#ex-debug-toolbar .terminal .xterm-color-186{color:#d7d787}#ex-debug-toolbar .terminal .xterm-bg-color-186{background-color:#d7d787}#ex-debug-toolbar .terminal .xterm-color-187{color:#d7d7af}#ex-debug-toolbar .terminal .xterm-bg-color-187{background-color:#d7d7af}#ex-debug-toolbar .terminal .xterm-color-188{color:#d7d7d7}#ex-debug-toolbar .terminal .xterm-bg-color-188{background-color:#d7d7d7}#ex-debug-toolbar .terminal .xterm-color-189{color:#d7d7ff}#ex-debug-toolbar .terminal .xterm-bg-color-189{background-color:#d7d7ff}#ex-debug-toolbar .terminal .xterm-color-190{color:#d7ff00}#ex-debug-toolbar .terminal .xterm-bg-color-190{background-color:#d7ff00}#ex-debug-toolbar .terminal .xterm-color-191{color:#d7ff5f}#ex-debug-toolbar .terminal .xterm-bg-color-191{background-color:#d7ff5f}#ex-debug-toolbar .terminal .xterm-color-192{color:#d7ff87}#ex-debug-toolbar .terminal .xterm-bg-color-192{background-color:#d7ff87}#ex-debug-toolbar .terminal .xterm-color-193{color:#d7ffaf}#ex-debug-toolbar .terminal .xterm-bg-color-193{background-color:#d7ffaf}#ex-debug-toolbar .terminal .xterm-color-194{color:#d7ffd7}#ex-debug-toolbar .terminal .xterm-bg-color-194{background-color:#d7ffd7}#ex-debug-toolbar .terminal .xterm-color-195{color:#d7ffff}#ex-debug-toolbar .terminal .xterm-bg-color-195{background-color:#d7ffff}#ex-debug-toolbar .terminal .xterm-color-196{color:red}#ex-debug-toolbar .terminal .xterm-bg-color-196{background-color:red}#ex-debug-toolbar .terminal .xterm-color-197{color:#ff005f}#ex-debug-toolbar .terminal .xterm-bg-color-197{background-color:#ff005f}#ex-debug-toolbar .terminal .xterm-color-198{color:#ff0087}#ex-debug-toolbar .terminal .xterm-bg-color-198{background-color:#ff0087}#ex-debug-toolbar .terminal .xterm-color-199{color:#ff00af}#ex-debug-toolbar .terminal .xterm-bg-color-199{background-color:#ff00af}#ex-debug-toolbar .terminal .xterm-color-200{color:#ff00d7}#ex-debug-toolbar .terminal .xterm-bg-color-200{background-color:#ff00d7}#ex-debug-toolbar .terminal .xterm-color-201{color:#f0f}#ex-debug-toolbar .terminal .xterm-bg-color-201{background-color:#f0f}#ex-debug-toolbar .terminal .xterm-color-202{color:#ff5f00}#ex-debug-toolbar .terminal .xterm-bg-color-202{background-color:#ff5f00}#ex-debug-toolbar .terminal .xterm-color-203{color:#ff5f5f}#ex-debug-toolbar .terminal .xterm-bg-color-203{background-color:#ff5f5f}#ex-debug-toolbar .terminal .xterm-color-204{color:#ff5f87}#ex-debug-toolbar .terminal .xterm-bg-color-204{background-color:#ff5f87}#ex-debug-toolbar .terminal .xterm-color-205{color:#ff5faf}#ex-debug-toolbar .terminal .xterm-bg-color-205{background-color:#ff5faf}#ex-debug-toolbar .terminal .xterm-color-206{color:#ff5fd7}#ex-debug-toolbar .terminal .xterm-bg-color-206{background-color:#ff5fd7}#ex-debug-toolbar .terminal .xterm-color-207{color:#ff5fff}#ex-debug-toolbar .terminal .xterm-bg-color-207{background-color:#ff5fff}#ex-debug-toolbar .terminal .xterm-color-208{color:#ff8700}#ex-debug-toolbar .terminal .xterm-bg-color-208{background-color:#ff8700}#ex-debug-toolbar .terminal .xterm-color-209{color:#ff875f}#ex-debug-toolbar .terminal .xterm-bg-color-209{background-color:#ff875f}#ex-debug-toolbar .terminal .xterm-color-210{color:#ff8787}#ex-debug-toolbar .terminal .xterm-bg-color-210{background-color:#ff8787}#ex-debug-toolbar .terminal .xterm-color-211{color:#ff87af}#ex-debug-toolbar .terminal .xterm-bg-color-211{background-color:#ff87af}#ex-debug-toolbar .terminal .xterm-color-212{color:#ff87d7}#ex-debug-toolbar .terminal .xterm-bg-color-212{background-color:#ff87d7}#ex-debug-toolbar .terminal .xterm-color-213{color:#ff87ff}#ex-debug-toolbar .terminal .xterm-bg-color-213{background-color:#ff87ff}#ex-debug-toolbar .terminal .xterm-color-214{color:#ffaf00}#ex-debug-toolbar .terminal .xterm-bg-color-214{background-color:#ffaf00}#ex-debug-toolbar .terminal .xterm-color-215{color:#ffaf5f}#ex-debug-toolbar .terminal .xterm-bg-color-215{background-color:#ffaf5f}#ex-debug-toolbar .terminal .xterm-color-216{color:#ffaf87}#ex-debug-toolbar .terminal .xterm-bg-color-216{background-color:#ffaf87}#ex-debug-toolbar .terminal .xterm-color-217{color:#ffafaf}#ex-debug-toolbar .terminal .xterm-bg-color-217{background-color:#ffafaf}#ex-debug-toolbar .terminal .xterm-color-218{color:#ffafd7}#ex-debug-toolbar .terminal .xterm-bg-color-218{background-color:#ffafd7}#ex-debug-toolbar .terminal .xterm-color-219{color:#ffafff}#ex-debug-toolbar .terminal .xterm-bg-color-219{background-color:#ffafff}#ex-debug-toolbar .terminal .xterm-color-220{color:gold}#ex-debug-toolbar .terminal .xterm-bg-color-220{background-color:gold}#ex-debug-toolbar .terminal .xterm-color-221{color:#ffd75f}#ex-debug-toolbar .terminal .xterm-bg-color-221{background-color:#ffd75f}#ex-debug-toolbar .terminal .xterm-color-222{color:#ffd787}#ex-debug-toolbar .terminal .xterm-bg-color-222{background-color:#ffd787}#ex-debug-toolbar .terminal .xterm-color-223{color:#ffd7af}#ex-debug-toolbar .terminal .xterm-bg-color-223{background-color:#ffd7af}#ex-debug-toolbar .terminal .xterm-color-224{color:#ffd7d7}#ex-debug-toolbar .terminal .xterm-bg-color-224{background-color:#ffd7d7}#ex-debug-toolbar .terminal .xterm-color-225{color:#ffd7ff}#ex-debug-toolbar .terminal .xterm-bg-color-225{background-color:#ffd7ff}#ex-debug-toolbar .terminal .xterm-color-226{color:#ff0}#ex-debug-toolbar .terminal .xterm-bg-color-226{background-color:#ff0}#ex-debug-toolbar .terminal .xterm-color-227{color:#ffff5f}#ex-debug-toolbar .terminal .xterm-bg-color-227{background-color:#ffff5f}#ex-debug-toolbar .terminal .xterm-color-228{color:#ffff87}#ex-debug-toolbar .terminal .xterm-bg-color-228{background-color:#ffff87}#ex-debug-toolbar .terminal .xterm-color-229{color:#ffffaf}#ex-debug-toolbar .terminal .xterm-bg-color-229{background-color:#ffffaf}#ex-debug-toolbar .terminal .xterm-color-230{color:#ffffd7}#ex-debug-toolbar .terminal .xterm-bg-color-230{background-color:#ffffd7}#ex-debug-toolbar .terminal .xterm-color-231{color:#fff}#ex-debug-toolbar .terminal .xterm-bg-color-231{background-color:#fff}#ex-debug-toolbar .terminal .xterm-color-232{color:#080808}#ex-debug-toolbar .terminal .xterm-bg-color-232{background-color:#080808}#ex-debug-toolbar .terminal .xterm-color-233{color:#121212}#ex-debug-toolbar .terminal .xterm-bg-color-233{background-color:#121212}#ex-debug-toolbar .terminal .xterm-color-234{color:#1c1c1c}#ex-debug-toolbar .terminal .xterm-bg-color-234{background-color:#1c1c1c}#ex-debug-toolbar .terminal .xterm-color-235{color:#262626}#ex-debug-toolbar .terminal .xterm-bg-color-235{background-color:#262626}#ex-debug-toolbar .terminal .xterm-color-236{color:#303030}#ex-debug-toolbar .terminal .xterm-bg-color-236{background-color:#303030}#ex-debug-toolbar .terminal .xterm-color-237{color:#3a3a3a}#ex-debug-toolbar .terminal .xterm-bg-color-237{background-color:#3a3a3a}#ex-debug-toolbar .terminal .xterm-color-238{color:#444}#ex-debug-toolbar .terminal .xterm-bg-color-238{background-color:#444}#ex-debug-toolbar .terminal .xterm-color-239{color:#4e4e4e}#ex-debug-toolbar .terminal .xterm-bg-color-239{background-color:#4e4e4e}#ex-debug-toolbar .terminal .xterm-color-240{color:#585858}#ex-debug-toolbar .terminal .xterm-bg-color-240{background-color:#585858}#ex-debug-toolbar .terminal .xterm-color-241{color:#626262}#ex-debug-toolbar .terminal .xterm-bg-color-241{background-color:#626262}#ex-debug-toolbar .terminal .xterm-color-242{color:#6c6c6c}#ex-debug-toolbar .terminal .xterm-bg-color-242{background-color:#6c6c6c}#ex-debug-toolbar .terminal .xterm-color-243{color:#767676}#ex-debug-toolbar .terminal .xterm-bg-color-243{background-color:#767676}#ex-debug-toolbar .terminal .xterm-color-244{color:grey}#ex-debug-toolbar .terminal .xterm-bg-color-244{background-color:grey}#ex-debug-toolbar .terminal .xterm-color-245{color:#8a8a8a}#ex-debug-toolbar .terminal .xterm-bg-color-245{background-color:#8a8a8a}#ex-debug-toolbar .terminal .xterm-color-246{color:#949494}#ex-debug-toolbar .terminal .xterm-bg-color-246{background-color:#949494}#ex-debug-toolbar .terminal .xterm-color-247{color:#9e9e9e}#ex-debug-toolbar .terminal .xterm-bg-color-247{background-color:#9e9e9e}#ex-debug-toolbar .terminal .xterm-color-248{color:#a8a8a8}#ex-debug-toolbar .terminal .xterm-bg-color-248{background-color:#a8a8a8}#ex-debug-toolbar .terminal .xterm-color-249{color:#b2b2b2}#ex-debug-toolbar .terminal .xterm-bg-color-249{background-color:#b2b2b2}#ex-debug-toolbar .terminal .xterm-color-250{color:#bcbcbc}#ex-debug-toolbar .terminal .xterm-bg-color-250{background-color:#bcbcbc}#ex-debug-toolbar .terminal .xterm-color-251{color:#c6c6c6}#ex-debug-toolbar .terminal .xterm-bg-color-251{background-color:#c6c6c6}#ex-debug-toolbar .terminal .xterm-color-252{color:#d0d0d0}#ex-debug-toolbar .terminal .xterm-bg-color-252{background-color:#d0d0d0}#ex-debug-toolbar .terminal .xterm-color-253{color:#dadada}#ex-debug-toolbar .terminal .xterm-bg-color-253{background-color:#dadada}#ex-debug-toolbar .terminal .xterm-color-254{color:#e4e4e4}#ex-debug-toolbar .terminal .xterm-bg-color-254{background-color:#e4e4e4}#ex-debug-toolbar .terminal .xterm-color-255{color:#eee}#ex-debug-toolbar .terminal .xterm-bg-color-255{background-color:#eee}#ex-debug-toolbar .xterm.fullscreen{position:fixed;top:0;bottom:0;left:0;right:0;width:auto;height:auto;z-index:255}#ex-debug-toolbar .navbar{min-height:30px;height:30px}#ex-debug-toolbar .navbar-nav.nav>li>span{padding-left:5px;padding-right:5px;padding-top:5px;cursor:pointer}#ex-debug-toolbar .navbar-nav.nav>li>span>i{margin-right:5px}#ex-debug-toolbar .navbar-brand{padding:2px 2px;height:30px}#ex-debug-toolbar .navbar-brand img{height:100%}#ex-debug-toolbar .toolbar-item{margin-right:5px}#ex-debug-toolbar .toolbar-item .label{position:relative;top:-2px}#ex-debug-toolbar .panel{margin-bottom:0;bottom:30px;display:none}#ex-debug-toolbar .panel .panel-body{padding:5px 15px;max-height:200px;overflow-y:auto}#ex-debug-toolbar .panel .panel-heading{padding:5px 15px}#ex-debug-toolbar .panel .table{margin-top:0;margin-bottom:0}#ex-debug-toolbar .panel .table caption{padding-top:4px;padding-bottom:4px}#ex-debug-toolbar .panel .table td,#ex-debug-toolbar .panel .table th{padding-left:5px;padding-right:5px;padding-top:1px;padding-bottom:1px}#ex-debug-toolbar .panel .table td p,#ex-debug-toolbar .panel .table th p{margin:0}#ex-debug-toolbar .nowrap{white-space:nowrap}#ex-debug-toolbar table .hljs{background:unset;padding:unset}#ex-debug-toolbar .pointer{cursor:pointer}#ex-debug-toolbar #terminal-container{width:auto;height:480px}#ex-debug-toolbar .modal-top-action{margin-right:10px}#ex-debug-toolbar .fullscreen .modal-dialog{width:100%;height:100%;margin:0;padding:0}#ex-debug-toolbar .fullscreen .modal-content{height:auto;min-height:100%;border-radius:0}#ex-debug-toolbar .fullscreen #terminal-container{height:100%}#ex-debug-toolbar .xterm.fullscreen{top:55px}#ex-debug-toolbar #code-snippet-container{margin-top:40px;position:fixed;left:50%}#ex-debug-toolbar #breakpoint .panel-body{height:200px}#ex-debug-toolbar .historic-flag{display:none}#ex-debug-toolbar .historic-flag .back-to-current-request{font-weight:700;color:#000;font-size:.85em;text-decoration:underline}#ex-debug-toolbar .historic-request .historic-flag{display:block}#ex-debug-toolbar .historic-request .navbar{background-color:#ececdb}#ex-debug-toolbar .history-point{cursor:pointer}#ex-debug-toolbar .history-point.active{cursor:default}#ex-debug-toolbar .history-point.prev-request{display:none}#ex-debug-toolbar .history-point .history-collapse{display:none} \ No newline at end of file + */ + /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ + /*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ + /** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + /* Code blocks */ + /* Inline code */ + /** + * xterm.js: xterm, in the browser + * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License) + * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License) + * https://github.com/chjj/term.js + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from (with the author's permission): + * Fabrice Bellard's javascript vt100 for jslinux: + * http://bellard.org/jslinux/ + * Copyright (c) 2011 Fabrice Bellard + * The original design remains. The terminal itself + * has been extended to include xterm CSI codes, among + * other features. + */ + /* + * Default style for xterm.js + */ + /* + * Determine default colors for xterm.js + */ } + #ex-debug-toolbar *::before { + all: unset; } + #ex-debug-toolbar *::after { + all: unset; } + #ex-debug-toolbar *::hover { + all: unset; } + #ex-debug-toolbar *::visited { + all: unset; } + #ex-debug-toolbar *::link { + all: unset; } + #ex-debug-toolbar *::active { + all: unset; } + #ex-debug-toolbar * { + max-width: inherit; + max-height: inherit; } + #ex-debug-toolbar .container-fluid * { + background: inherit; } + #ex-debug-toolbar html, #ex-debug-toolbar body, #ex-debug-toolbar div, #ex-debug-toolbar span, #ex-debug-toolbar applet, #ex-debug-toolbar object, #ex-debug-toolbar iframe, + #ex-debug-toolbar h1, #ex-debug-toolbar h2, #ex-debug-toolbar h3, #ex-debug-toolbar h4, #ex-debug-toolbar h5, #ex-debug-toolbar h6, #ex-debug-toolbar p, #ex-debug-toolbar blockquote, #ex-debug-toolbar pre, + #ex-debug-toolbar a, #ex-debug-toolbar .navbar-nav.nav > li > span, #ex-debug-toolbar abbr, #ex-debug-toolbar acronym, #ex-debug-toolbar address, #ex-debug-toolbar big, #ex-debug-toolbar cite, #ex-debug-toolbar code, + #ex-debug-toolbar del, #ex-debug-toolbar dfn, #ex-debug-toolbar em, #ex-debug-toolbar img, #ex-debug-toolbar ins, #ex-debug-toolbar kbd, #ex-debug-toolbar q, #ex-debug-toolbar s, #ex-debug-toolbar samp, + #ex-debug-toolbar small, #ex-debug-toolbar strike, #ex-debug-toolbar strong, #ex-debug-toolbar sub, #ex-debug-toolbar sup, #ex-debug-toolbar tt, #ex-debug-toolbar var, + #ex-debug-toolbar b, #ex-debug-toolbar u, #ex-debug-toolbar i, #ex-debug-toolbar center, + #ex-debug-toolbar dl, #ex-debug-toolbar dt, #ex-debug-toolbar dd, #ex-debug-toolbar ol, #ex-debug-toolbar ul, #ex-debug-toolbar li, + #ex-debug-toolbar fieldset, #ex-debug-toolbar form, #ex-debug-toolbar label, #ex-debug-toolbar legend, + #ex-debug-toolbar table, #ex-debug-toolbar caption, #ex-debug-toolbar tbody, #ex-debug-toolbar tfoot, #ex-debug-toolbar thead, #ex-debug-toolbar tr, #ex-debug-toolbar th, #ex-debug-toolbar td, + #ex-debug-toolbar article, #ex-debug-toolbar aside, #ex-debug-toolbar canvas, #ex-debug-toolbar details, #ex-debug-toolbar embed, + #ex-debug-toolbar figure, #ex-debug-toolbar figcaption, #ex-debug-toolbar footer, #ex-debug-toolbar header, #ex-debug-toolbar main, + #ex-debug-toolbar menu, #ex-debug-toolbar nav, #ex-debug-toolbar output, #ex-debug-toolbar ruby, #ex-debug-toolbar section, #ex-debug-toolbar summary, + #ex-debug-toolbar time, #ex-debug-toolbar mark, #ex-debug-toolbar audio, #ex-debug-toolbar video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } + #ex-debug-toolbar article, #ex-debug-toolbar aside, #ex-debug-toolbar details, #ex-debug-toolbar figcaption, #ex-debug-toolbar figure, + #ex-debug-toolbar footer, #ex-debug-toolbar header, #ex-debug-toolbar menu, #ex-debug-toolbar nav, #ex-debug-toolbar section, + #ex-debug-toolbar main, #ex-debug-toolbar summary { + display: block; } + #ex-debug-toolbar body { + line-height: 1; } + #ex-debug-toolbar ol, #ex-debug-toolbar ul { + list-style: none; } + #ex-debug-toolbar blockquote, #ex-debug-toolbar q { + quotes: none; } + #ex-debug-toolbar blockquote:before, #ex-debug-toolbar blockquote:after, + #ex-debug-toolbar q:before, #ex-debug-toolbar q:after { + content: ''; + content: none; } + #ex-debug-toolbar table { + border-collapse: collapse; + border-spacing: 0; } + #ex-debug-toolbar html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; } + #ex-debug-toolbar audio, + #ex-debug-toolbar canvas, + #ex-debug-toolbar progress, + #ex-debug-toolbar video { + display: inline-block; + vertical-align: baseline; } + #ex-debug-toolbar audio:not([controls]) { + display: none; + height: 0; } + #ex-debug-toolbar [hidden], + #ex-debug-toolbar template { + display: none; } + #ex-debug-toolbar a, #ex-debug-toolbar .navbar-nav.nav > li > span { + background-color: transparent; } + #ex-debug-toolbar a:active, #ex-debug-toolbar .navbar-nav.nav > li > span:active, + #ex-debug-toolbar a:hover, #ex-debug-toolbar .navbar-nav.nav > li > span:hover { + outline: 0; } + #ex-debug-toolbar abbr[title] { + border-bottom: 1px dotted; } + #ex-debug-toolbar b, + #ex-debug-toolbar strong { + font-weight: bold; } + #ex-debug-toolbar dfn, + #ex-debug-toolbar i, #ex-debug-toolbar em { + font-style: italic; } + #ex-debug-toolbar mark { + background: #ff0; + color: #000; } + #ex-debug-toolbar small { + font-size: 80%; } + #ex-debug-toolbar sub, + #ex-debug-toolbar sup { + font-size: 75%; + line-height: 0; + position: relative; } + #ex-debug-toolbar sup { + top: -0.5em; } + #ex-debug-toolbar sub { + bottom: -0.25em; } + #ex-debug-toolbar img { + border: 0; } + #ex-debug-toolbar svg:not(:root) { + overflow: hidden; } + #ex-debug-toolbar hr { + box-sizing: content-box; + height: 0; } + #ex-debug-toolbar pre { + overflow: auto; } + #ex-debug-toolbar code, + #ex-debug-toolbar kbd, + #ex-debug-toolbar pre, + #ex-debug-toolbar samp { + font-family: monospace, monospace; } + #ex-debug-toolbar button, + #ex-debug-toolbar input, + #ex-debug-toolbar optgroup, + #ex-debug-toolbar select, + #ex-debug-toolbar textarea { + color: inherit; + font: inherit; + margin: 0; } + #ex-debug-toolbar button { + overflow: visible; } + #ex-debug-toolbar button, + #ex-debug-toolbar select { + text-transform: none; } + #ex-debug-toolbar button, + #ex-debug-toolbar html input[type="button"], + #ex-debug-toolbar input[type="reset"], + #ex-debug-toolbar input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; } + #ex-debug-toolbar button[disabled], + #ex-debug-toolbar html input[disabled] { + cursor: default; } + #ex-debug-toolbar button::-moz-focus-inner, + #ex-debug-toolbar input::-moz-focus-inner { + border: 0; + padding: 0; } + #ex-debug-toolbar input { + line-height: normal; } + #ex-debug-toolbar input[type="checkbox"], + #ex-debug-toolbar input[type="radio"] { + padding: 0; } + #ex-debug-toolbar input[type="number"]::-webkit-inner-spin-button, + #ex-debug-toolbar input[type="number"]::-webkit-outer-spin-button { + height: auto; } + #ex-debug-toolbar input[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; } + #ex-debug-toolbar input[type="search"]::-webkit-search-cancel-button, + #ex-debug-toolbar input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + #ex-debug-toolbar textarea { + overflow: auto; } + #ex-debug-toolbar optgroup { + font-weight: bold; } + #ex-debug-toolbar html { + font-family: sans-serif; + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; } + #ex-debug-toolbar body { + margin: 0; } + #ex-debug-toolbar article, + #ex-debug-toolbar aside, + #ex-debug-toolbar details, + #ex-debug-toolbar figcaption, + #ex-debug-toolbar figure, + #ex-debug-toolbar footer, + #ex-debug-toolbar header, + #ex-debug-toolbar hgroup, + #ex-debug-toolbar main, + #ex-debug-toolbar menu, + #ex-debug-toolbar nav, + #ex-debug-toolbar section, + #ex-debug-toolbar summary { + display: block; } + #ex-debug-toolbar audio, + #ex-debug-toolbar canvas, + #ex-debug-toolbar progress, + #ex-debug-toolbar video { + display: inline-block; + vertical-align: baseline; } + #ex-debug-toolbar audio:not([controls]) { + display: none; + height: 0; } + #ex-debug-toolbar [hidden], + #ex-debug-toolbar template { + display: none; } + #ex-debug-toolbar a, #ex-debug-toolbar .navbar-nav.nav > li > span { + background-color: transparent; } + #ex-debug-toolbar a:active, #ex-debug-toolbar .navbar-nav.nav > li > span:active, + #ex-debug-toolbar a:hover, #ex-debug-toolbar .navbar-nav.nav > li > span:hover { + outline: 0; } + #ex-debug-toolbar abbr[title] { + border-bottom: 1px dotted; } + #ex-debug-toolbar b, + #ex-debug-toolbar strong { + font-weight: bold; } + #ex-debug-toolbar dfn { + font-style: italic; } + #ex-debug-toolbar h1 { + font-size: 2em; + margin: 0.67em 0; } + #ex-debug-toolbar mark { + background: #ff0; + color: #000; } + #ex-debug-toolbar small { + font-size: 80%; } + #ex-debug-toolbar sub, + #ex-debug-toolbar sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + #ex-debug-toolbar sup { + top: -0.5em; } + #ex-debug-toolbar sub { + bottom: -0.25em; } + #ex-debug-toolbar img { + border: 0; } + #ex-debug-toolbar svg:not(:root) { + overflow: hidden; } + #ex-debug-toolbar figure { + margin: 1em 40px; } + #ex-debug-toolbar hr { + box-sizing: content-box; + height: 0; } + #ex-debug-toolbar pre { + overflow: auto; } + #ex-debug-toolbar code, + #ex-debug-toolbar kbd, + #ex-debug-toolbar pre, + #ex-debug-toolbar samp { + font-family: monospace, monospace; + font-size: 1em; } + #ex-debug-toolbar button, + #ex-debug-toolbar input, + #ex-debug-toolbar optgroup, + #ex-debug-toolbar select, + #ex-debug-toolbar textarea { + color: inherit; + font: inherit; + margin: 0; } + #ex-debug-toolbar button { + overflow: visible; } + #ex-debug-toolbar button, + #ex-debug-toolbar select { + text-transform: none; } + #ex-debug-toolbar button, + #ex-debug-toolbar html input[type="button"], + #ex-debug-toolbar input[type="reset"], + #ex-debug-toolbar input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; } + #ex-debug-toolbar button[disabled], + #ex-debug-toolbar html input[disabled] { + cursor: default; } + #ex-debug-toolbar button::-moz-focus-inner, + #ex-debug-toolbar input::-moz-focus-inner { + border: 0; + padding: 0; } + #ex-debug-toolbar input { + line-height: normal; } + #ex-debug-toolbar input[type="checkbox"], + #ex-debug-toolbar input[type="radio"] { + box-sizing: border-box; + padding: 0; } + #ex-debug-toolbar input[type="number"]::-webkit-inner-spin-button, + #ex-debug-toolbar input[type="number"]::-webkit-outer-spin-button { + height: auto; } + #ex-debug-toolbar input[type="search"] { + -webkit-appearance: textfield; + box-sizing: content-box; } + #ex-debug-toolbar input[type="search"]::-webkit-search-cancel-button, + #ex-debug-toolbar input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + #ex-debug-toolbar fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + #ex-debug-toolbar legend { + border: 0; + padding: 0; } + #ex-debug-toolbar textarea { + overflow: auto; } + #ex-debug-toolbar optgroup { + font-weight: bold; } + #ex-debug-toolbar table { + border-collapse: collapse; + border-spacing: 0; } + #ex-debug-toolbar td, + #ex-debug-toolbar th { + padding: 0; } + @media print { + #ex-debug-toolbar *, + #ex-debug-toolbar *:before, + #ex-debug-toolbar *:after { + background: transparent !important; + color: #000 !important; + box-shadow: none !important; + text-shadow: none !important; } + #ex-debug-toolbar a, #ex-debug-toolbar .navbar-nav.nav > li > span, + #ex-debug-toolbar a:visited, #ex-debug-toolbar .navbar-nav.nav > li > span:visited { + text-decoration: underline; } + #ex-debug-toolbar a[href]:after, #ex-debug-toolbar .navbar-nav.nav > li > span[href]:after { + content: " (" attr(href) ")"; } + #ex-debug-toolbar abbr[title]:after { + content: " (" attr(title) ")"; } + #ex-debug-toolbar a[href^="#"]:after, #ex-debug-toolbar .navbar-nav.nav > li > span[href^="#"]:after, + #ex-debug-toolbar a[href^="javascript:"]:after, #ex-debug-toolbar .navbar-nav.nav > li > span[href^="javascript:"]:after { + content: ""; } + #ex-debug-toolbar pre, + #ex-debug-toolbar blockquote { + border: 1px solid #999; + page-break-inside: avoid; } + #ex-debug-toolbar thead { + display: table-header-group; } + #ex-debug-toolbar tr, + #ex-debug-toolbar img { + page-break-inside: avoid; } + #ex-debug-toolbar img { + max-width: 100% !important; } + #ex-debug-toolbar p, + #ex-debug-toolbar h2, + #ex-debug-toolbar h3 { + orphans: 3; + widows: 3; } + #ex-debug-toolbar h2, + #ex-debug-toolbar h3 { + page-break-after: avoid; } + #ex-debug-toolbar .navbar { + display: none; } + #ex-debug-toolbar .btn > .caret, + #ex-debug-toolbar .dropup > .btn > .caret { + border-top-color: #000 !important; } + #ex-debug-toolbar .label { + border: 1px solid #000; } + #ex-debug-toolbar .table { + border-collapse: collapse !important; } + #ex-debug-toolbar .table td, + #ex-debug-toolbar .table th { + background-color: #fff !important; } + #ex-debug-toolbar .table-bordered th, + #ex-debug-toolbar .table-bordered td { + border: 1px solid #ddd !important; } } + +@font-face { + font-family: 'Glyphicons Halflings'; + src: url("../fonts/bootstrap/glyphicons-halflings-regular.eot"); + src: url("../fonts/bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/bootstrap/glyphicons-halflings-regular.woff2") format("woff2"), url("../fonts/bootstrap/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/bootstrap/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg"); } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .glyphicon-asterisk:before { + content: "\002a"; } + #ex-debug-toolbar .glyphicon-plus:before { + content: "\002b"; } + #ex-debug-toolbar .glyphicon-euro:before, + #ex-debug-toolbar .glyphicon-eur:before { + content: "\20ac"; } + #ex-debug-toolbar .glyphicon-minus:before { + content: "\2212"; } + #ex-debug-toolbar .glyphicon-cloud:before { + content: "\2601"; } + #ex-debug-toolbar .glyphicon-envelope:before { + content: "\2709"; } + #ex-debug-toolbar .glyphicon-pencil:before { + content: "\270f"; } + #ex-debug-toolbar .glyphicon-glass:before { + content: "\e001"; } + #ex-debug-toolbar .glyphicon-music:before { + content: "\e002"; } + #ex-debug-toolbar .glyphicon-search:before { + content: "\e003"; } + #ex-debug-toolbar .glyphicon-heart:before { + content: "\e005"; } + #ex-debug-toolbar .glyphicon-star:before { + content: "\e006"; } + #ex-debug-toolbar .glyphicon-star-empty:before { + content: "\e007"; } + #ex-debug-toolbar .glyphicon-user:before { + content: "\e008"; } + #ex-debug-toolbar .glyphicon-film:before { + content: "\e009"; } + #ex-debug-toolbar .glyphicon-th-large:before { + content: "\e010"; } + #ex-debug-toolbar .glyphicon-th:before { + content: "\e011"; } + #ex-debug-toolbar .glyphicon-th-list:before { + content: "\e012"; } + #ex-debug-toolbar .glyphicon-ok:before { + content: "\e013"; } + #ex-debug-toolbar .glyphicon-remove:before { + content: "\e014"; } + #ex-debug-toolbar .glyphicon-zoom-in:before { + content: "\e015"; } + #ex-debug-toolbar .glyphicon-zoom-out:before { + content: "\e016"; } + #ex-debug-toolbar .glyphicon-off:before { + content: "\e017"; } + #ex-debug-toolbar .glyphicon-signal:before { + content: "\e018"; } + #ex-debug-toolbar .glyphicon-cog:before { + content: "\e019"; } + #ex-debug-toolbar .glyphicon-trash:before { + content: "\e020"; } + #ex-debug-toolbar .glyphicon-home:before { + content: "\e021"; } + #ex-debug-toolbar .glyphicon-file:before { + content: "\e022"; } + #ex-debug-toolbar .glyphicon-time:before { + content: "\e023"; } + #ex-debug-toolbar .glyphicon-road:before { + content: "\e024"; } + #ex-debug-toolbar .glyphicon-download-alt:before { + content: "\e025"; } + #ex-debug-toolbar .glyphicon-download:before { + content: "\e026"; } + #ex-debug-toolbar .glyphicon-upload:before { + content: "\e027"; } + #ex-debug-toolbar .glyphicon-inbox:before { + content: "\e028"; } + #ex-debug-toolbar .glyphicon-play-circle:before { + content: "\e029"; } + #ex-debug-toolbar .glyphicon-repeat:before { + content: "\e030"; } + #ex-debug-toolbar .glyphicon-refresh:before { + content: "\e031"; } + #ex-debug-toolbar .glyphicon-list-alt:before { + content: "\e032"; } + #ex-debug-toolbar .glyphicon-lock:before { + content: "\e033"; } + #ex-debug-toolbar .glyphicon-flag:before { + content: "\e034"; } + #ex-debug-toolbar .glyphicon-headphones:before { + content: "\e035"; } + #ex-debug-toolbar .glyphicon-volume-off:before { + content: "\e036"; } + #ex-debug-toolbar .glyphicon-volume-down:before { + content: "\e037"; } + #ex-debug-toolbar .glyphicon-volume-up:before { + content: "\e038"; } + #ex-debug-toolbar .glyphicon-qrcode:before { + content: "\e039"; } + #ex-debug-toolbar .glyphicon-barcode:before { + content: "\e040"; } + #ex-debug-toolbar .glyphicon-tag:before { + content: "\e041"; } + #ex-debug-toolbar .glyphicon-tags:before { + content: "\e042"; } + #ex-debug-toolbar .glyphicon-book:before { + content: "\e043"; } + #ex-debug-toolbar .glyphicon-bookmark:before { + content: "\e044"; } + #ex-debug-toolbar .glyphicon-print:before { + content: "\e045"; } + #ex-debug-toolbar .glyphicon-camera:before { + content: "\e046"; } + #ex-debug-toolbar .glyphicon-font:before { + content: "\e047"; } + #ex-debug-toolbar .glyphicon-bold:before { + content: "\e048"; } + #ex-debug-toolbar .glyphicon-italic:before { + content: "\e049"; } + #ex-debug-toolbar .glyphicon-text-height:before { + content: "\e050"; } + #ex-debug-toolbar .glyphicon-text-width:before { + content: "\e051"; } + #ex-debug-toolbar .glyphicon-align-left:before { + content: "\e052"; } + #ex-debug-toolbar .glyphicon-align-center:before { + content: "\e053"; } + #ex-debug-toolbar .glyphicon-align-right:before { + content: "\e054"; } + #ex-debug-toolbar .glyphicon-align-justify:before { + content: "\e055"; } + #ex-debug-toolbar .glyphicon-list:before { + content: "\e056"; } + #ex-debug-toolbar .glyphicon-indent-left:before { + content: "\e057"; } + #ex-debug-toolbar .glyphicon-indent-right:before { + content: "\e058"; } + #ex-debug-toolbar .glyphicon-facetime-video:before { + content: "\e059"; } + #ex-debug-toolbar .glyphicon-picture:before { + content: "\e060"; } + #ex-debug-toolbar .glyphicon-map-marker:before { + content: "\e062"; } + #ex-debug-toolbar .glyphicon-adjust:before { + content: "\e063"; } + #ex-debug-toolbar .glyphicon-tint:before { + content: "\e064"; } + #ex-debug-toolbar .glyphicon-edit:before { + content: "\e065"; } + #ex-debug-toolbar .glyphicon-share:before { + content: "\e066"; } + #ex-debug-toolbar .glyphicon-check:before { + content: "\e067"; } + #ex-debug-toolbar .glyphicon-move:before { + content: "\e068"; } + #ex-debug-toolbar .glyphicon-step-backward:before { + content: "\e069"; } + #ex-debug-toolbar .glyphicon-fast-backward:before { + content: "\e070"; } + #ex-debug-toolbar .glyphicon-backward:before { + content: "\e071"; } + #ex-debug-toolbar .glyphicon-play:before { + content: "\e072"; } + #ex-debug-toolbar .glyphicon-pause:before { + content: "\e073"; } + #ex-debug-toolbar .glyphicon-stop:before { + content: "\e074"; } + #ex-debug-toolbar .glyphicon-forward:before { + content: "\e075"; } + #ex-debug-toolbar .glyphicon-fast-forward:before { + content: "\e076"; } + #ex-debug-toolbar .glyphicon-step-forward:before { + content: "\e077"; } + #ex-debug-toolbar .glyphicon-eject:before { + content: "\e078"; } + #ex-debug-toolbar .glyphicon-chevron-left:before { + content: "\e079"; } + #ex-debug-toolbar .glyphicon-chevron-right:before { + content: "\e080"; } + #ex-debug-toolbar .glyphicon-plus-sign:before { + content: "\e081"; } + #ex-debug-toolbar .glyphicon-minus-sign:before { + content: "\e082"; } + #ex-debug-toolbar .glyphicon-remove-sign:before { + content: "\e083"; } + #ex-debug-toolbar .glyphicon-ok-sign:before { + content: "\e084"; } + #ex-debug-toolbar .glyphicon-question-sign:before { + content: "\e085"; } + #ex-debug-toolbar .glyphicon-info-sign:before { + content: "\e086"; } + #ex-debug-toolbar .glyphicon-screenshot:before { + content: "\e087"; } + #ex-debug-toolbar .glyphicon-remove-circle:before { + content: "\e088"; } + #ex-debug-toolbar .glyphicon-ok-circle:before { + content: "\e089"; } + #ex-debug-toolbar .glyphicon-ban-circle:before { + content: "\e090"; } + #ex-debug-toolbar .glyphicon-arrow-left:before { + content: "\e091"; } + #ex-debug-toolbar .glyphicon-arrow-right:before { + content: "\e092"; } + #ex-debug-toolbar .glyphicon-arrow-up:before { + content: "\e093"; } + #ex-debug-toolbar .glyphicon-arrow-down:before { + content: "\e094"; } + #ex-debug-toolbar .glyphicon-share-alt:before { + content: "\e095"; } + #ex-debug-toolbar .glyphicon-resize-full:before { + content: "\e096"; } + #ex-debug-toolbar .glyphicon-resize-small:before { + content: "\e097"; } + #ex-debug-toolbar .glyphicon-exclamation-sign:before { + content: "\e101"; } + #ex-debug-toolbar .glyphicon-gift:before { + content: "\e102"; } + #ex-debug-toolbar .glyphicon-leaf:before { + content: "\e103"; } + #ex-debug-toolbar .glyphicon-fire:before { + content: "\e104"; } + #ex-debug-toolbar .glyphicon-eye-open:before { + content: "\e105"; } + #ex-debug-toolbar .glyphicon-eye-close:before { + content: "\e106"; } + #ex-debug-toolbar .glyphicon-warning-sign:before { + content: "\e107"; } + #ex-debug-toolbar .glyphicon-plane:before { + content: "\e108"; } + #ex-debug-toolbar .glyphicon-calendar:before { + content: "\e109"; } + #ex-debug-toolbar .glyphicon-random:before { + content: "\e110"; } + #ex-debug-toolbar .glyphicon-comment:before { + content: "\e111"; } + #ex-debug-toolbar .glyphicon-magnet:before { + content: "\e112"; } + #ex-debug-toolbar .glyphicon-chevron-up:before { + content: "\e113"; } + #ex-debug-toolbar .glyphicon-chevron-down:before { + content: "\e114"; } + #ex-debug-toolbar .glyphicon-retweet:before { + content: "\e115"; } + #ex-debug-toolbar .glyphicon-shopping-cart:before { + content: "\e116"; } + #ex-debug-toolbar .glyphicon-folder-close:before { + content: "\e117"; } + #ex-debug-toolbar .glyphicon-folder-open:before { + content: "\e118"; } + #ex-debug-toolbar .glyphicon-resize-vertical:before { + content: "\e119"; } + #ex-debug-toolbar .glyphicon-resize-horizontal:before { + content: "\e120"; } + #ex-debug-toolbar .glyphicon-hdd:before { + content: "\e121"; } + #ex-debug-toolbar .glyphicon-bullhorn:before { + content: "\e122"; } + #ex-debug-toolbar .glyphicon-bell:before { + content: "\e123"; } + #ex-debug-toolbar .glyphicon-certificate:before { + content: "\e124"; } + #ex-debug-toolbar .glyphicon-thumbs-up:before { + content: "\e125"; } + #ex-debug-toolbar .glyphicon-thumbs-down:before { + content: "\e126"; } + #ex-debug-toolbar .glyphicon-hand-right:before { + content: "\e127"; } + #ex-debug-toolbar .glyphicon-hand-left:before { + content: "\e128"; } + #ex-debug-toolbar .glyphicon-hand-up:before { + content: "\e129"; } + #ex-debug-toolbar .glyphicon-hand-down:before { + content: "\e130"; } + #ex-debug-toolbar .glyphicon-circle-arrow-right:before { + content: "\e131"; } + #ex-debug-toolbar .glyphicon-circle-arrow-left:before { + content: "\e132"; } + #ex-debug-toolbar .glyphicon-circle-arrow-up:before { + content: "\e133"; } + #ex-debug-toolbar .glyphicon-circle-arrow-down:before { + content: "\e134"; } + #ex-debug-toolbar .glyphicon-globe:before { + content: "\e135"; } + #ex-debug-toolbar .glyphicon-wrench:before { + content: "\e136"; } + #ex-debug-toolbar .glyphicon-tasks:before { + content: "\e137"; } + #ex-debug-toolbar .glyphicon-filter:before { + content: "\e138"; } + #ex-debug-toolbar .glyphicon-briefcase:before { + content: "\e139"; } + #ex-debug-toolbar .glyphicon-fullscreen:before { + content: "\e140"; } + #ex-debug-toolbar .glyphicon-dashboard:before { + content: "\e141"; } + #ex-debug-toolbar .glyphicon-paperclip:before { + content: "\e142"; } + #ex-debug-toolbar .glyphicon-heart-empty:before { + content: "\e143"; } + #ex-debug-toolbar .glyphicon-link:before { + content: "\e144"; } + #ex-debug-toolbar .glyphicon-phone:before { + content: "\e145"; } + #ex-debug-toolbar .glyphicon-pushpin:before { + content: "\e146"; } + #ex-debug-toolbar .glyphicon-usd:before { + content: "\e148"; } + #ex-debug-toolbar .glyphicon-gbp:before { + content: "\e149"; } + #ex-debug-toolbar .glyphicon-sort:before { + content: "\e150"; } + #ex-debug-toolbar .glyphicon-sort-by-alphabet:before { + content: "\e151"; } + #ex-debug-toolbar .glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; } + #ex-debug-toolbar .glyphicon-sort-by-order:before { + content: "\e153"; } + #ex-debug-toolbar .glyphicon-sort-by-order-alt:before { + content: "\e154"; } + #ex-debug-toolbar .glyphicon-sort-by-attributes:before { + content: "\e155"; } + #ex-debug-toolbar .glyphicon-sort-by-attributes-alt:before { + content: "\e156"; } + #ex-debug-toolbar .glyphicon-unchecked:before { + content: "\e157"; } + #ex-debug-toolbar .glyphicon-expand:before { + content: "\e158"; } + #ex-debug-toolbar .glyphicon-collapse-down:before { + content: "\e159"; } + #ex-debug-toolbar .glyphicon-collapse-up:before { + content: "\e160"; } + #ex-debug-toolbar .glyphicon-log-in:before { + content: "\e161"; } + #ex-debug-toolbar .glyphicon-flash:before { + content: "\e162"; } + #ex-debug-toolbar .glyphicon-log-out:before { + content: "\e163"; } + #ex-debug-toolbar .glyphicon-new-window:before { + content: "\e164"; } + #ex-debug-toolbar .glyphicon-record:before { + content: "\e165"; } + #ex-debug-toolbar .glyphicon-save:before { + content: "\e166"; } + #ex-debug-toolbar .glyphicon-open:before { + content: "\e167"; } + #ex-debug-toolbar .glyphicon-saved:before { + content: "\e168"; } + #ex-debug-toolbar .glyphicon-import:before { + content: "\e169"; } + #ex-debug-toolbar .glyphicon-export:before { + content: "\e170"; } + #ex-debug-toolbar .glyphicon-send:before { + content: "\e171"; } + #ex-debug-toolbar .glyphicon-floppy-disk:before { + content: "\e172"; } + #ex-debug-toolbar .glyphicon-floppy-saved:before { + content: "\e173"; } + #ex-debug-toolbar .glyphicon-floppy-remove:before { + content: "\e174"; } + #ex-debug-toolbar .glyphicon-floppy-save:before { + content: "\e175"; } + #ex-debug-toolbar .glyphicon-floppy-open:before { + content: "\e176"; } + #ex-debug-toolbar .glyphicon-credit-card:before { + content: "\e177"; } + #ex-debug-toolbar .glyphicon-transfer:before { + content: "\e178"; } + #ex-debug-toolbar .glyphicon-cutlery:before { + content: "\e179"; } + #ex-debug-toolbar .glyphicon-header:before { + content: "\e180"; } + #ex-debug-toolbar .glyphicon-compressed:before { + content: "\e181"; } + #ex-debug-toolbar .glyphicon-earphone:before { + content: "\e182"; } + #ex-debug-toolbar .glyphicon-phone-alt:before { + content: "\e183"; } + #ex-debug-toolbar .glyphicon-tower:before { + content: "\e184"; } + #ex-debug-toolbar .glyphicon-stats:before { + content: "\e185"; } + #ex-debug-toolbar .glyphicon-sd-video:before { + content: "\e186"; } + #ex-debug-toolbar .glyphicon-hd-video:before { + content: "\e187"; } + #ex-debug-toolbar .glyphicon-subtitles:before { + content: "\e188"; } + #ex-debug-toolbar .glyphicon-sound-stereo:before { + content: "\e189"; } + #ex-debug-toolbar .glyphicon-sound-dolby:before { + content: "\e190"; } + #ex-debug-toolbar .glyphicon-sound-5-1:before { + content: "\e191"; } + #ex-debug-toolbar .glyphicon-sound-6-1:before { + content: "\e192"; } + #ex-debug-toolbar .glyphicon-sound-7-1:before { + content: "\e193"; } + #ex-debug-toolbar .glyphicon-copyright-mark:before { + content: "\e194"; } + #ex-debug-toolbar .glyphicon-registration-mark:before { + content: "\e195"; } + #ex-debug-toolbar .glyphicon-cloud-download:before { + content: "\e197"; } + #ex-debug-toolbar .glyphicon-cloud-upload:before { + content: "\e198"; } + #ex-debug-toolbar .glyphicon-tree-conifer:before { + content: "\e199"; } + #ex-debug-toolbar .glyphicon-tree-deciduous:before { + content: "\e200"; } + #ex-debug-toolbar .glyphicon-cd:before { + content: "\e201"; } + #ex-debug-toolbar .glyphicon-save-file:before { + content: "\e202"; } + #ex-debug-toolbar .glyphicon-open-file:before { + content: "\e203"; } + #ex-debug-toolbar .glyphicon-level-up:before { + content: "\e204"; } + #ex-debug-toolbar .glyphicon-copy:before { + content: "\e205"; } + #ex-debug-toolbar .glyphicon-paste:before { + content: "\e206"; } + #ex-debug-toolbar .glyphicon-alert:before { + content: "\e209"; } + #ex-debug-toolbar .glyphicon-equalizer:before { + content: "\e210"; } + #ex-debug-toolbar .glyphicon-king:before { + content: "\e211"; } + #ex-debug-toolbar .glyphicon-queen:before { + content: "\e212"; } + #ex-debug-toolbar .glyphicon-pawn:before { + content: "\e213"; } + #ex-debug-toolbar .glyphicon-bishop:before { + content: "\e214"; } + #ex-debug-toolbar .glyphicon-knight:before { + content: "\e215"; } + #ex-debug-toolbar .glyphicon-baby-formula:before { + content: "\e216"; } + #ex-debug-toolbar .glyphicon-tent:before { + content: "\26fa"; } + #ex-debug-toolbar .glyphicon-blackboard:before { + content: "\e218"; } + #ex-debug-toolbar .glyphicon-bed:before { + content: "\e219"; } + #ex-debug-toolbar .glyphicon-apple:before { + content: "\f8ff"; } + #ex-debug-toolbar .glyphicon-erase:before { + content: "\e221"; } + #ex-debug-toolbar .glyphicon-hourglass:before { + content: "\231b"; } + #ex-debug-toolbar .glyphicon-lamp:before { + content: "\e223"; } + #ex-debug-toolbar .glyphicon-duplicate:before { + content: "\e224"; } + #ex-debug-toolbar .glyphicon-piggy-bank:before { + content: "\e225"; } + #ex-debug-toolbar .glyphicon-scissors:before { + content: "\e226"; } + #ex-debug-toolbar .glyphicon-bitcoin:before { + content: "\e227"; } + #ex-debug-toolbar .glyphicon-btc:before { + content: "\e227"; } + #ex-debug-toolbar .glyphicon-xbt:before { + content: "\e227"; } + #ex-debug-toolbar .glyphicon-yen:before { + content: "\00a5"; } + #ex-debug-toolbar .glyphicon-jpy:before { + content: "\00a5"; } + #ex-debug-toolbar .glyphicon-ruble:before { + content: "\20bd"; } + #ex-debug-toolbar .glyphicon-rub:before { + content: "\20bd"; } + #ex-debug-toolbar .glyphicon-scale:before { + content: "\e230"; } + #ex-debug-toolbar .glyphicon-ice-lolly:before { + content: "\e231"; } + #ex-debug-toolbar .glyphicon-ice-lolly-tasted:before { + content: "\e232"; } + #ex-debug-toolbar .glyphicon-education:before { + content: "\e233"; } + #ex-debug-toolbar .glyphicon-option-horizontal:before { + content: "\e234"; } + #ex-debug-toolbar .glyphicon-option-vertical:before { + content: "\e235"; } + #ex-debug-toolbar .glyphicon-menu-hamburger:before { + content: "\e236"; } + #ex-debug-toolbar .glyphicon-modal-window:before { + content: "\e237"; } + #ex-debug-toolbar .glyphicon-oil:before { + content: "\e238"; } + #ex-debug-toolbar .glyphicon-grain:before { + content: "\e239"; } + #ex-debug-toolbar .glyphicon-sunglasses:before { + content: "\e240"; } + #ex-debug-toolbar .glyphicon-text-size:before { + content: "\e241"; } + #ex-debug-toolbar .glyphicon-text-color:before { + content: "\e242"; } + #ex-debug-toolbar .glyphicon-text-background:before { + content: "\e243"; } + #ex-debug-toolbar .glyphicon-object-align-top:before { + content: "\e244"; } + #ex-debug-toolbar .glyphicon-object-align-bottom:before { + content: "\e245"; } + #ex-debug-toolbar .glyphicon-object-align-horizontal:before { + content: "\e246"; } + #ex-debug-toolbar .glyphicon-object-align-left:before { + content: "\e247"; } + #ex-debug-toolbar .glyphicon-object-align-vertical:before { + content: "\e248"; } + #ex-debug-toolbar .glyphicon-object-align-right:before { + content: "\e249"; } + #ex-debug-toolbar .glyphicon-triangle-right:before { + content: "\e250"; } + #ex-debug-toolbar .glyphicon-triangle-left:before { + content: "\e251"; } + #ex-debug-toolbar .glyphicon-triangle-bottom:before { + content: "\e252"; } + #ex-debug-toolbar .glyphicon-triangle-top:before { + content: "\e253"; } + #ex-debug-toolbar .glyphicon-console:before { + content: "\e254"; } + #ex-debug-toolbar .glyphicon-superscript:before { + content: "\e255"; } + #ex-debug-toolbar .glyphicon-subscript:before { + content: "\e256"; } + #ex-debug-toolbar .glyphicon-menu-left:before { + content: "\e257"; } + #ex-debug-toolbar .glyphicon-menu-right:before { + content: "\e258"; } + #ex-debug-toolbar .glyphicon-menu-down:before { + content: "\e259"; } + #ex-debug-toolbar .glyphicon-menu-up:before { + content: "\e260"; } + #ex-debug-toolbar * { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + #ex-debug-toolbar *:before, + #ex-debug-toolbar *:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + #ex-debug-toolbar html { + font-size: 10px; + -webkit-tap-highlight-color: transparent; } + #ex-debug-toolbar body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857; + color: #333333; + background-color: #fff; } + #ex-debug-toolbar input, + #ex-debug-toolbar button, + #ex-debug-toolbar select, + #ex-debug-toolbar textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; } + #ex-debug-toolbar a, #ex-debug-toolbar .navbar-nav.nav > li > span { + color: #337ab7; + text-decoration: none; } + #ex-debug-toolbar a:hover, #ex-debug-toolbar .navbar-nav.nav > li > span:hover, #ex-debug-toolbar a:focus, #ex-debug-toolbar .navbar-nav.nav > li > span:focus { + color: #23527c; + text-decoration: underline; } + #ex-debug-toolbar a:focus, #ex-debug-toolbar .navbar-nav.nav > li > span:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + #ex-debug-toolbar figure { + margin: 0; } + #ex-debug-toolbar img { + vertical-align: middle; } + #ex-debug-toolbar .img-responsive { + display: block; + max-width: 100%; + height: auto; } + #ex-debug-toolbar .img-rounded { + border-radius: 6px; } + #ex-debug-toolbar .img-thumbnail { + padding: 4px; + line-height: 1.42857; + background-color: #fff; + border: 1px solid #ddd; + 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; } + #ex-debug-toolbar .img-circle { + border-radius: 50%; } + #ex-debug-toolbar hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; } + #ex-debug-toolbar .sr-only { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } + #ex-debug-toolbar .sr-only-focusable:active, #ex-debug-toolbar .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; } + #ex-debug-toolbar [role="button"] { + cursor: pointer; } + #ex-debug-toolbar h1, #ex-debug-toolbar h2, #ex-debug-toolbar h3, #ex-debug-toolbar h4, #ex-debug-toolbar h5, #ex-debug-toolbar h6, + #ex-debug-toolbar .h1, #ex-debug-toolbar .h2, #ex-debug-toolbar .h3, #ex-debug-toolbar .h4, #ex-debug-toolbar .h5, #ex-debug-toolbar .h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; } + #ex-debug-toolbar h1 small, + #ex-debug-toolbar h1 .small, #ex-debug-toolbar h2 small, + #ex-debug-toolbar h2 .small, #ex-debug-toolbar h3 small, + #ex-debug-toolbar h3 .small, #ex-debug-toolbar h4 small, + #ex-debug-toolbar h4 .small, #ex-debug-toolbar h5 small, + #ex-debug-toolbar h5 .small, #ex-debug-toolbar h6 small, + #ex-debug-toolbar h6 .small, + #ex-debug-toolbar .h1 small, + #ex-debug-toolbar .h1 .small, #ex-debug-toolbar .h2 small, + #ex-debug-toolbar .h2 .small, #ex-debug-toolbar .h3 small, + #ex-debug-toolbar .h3 .small, #ex-debug-toolbar .h4 small, + #ex-debug-toolbar .h4 .small, #ex-debug-toolbar .h5 small, + #ex-debug-toolbar .h5 .small, #ex-debug-toolbar .h6 small, + #ex-debug-toolbar .h6 .small { + font-weight: normal; + line-height: 1; + color: #777777; } + #ex-debug-toolbar h1, #ex-debug-toolbar .h1, + #ex-debug-toolbar h2, #ex-debug-toolbar .h2, + #ex-debug-toolbar h3, #ex-debug-toolbar .h3 { + margin-top: 20px; + margin-bottom: 10px; } + #ex-debug-toolbar h1 small, + #ex-debug-toolbar h1 .small, #ex-debug-toolbar .h1 small, + #ex-debug-toolbar .h1 .small, + #ex-debug-toolbar h2 small, + #ex-debug-toolbar h2 .small, #ex-debug-toolbar .h2 small, + #ex-debug-toolbar .h2 .small, + #ex-debug-toolbar h3 small, + #ex-debug-toolbar h3 .small, #ex-debug-toolbar .h3 small, + #ex-debug-toolbar .h3 .small { + font-size: 65%; } + #ex-debug-toolbar h4, #ex-debug-toolbar .h4, + #ex-debug-toolbar h5, #ex-debug-toolbar .h5, + #ex-debug-toolbar h6, #ex-debug-toolbar .h6 { + margin-top: 10px; + margin-bottom: 10px; } + #ex-debug-toolbar h4 small, + #ex-debug-toolbar h4 .small, #ex-debug-toolbar .h4 small, + #ex-debug-toolbar .h4 .small, + #ex-debug-toolbar h5 small, + #ex-debug-toolbar h5 .small, #ex-debug-toolbar .h5 small, + #ex-debug-toolbar .h5 .small, + #ex-debug-toolbar h6 small, + #ex-debug-toolbar h6 .small, #ex-debug-toolbar .h6 small, + #ex-debug-toolbar .h6 .small { + font-size: 75%; } + #ex-debug-toolbar h1, #ex-debug-toolbar .h1 { + font-size: 36px; } + #ex-debug-toolbar h2, #ex-debug-toolbar .h2 { + font-size: 30px; } + #ex-debug-toolbar h3, #ex-debug-toolbar .h3 { + font-size: 24px; } + #ex-debug-toolbar h4, #ex-debug-toolbar .h4 { + font-size: 18px; } + #ex-debug-toolbar h5, #ex-debug-toolbar .h5 { + font-size: 14px; } + #ex-debug-toolbar h6, #ex-debug-toolbar .h6 { + font-size: 12px; } + #ex-debug-toolbar p { + margin: 0 0 10px; } + #ex-debug-toolbar .lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; } + @media (min-width: 768px) { + #ex-debug-toolbar .lead { + font-size: 21px; } } + #ex-debug-toolbar small, + #ex-debug-toolbar .small { + font-size: 85%; } + #ex-debug-toolbar mark, + #ex-debug-toolbar .mark { + background-color: #fcf8e3; + padding: .2em; } + #ex-debug-toolbar .text-left { + text-align: left; } + #ex-debug-toolbar .text-right { + text-align: right; } + #ex-debug-toolbar .text-center { + text-align: center; } + #ex-debug-toolbar .text-justify { + text-align: justify; } + #ex-debug-toolbar .text-nowrap { + white-space: nowrap; } + #ex-debug-toolbar .text-lowercase { + text-transform: lowercase; } + #ex-debug-toolbar .text-uppercase, #ex-debug-toolbar .initialism { + text-transform: uppercase; } + #ex-debug-toolbar .text-capitalize { + text-transform: capitalize; } + #ex-debug-toolbar .text-muted { + color: #777777; } + #ex-debug-toolbar .text-primary { + color: #337ab7; } + #ex-debug-toolbar a.text-primary:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.text-primary:hover, + #ex-debug-toolbar a.text-primary:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.text-primary:focus { + color: #286090; } + #ex-debug-toolbar .text-success { + color: #3c763d; } + #ex-debug-toolbar a.text-success:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.text-success:hover, + #ex-debug-toolbar a.text-success:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.text-success:focus { + color: #2b542c; } + #ex-debug-toolbar .text-info { + color: #31708f; } + #ex-debug-toolbar a.text-info:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.text-info:hover, + #ex-debug-toolbar a.text-info:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.text-info:focus { + color: #245269; } + #ex-debug-toolbar .text-warning { + color: #8a6d3b; } + #ex-debug-toolbar a.text-warning:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.text-warning:hover, + #ex-debug-toolbar a.text-warning:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.text-warning:focus { + color: #66512c; } + #ex-debug-toolbar .text-danger { + color: #a94442; } + #ex-debug-toolbar a.text-danger:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.text-danger:hover, + #ex-debug-toolbar a.text-danger:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.text-danger:focus { + color: #843534; } + #ex-debug-toolbar .bg-primary { + color: #fff; } + #ex-debug-toolbar .bg-primary { + background-color: #337ab7; } + #ex-debug-toolbar a.bg-primary:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-primary:hover, + #ex-debug-toolbar a.bg-primary:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-primary:focus { + background-color: #286090; } + #ex-debug-toolbar .bg-success { + background-color: #dff0d8; } + #ex-debug-toolbar a.bg-success:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-success:hover, + #ex-debug-toolbar a.bg-success:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-success:focus { + background-color: #c1e2b3; } + #ex-debug-toolbar .bg-info { + background-color: #d9edf7; } + #ex-debug-toolbar a.bg-info:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-info:hover, + #ex-debug-toolbar a.bg-info:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-info:focus { + background-color: #afd9ee; } + #ex-debug-toolbar .bg-warning { + background-color: #fcf8e3; } + #ex-debug-toolbar a.bg-warning:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-warning:hover, + #ex-debug-toolbar a.bg-warning:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-warning:focus { + background-color: #f7ecb5; } + #ex-debug-toolbar .bg-danger { + background-color: #f2dede; } + #ex-debug-toolbar a.bg-danger:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-danger:hover, + #ex-debug-toolbar a.bg-danger:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.bg-danger:focus { + background-color: #e4b9b9; } + #ex-debug-toolbar .page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; } + #ex-debug-toolbar ul, + #ex-debug-toolbar ol { + margin-top: 0; + margin-bottom: 10px; } + #ex-debug-toolbar ul ul, + #ex-debug-toolbar ul ol, + #ex-debug-toolbar ol ul, + #ex-debug-toolbar ol ol { + margin-bottom: 0; } + #ex-debug-toolbar .list-unstyled { + padding-left: 0; + list-style: none; } + #ex-debug-toolbar .list-inline { + padding-left: 0; + list-style: none; + margin-left: -5px; } + #ex-debug-toolbar .list-inline > li { + display: inline-block; + padding-left: 5px; + padding-right: 5px; } + #ex-debug-toolbar dl { + margin-top: 0; + margin-bottom: 20px; } + #ex-debug-toolbar dt, + #ex-debug-toolbar dd { + line-height: 1.42857; } + #ex-debug-toolbar dt { + font-weight: bold; } + #ex-debug-toolbar dd { + margin-left: 0; } + #ex-debug-toolbar .dl-horizontal dd:before, #ex-debug-toolbar .dl-horizontal dd:after { + content: " "; + display: table; } + #ex-debug-toolbar .dl-horizontal dd:after { + clear: both; } + @media (min-width: 768px) { + #ex-debug-toolbar .dl-horizontal dt { + float: left; + width: 160px; + clear: left; + text-align: right; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } + #ex-debug-toolbar .dl-horizontal dd { + margin-left: 180px; } } + #ex-debug-toolbar abbr[title], + #ex-debug-toolbar abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777777; } + #ex-debug-toolbar .initialism { + font-size: 90%; } + #ex-debug-toolbar blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eeeeee; } + #ex-debug-toolbar blockquote p:last-child, + #ex-debug-toolbar blockquote ul:last-child, + #ex-debug-toolbar blockquote ol:last-child { + margin-bottom: 0; } + #ex-debug-toolbar blockquote footer, + #ex-debug-toolbar blockquote small, + #ex-debug-toolbar blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857; + color: #777777; } + #ex-debug-toolbar blockquote footer:before, + #ex-debug-toolbar blockquote small:before, + #ex-debug-toolbar blockquote .small:before { + content: '\2014 \00A0'; } + #ex-debug-toolbar .blockquote-reverse, + #ex-debug-toolbar blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; + text-align: right; } + #ex-debug-toolbar .blockquote-reverse footer:before, + #ex-debug-toolbar .blockquote-reverse small:before, + #ex-debug-toolbar .blockquote-reverse .small:before, + #ex-debug-toolbar blockquote.pull-right footer:before, + #ex-debug-toolbar blockquote.pull-right small:before, + #ex-debug-toolbar blockquote.pull-right .small:before { + content: ''; } + #ex-debug-toolbar .blockquote-reverse footer:after, + #ex-debug-toolbar .blockquote-reverse small:after, + #ex-debug-toolbar .blockquote-reverse .small:after, + #ex-debug-toolbar blockquote.pull-right footer:after, + #ex-debug-toolbar blockquote.pull-right small:after, + #ex-debug-toolbar blockquote.pull-right .small:after { + content: '\00A0 \2014'; } + #ex-debug-toolbar address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857; } + #ex-debug-toolbar code, + #ex-debug-toolbar kbd, + #ex-debug-toolbar pre, + #ex-debug-toolbar samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } + #ex-debug-toolbar code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; } + #ex-debug-toolbar kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25); } + #ex-debug-toolbar kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + box-shadow: none; } + #ex-debug-toolbar pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857; + word-break: break-all; + word-wrap: break-word; + color: #333333; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; } + #ex-debug-toolbar pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; } + #ex-debug-toolbar .pre-scrollable { + max-height: 340px; + overflow-y: scroll; } + #ex-debug-toolbar .container { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; } + #ex-debug-toolbar .container:before, #ex-debug-toolbar .container:after { + content: " "; + display: table; } + #ex-debug-toolbar .container:after { + clear: both; } + @media (min-width: 768px) { + #ex-debug-toolbar .container { + width: 750px; } } + @media (min-width: 992px) { + #ex-debug-toolbar .container { + width: 970px; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .container { + width: 1170px; } } + #ex-debug-toolbar .container-fluid { + margin-right: auto; + margin-left: auto; + padding-left: 15px; + padding-right: 15px; } + #ex-debug-toolbar .container-fluid:before, #ex-debug-toolbar .container-fluid:after { + content: " "; + display: table; } + #ex-debug-toolbar .container-fluid:after { + clear: both; } + #ex-debug-toolbar .row { + margin-left: -15px; + margin-right: -15px; } + #ex-debug-toolbar .row:before, #ex-debug-toolbar .row:after { + content: " "; + display: table; } + #ex-debug-toolbar .row:after { + clear: both; } + #ex-debug-toolbar .col-xs-1, #ex-debug-toolbar .col-sm-1, #ex-debug-toolbar .col-md-1, #ex-debug-toolbar .col-lg-1, #ex-debug-toolbar .col-xs-2, #ex-debug-toolbar .col-sm-2, #ex-debug-toolbar .col-md-2, #ex-debug-toolbar .col-lg-2, #ex-debug-toolbar .col-xs-3, #ex-debug-toolbar .col-sm-3, #ex-debug-toolbar .col-md-3, #ex-debug-toolbar .col-lg-3, #ex-debug-toolbar .col-xs-4, #ex-debug-toolbar .col-sm-4, #ex-debug-toolbar .col-md-4, #ex-debug-toolbar .col-lg-4, #ex-debug-toolbar .col-xs-5, #ex-debug-toolbar .col-sm-5, #ex-debug-toolbar .col-md-5, #ex-debug-toolbar .col-lg-5, #ex-debug-toolbar .col-xs-6, #ex-debug-toolbar .col-sm-6, #ex-debug-toolbar .col-md-6, #ex-debug-toolbar .col-lg-6, #ex-debug-toolbar .col-xs-7, #ex-debug-toolbar .col-sm-7, #ex-debug-toolbar .col-md-7, #ex-debug-toolbar .col-lg-7, #ex-debug-toolbar .col-xs-8, #ex-debug-toolbar .col-sm-8, #ex-debug-toolbar .col-md-8, #ex-debug-toolbar .col-lg-8, #ex-debug-toolbar .col-xs-9, #ex-debug-toolbar .col-sm-9, #ex-debug-toolbar .col-md-9, #ex-debug-toolbar .col-lg-9, #ex-debug-toolbar .col-xs-10, #ex-debug-toolbar .col-sm-10, #ex-debug-toolbar .col-md-10, #ex-debug-toolbar .col-lg-10, #ex-debug-toolbar .col-xs-11, #ex-debug-toolbar .col-sm-11, #ex-debug-toolbar .col-md-11, #ex-debug-toolbar .col-lg-11, #ex-debug-toolbar .col-xs-12, #ex-debug-toolbar .col-sm-12, #ex-debug-toolbar .col-md-12, #ex-debug-toolbar .col-lg-12 { + position: relative; + min-height: 1px; + padding-left: 15px; + padding-right: 15px; } + #ex-debug-toolbar .col-xs-1, #ex-debug-toolbar .col-xs-2, #ex-debug-toolbar .col-xs-3, #ex-debug-toolbar .col-xs-4, #ex-debug-toolbar .col-xs-5, #ex-debug-toolbar .col-xs-6, #ex-debug-toolbar .col-xs-7, #ex-debug-toolbar .col-xs-8, #ex-debug-toolbar .col-xs-9, #ex-debug-toolbar .col-xs-10, #ex-debug-toolbar .col-xs-11, #ex-debug-toolbar .col-xs-12 { + float: left; } + #ex-debug-toolbar .col-xs-1 { + width: 8.33333%; } + #ex-debug-toolbar .col-xs-2 { + width: 16.66667%; } + #ex-debug-toolbar .col-xs-3 { + width: 25%; } + #ex-debug-toolbar .col-xs-4 { + width: 33.33333%; } + #ex-debug-toolbar .col-xs-5 { + width: 41.66667%; } + #ex-debug-toolbar .col-xs-6 { + width: 50%; } + #ex-debug-toolbar .col-xs-7 { + width: 58.33333%; } + #ex-debug-toolbar .col-xs-8 { + width: 66.66667%; } + #ex-debug-toolbar .col-xs-9 { + width: 75%; } + #ex-debug-toolbar .col-xs-10 { + width: 83.33333%; } + #ex-debug-toolbar .col-xs-11 { + width: 91.66667%; } + #ex-debug-toolbar .col-xs-12 { + width: 100%; } + #ex-debug-toolbar .col-xs-pull-0 { + right: auto; } + #ex-debug-toolbar .col-xs-pull-1 { + right: 8.33333%; } + #ex-debug-toolbar .col-xs-pull-2 { + right: 16.66667%; } + #ex-debug-toolbar .col-xs-pull-3 { + right: 25%; } + #ex-debug-toolbar .col-xs-pull-4 { + right: 33.33333%; } + #ex-debug-toolbar .col-xs-pull-5 { + right: 41.66667%; } + #ex-debug-toolbar .col-xs-pull-6 { + right: 50%; } + #ex-debug-toolbar .col-xs-pull-7 { + right: 58.33333%; } + #ex-debug-toolbar .col-xs-pull-8 { + right: 66.66667%; } + #ex-debug-toolbar .col-xs-pull-9 { + right: 75%; } + #ex-debug-toolbar .col-xs-pull-10 { + right: 83.33333%; } + #ex-debug-toolbar .col-xs-pull-11 { + right: 91.66667%; } + #ex-debug-toolbar .col-xs-pull-12 { + right: 100%; } + #ex-debug-toolbar .col-xs-push-0 { + left: auto; } + #ex-debug-toolbar .col-xs-push-1 { + left: 8.33333%; } + #ex-debug-toolbar .col-xs-push-2 { + left: 16.66667%; } + #ex-debug-toolbar .col-xs-push-3 { + left: 25%; } + #ex-debug-toolbar .col-xs-push-4 { + left: 33.33333%; } + #ex-debug-toolbar .col-xs-push-5 { + left: 41.66667%; } + #ex-debug-toolbar .col-xs-push-6 { + left: 50%; } + #ex-debug-toolbar .col-xs-push-7 { + left: 58.33333%; } + #ex-debug-toolbar .col-xs-push-8 { + left: 66.66667%; } + #ex-debug-toolbar .col-xs-push-9 { + left: 75%; } + #ex-debug-toolbar .col-xs-push-10 { + left: 83.33333%; } + #ex-debug-toolbar .col-xs-push-11 { + left: 91.66667%; } + #ex-debug-toolbar .col-xs-push-12 { + left: 100%; } + #ex-debug-toolbar .col-xs-offset-0 { + margin-left: 0%; } + #ex-debug-toolbar .col-xs-offset-1 { + margin-left: 8.33333%; } + #ex-debug-toolbar .col-xs-offset-2 { + margin-left: 16.66667%; } + #ex-debug-toolbar .col-xs-offset-3 { + margin-left: 25%; } + #ex-debug-toolbar .col-xs-offset-4 { + margin-left: 33.33333%; } + #ex-debug-toolbar .col-xs-offset-5 { + margin-left: 41.66667%; } + #ex-debug-toolbar .col-xs-offset-6 { + margin-left: 50%; } + #ex-debug-toolbar .col-xs-offset-7 { + margin-left: 58.33333%; } + #ex-debug-toolbar .col-xs-offset-8 { + margin-left: 66.66667%; } + #ex-debug-toolbar .col-xs-offset-9 { + margin-left: 75%; } + #ex-debug-toolbar .col-xs-offset-10 { + margin-left: 83.33333%; } + #ex-debug-toolbar .col-xs-offset-11 { + margin-left: 91.66667%; } + #ex-debug-toolbar .col-xs-offset-12 { + margin-left: 100%; } + @media (min-width: 768px) { + #ex-debug-toolbar .col-sm-1, #ex-debug-toolbar .col-sm-2, #ex-debug-toolbar .col-sm-3, #ex-debug-toolbar .col-sm-4, #ex-debug-toolbar .col-sm-5, #ex-debug-toolbar .col-sm-6, #ex-debug-toolbar .col-sm-7, #ex-debug-toolbar .col-sm-8, #ex-debug-toolbar .col-sm-9, #ex-debug-toolbar .col-sm-10, #ex-debug-toolbar .col-sm-11, #ex-debug-toolbar .col-sm-12 { + float: left; } + #ex-debug-toolbar .col-sm-1 { + width: 8.33333%; } + #ex-debug-toolbar .col-sm-2 { + width: 16.66667%; } + #ex-debug-toolbar .col-sm-3 { + width: 25%; } + #ex-debug-toolbar .col-sm-4 { + width: 33.33333%; } + #ex-debug-toolbar .col-sm-5 { + width: 41.66667%; } + #ex-debug-toolbar .col-sm-6 { + width: 50%; } + #ex-debug-toolbar .col-sm-7 { + width: 58.33333%; } + #ex-debug-toolbar .col-sm-8 { + width: 66.66667%; } + #ex-debug-toolbar .col-sm-9 { + width: 75%; } + #ex-debug-toolbar .col-sm-10 { + width: 83.33333%; } + #ex-debug-toolbar .col-sm-11 { + width: 91.66667%; } + #ex-debug-toolbar .col-sm-12 { + width: 100%; } + #ex-debug-toolbar .col-sm-pull-0 { + right: auto; } + #ex-debug-toolbar .col-sm-pull-1 { + right: 8.33333%; } + #ex-debug-toolbar .col-sm-pull-2 { + right: 16.66667%; } + #ex-debug-toolbar .col-sm-pull-3 { + right: 25%; } + #ex-debug-toolbar .col-sm-pull-4 { + right: 33.33333%; } + #ex-debug-toolbar .col-sm-pull-5 { + right: 41.66667%; } + #ex-debug-toolbar .col-sm-pull-6 { + right: 50%; } + #ex-debug-toolbar .col-sm-pull-7 { + right: 58.33333%; } + #ex-debug-toolbar .col-sm-pull-8 { + right: 66.66667%; } + #ex-debug-toolbar .col-sm-pull-9 { + right: 75%; } + #ex-debug-toolbar .col-sm-pull-10 { + right: 83.33333%; } + #ex-debug-toolbar .col-sm-pull-11 { + right: 91.66667%; } + #ex-debug-toolbar .col-sm-pull-12 { + right: 100%; } + #ex-debug-toolbar .col-sm-push-0 { + left: auto; } + #ex-debug-toolbar .col-sm-push-1 { + left: 8.33333%; } + #ex-debug-toolbar .col-sm-push-2 { + left: 16.66667%; } + #ex-debug-toolbar .col-sm-push-3 { + left: 25%; } + #ex-debug-toolbar .col-sm-push-4 { + left: 33.33333%; } + #ex-debug-toolbar .col-sm-push-5 { + left: 41.66667%; } + #ex-debug-toolbar .col-sm-push-6 { + left: 50%; } + #ex-debug-toolbar .col-sm-push-7 { + left: 58.33333%; } + #ex-debug-toolbar .col-sm-push-8 { + left: 66.66667%; } + #ex-debug-toolbar .col-sm-push-9 { + left: 75%; } + #ex-debug-toolbar .col-sm-push-10 { + left: 83.33333%; } + #ex-debug-toolbar .col-sm-push-11 { + left: 91.66667%; } + #ex-debug-toolbar .col-sm-push-12 { + left: 100%; } + #ex-debug-toolbar .col-sm-offset-0 { + margin-left: 0%; } + #ex-debug-toolbar .col-sm-offset-1 { + margin-left: 8.33333%; } + #ex-debug-toolbar .col-sm-offset-2 { + margin-left: 16.66667%; } + #ex-debug-toolbar .col-sm-offset-3 { + margin-left: 25%; } + #ex-debug-toolbar .col-sm-offset-4 { + margin-left: 33.33333%; } + #ex-debug-toolbar .col-sm-offset-5 { + margin-left: 41.66667%; } + #ex-debug-toolbar .col-sm-offset-6 { + margin-left: 50%; } + #ex-debug-toolbar .col-sm-offset-7 { + margin-left: 58.33333%; } + #ex-debug-toolbar .col-sm-offset-8 { + margin-left: 66.66667%; } + #ex-debug-toolbar .col-sm-offset-9 { + margin-left: 75%; } + #ex-debug-toolbar .col-sm-offset-10 { + margin-left: 83.33333%; } + #ex-debug-toolbar .col-sm-offset-11 { + margin-left: 91.66667%; } + #ex-debug-toolbar .col-sm-offset-12 { + margin-left: 100%; } } + @media (min-width: 992px) { + #ex-debug-toolbar .col-md-1, #ex-debug-toolbar .col-md-2, #ex-debug-toolbar .col-md-3, #ex-debug-toolbar .col-md-4, #ex-debug-toolbar .col-md-5, #ex-debug-toolbar .col-md-6, #ex-debug-toolbar .col-md-7, #ex-debug-toolbar .col-md-8, #ex-debug-toolbar .col-md-9, #ex-debug-toolbar .col-md-10, #ex-debug-toolbar .col-md-11, #ex-debug-toolbar .col-md-12 { + float: left; } + #ex-debug-toolbar .col-md-1 { + width: 8.33333%; } + #ex-debug-toolbar .col-md-2 { + width: 16.66667%; } + #ex-debug-toolbar .col-md-3 { + width: 25%; } + #ex-debug-toolbar .col-md-4 { + width: 33.33333%; } + #ex-debug-toolbar .col-md-5 { + width: 41.66667%; } + #ex-debug-toolbar .col-md-6 { + width: 50%; } + #ex-debug-toolbar .col-md-7 { + width: 58.33333%; } + #ex-debug-toolbar .col-md-8 { + width: 66.66667%; } + #ex-debug-toolbar .col-md-9 { + width: 75%; } + #ex-debug-toolbar .col-md-10 { + width: 83.33333%; } + #ex-debug-toolbar .col-md-11 { + width: 91.66667%; } + #ex-debug-toolbar .col-md-12 { + width: 100%; } + #ex-debug-toolbar .col-md-pull-0 { + right: auto; } + #ex-debug-toolbar .col-md-pull-1 { + right: 8.33333%; } + #ex-debug-toolbar .col-md-pull-2 { + right: 16.66667%; } + #ex-debug-toolbar .col-md-pull-3 { + right: 25%; } + #ex-debug-toolbar .col-md-pull-4 { + right: 33.33333%; } + #ex-debug-toolbar .col-md-pull-5 { + right: 41.66667%; } + #ex-debug-toolbar .col-md-pull-6 { + right: 50%; } + #ex-debug-toolbar .col-md-pull-7 { + right: 58.33333%; } + #ex-debug-toolbar .col-md-pull-8 { + right: 66.66667%; } + #ex-debug-toolbar .col-md-pull-9 { + right: 75%; } + #ex-debug-toolbar .col-md-pull-10 { + right: 83.33333%; } + #ex-debug-toolbar .col-md-pull-11 { + right: 91.66667%; } + #ex-debug-toolbar .col-md-pull-12 { + right: 100%; } + #ex-debug-toolbar .col-md-push-0 { + left: auto; } + #ex-debug-toolbar .col-md-push-1 { + left: 8.33333%; } + #ex-debug-toolbar .col-md-push-2 { + left: 16.66667%; } + #ex-debug-toolbar .col-md-push-3 { + left: 25%; } + #ex-debug-toolbar .col-md-push-4 { + left: 33.33333%; } + #ex-debug-toolbar .col-md-push-5 { + left: 41.66667%; } + #ex-debug-toolbar .col-md-push-6 { + left: 50%; } + #ex-debug-toolbar .col-md-push-7 { + left: 58.33333%; } + #ex-debug-toolbar .col-md-push-8 { + left: 66.66667%; } + #ex-debug-toolbar .col-md-push-9 { + left: 75%; } + #ex-debug-toolbar .col-md-push-10 { + left: 83.33333%; } + #ex-debug-toolbar .col-md-push-11 { + left: 91.66667%; } + #ex-debug-toolbar .col-md-push-12 { + left: 100%; } + #ex-debug-toolbar .col-md-offset-0 { + margin-left: 0%; } + #ex-debug-toolbar .col-md-offset-1 { + margin-left: 8.33333%; } + #ex-debug-toolbar .col-md-offset-2 { + margin-left: 16.66667%; } + #ex-debug-toolbar .col-md-offset-3 { + margin-left: 25%; } + #ex-debug-toolbar .col-md-offset-4 { + margin-left: 33.33333%; } + #ex-debug-toolbar .col-md-offset-5 { + margin-left: 41.66667%; } + #ex-debug-toolbar .col-md-offset-6 { + margin-left: 50%; } + #ex-debug-toolbar .col-md-offset-7 { + margin-left: 58.33333%; } + #ex-debug-toolbar .col-md-offset-8 { + margin-left: 66.66667%; } + #ex-debug-toolbar .col-md-offset-9 { + margin-left: 75%; } + #ex-debug-toolbar .col-md-offset-10 { + margin-left: 83.33333%; } + #ex-debug-toolbar .col-md-offset-11 { + margin-left: 91.66667%; } + #ex-debug-toolbar .col-md-offset-12 { + margin-left: 100%; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .col-lg-1, #ex-debug-toolbar .col-lg-2, #ex-debug-toolbar .col-lg-3, #ex-debug-toolbar .col-lg-4, #ex-debug-toolbar .col-lg-5, #ex-debug-toolbar .col-lg-6, #ex-debug-toolbar .col-lg-7, #ex-debug-toolbar .col-lg-8, #ex-debug-toolbar .col-lg-9, #ex-debug-toolbar .col-lg-10, #ex-debug-toolbar .col-lg-11, #ex-debug-toolbar .col-lg-12 { + float: left; } + #ex-debug-toolbar .col-lg-1 { + width: 8.33333%; } + #ex-debug-toolbar .col-lg-2 { + width: 16.66667%; } + #ex-debug-toolbar .col-lg-3 { + width: 25%; } + #ex-debug-toolbar .col-lg-4 { + width: 33.33333%; } + #ex-debug-toolbar .col-lg-5 { + width: 41.66667%; } + #ex-debug-toolbar .col-lg-6 { + width: 50%; } + #ex-debug-toolbar .col-lg-7 { + width: 58.33333%; } + #ex-debug-toolbar .col-lg-8 { + width: 66.66667%; } + #ex-debug-toolbar .col-lg-9 { + width: 75%; } + #ex-debug-toolbar .col-lg-10 { + width: 83.33333%; } + #ex-debug-toolbar .col-lg-11 { + width: 91.66667%; } + #ex-debug-toolbar .col-lg-12 { + width: 100%; } + #ex-debug-toolbar .col-lg-pull-0 { + right: auto; } + #ex-debug-toolbar .col-lg-pull-1 { + right: 8.33333%; } + #ex-debug-toolbar .col-lg-pull-2 { + right: 16.66667%; } + #ex-debug-toolbar .col-lg-pull-3 { + right: 25%; } + #ex-debug-toolbar .col-lg-pull-4 { + right: 33.33333%; } + #ex-debug-toolbar .col-lg-pull-5 { + right: 41.66667%; } + #ex-debug-toolbar .col-lg-pull-6 { + right: 50%; } + #ex-debug-toolbar .col-lg-pull-7 { + right: 58.33333%; } + #ex-debug-toolbar .col-lg-pull-8 { + right: 66.66667%; } + #ex-debug-toolbar .col-lg-pull-9 { + right: 75%; } + #ex-debug-toolbar .col-lg-pull-10 { + right: 83.33333%; } + #ex-debug-toolbar .col-lg-pull-11 { + right: 91.66667%; } + #ex-debug-toolbar .col-lg-pull-12 { + right: 100%; } + #ex-debug-toolbar .col-lg-push-0 { + left: auto; } + #ex-debug-toolbar .col-lg-push-1 { + left: 8.33333%; } + #ex-debug-toolbar .col-lg-push-2 { + left: 16.66667%; } + #ex-debug-toolbar .col-lg-push-3 { + left: 25%; } + #ex-debug-toolbar .col-lg-push-4 { + left: 33.33333%; } + #ex-debug-toolbar .col-lg-push-5 { + left: 41.66667%; } + #ex-debug-toolbar .col-lg-push-6 { + left: 50%; } + #ex-debug-toolbar .col-lg-push-7 { + left: 58.33333%; } + #ex-debug-toolbar .col-lg-push-8 { + left: 66.66667%; } + #ex-debug-toolbar .col-lg-push-9 { + left: 75%; } + #ex-debug-toolbar .col-lg-push-10 { + left: 83.33333%; } + #ex-debug-toolbar .col-lg-push-11 { + left: 91.66667%; } + #ex-debug-toolbar .col-lg-push-12 { + left: 100%; } + #ex-debug-toolbar .col-lg-offset-0 { + margin-left: 0%; } + #ex-debug-toolbar .col-lg-offset-1 { + margin-left: 8.33333%; } + #ex-debug-toolbar .col-lg-offset-2 { + margin-left: 16.66667%; } + #ex-debug-toolbar .col-lg-offset-3 { + margin-left: 25%; } + #ex-debug-toolbar .col-lg-offset-4 { + margin-left: 33.33333%; } + #ex-debug-toolbar .col-lg-offset-5 { + margin-left: 41.66667%; } + #ex-debug-toolbar .col-lg-offset-6 { + margin-left: 50%; } + #ex-debug-toolbar .col-lg-offset-7 { + margin-left: 58.33333%; } + #ex-debug-toolbar .col-lg-offset-8 { + margin-left: 66.66667%; } + #ex-debug-toolbar .col-lg-offset-9 { + margin-left: 75%; } + #ex-debug-toolbar .col-lg-offset-10 { + margin-left: 83.33333%; } + #ex-debug-toolbar .col-lg-offset-11 { + margin-left: 91.66667%; } + #ex-debug-toolbar .col-lg-offset-12 { + margin-left: 100%; } } + #ex-debug-toolbar table { + background-color: transparent; } + #ex-debug-toolbar caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777777; + text-align: left; } + #ex-debug-toolbar th { + text-align: left; } + #ex-debug-toolbar .table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; } + #ex-debug-toolbar .table > thead > tr > th, + #ex-debug-toolbar .table > thead > tr > td, + #ex-debug-toolbar .table > tbody > tr > th, + #ex-debug-toolbar .table > tbody > tr > td, + #ex-debug-toolbar .table > tfoot > tr > th, + #ex-debug-toolbar .table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857; + vertical-align: top; + border-top: 1px solid #ddd; } + #ex-debug-toolbar .table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; } + #ex-debug-toolbar .table > caption + thead > tr:first-child > th, + #ex-debug-toolbar .table > caption + thead > tr:first-child > td, + #ex-debug-toolbar .table > colgroup + thead > tr:first-child > th, + #ex-debug-toolbar .table > colgroup + thead > tr:first-child > td, + #ex-debug-toolbar .table > thead:first-child > tr:first-child > th, + #ex-debug-toolbar .table > thead:first-child > tr:first-child > td { + border-top: 0; } + #ex-debug-toolbar .table > tbody + tbody { + border-top: 2px solid #ddd; } + #ex-debug-toolbar .table .table { + background-color: #fff; } + #ex-debug-toolbar .table-condensed > thead > tr > th, + #ex-debug-toolbar .table-condensed > thead > tr > td, + #ex-debug-toolbar .table-condensed > tbody > tr > th, + #ex-debug-toolbar .table-condensed > tbody > tr > td, + #ex-debug-toolbar .table-condensed > tfoot > tr > th, + #ex-debug-toolbar .table-condensed > tfoot > tr > td { + padding: 5px; } + #ex-debug-toolbar .table-bordered { + border: 1px solid #ddd; } + #ex-debug-toolbar .table-bordered > thead > tr > th, + #ex-debug-toolbar .table-bordered > thead > tr > td, + #ex-debug-toolbar .table-bordered > tbody > tr > th, + #ex-debug-toolbar .table-bordered > tbody > tr > td, + #ex-debug-toolbar .table-bordered > tfoot > tr > th, + #ex-debug-toolbar .table-bordered > tfoot > tr > td { + border: 1px solid #ddd; } + #ex-debug-toolbar .table-bordered > thead > tr > th, + #ex-debug-toolbar .table-bordered > thead > tr > td { + border-bottom-width: 2px; } + #ex-debug-toolbar .table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; } + #ex-debug-toolbar .table-hover > tbody > tr:hover { + background-color: #f5f5f5; } + #ex-debug-toolbar table col[class*="col-"] { + position: static; + float: none; + display: table-column; } + #ex-debug-toolbar table td[class*="col-"], + #ex-debug-toolbar table th[class*="col-"] { + position: static; + float: none; + display: table-cell; } + #ex-debug-toolbar .table > thead > tr > td.active, + #ex-debug-toolbar .table > thead > tr > th.active, + #ex-debug-toolbar .table > thead > tr.active > td, + #ex-debug-toolbar .table > thead > tr.active > th, + #ex-debug-toolbar .table > tbody > tr > td.active, + #ex-debug-toolbar .table > tbody > tr > th.active, + #ex-debug-toolbar .table > tbody > tr.active > td, + #ex-debug-toolbar .table > tbody > tr.active > th, + #ex-debug-toolbar .table > tfoot > tr > td.active, + #ex-debug-toolbar .table > tfoot > tr > th.active, + #ex-debug-toolbar .table > tfoot > tr.active > td, + #ex-debug-toolbar .table > tfoot > tr.active > th { + background-color: #f5f5f5; } + #ex-debug-toolbar .table-hover > tbody > tr > td.active:hover, + #ex-debug-toolbar .table-hover > tbody > tr > th.active:hover, + #ex-debug-toolbar .table-hover > tbody > tr.active:hover > td, + #ex-debug-toolbar .table-hover > tbody > tr:hover > .active, + #ex-debug-toolbar .table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; } + #ex-debug-toolbar .table > thead > tr > td.success, + #ex-debug-toolbar .table > thead > tr > th.success, + #ex-debug-toolbar .table > thead > tr.success > td, + #ex-debug-toolbar .table > thead > tr.success > th, + #ex-debug-toolbar .table > tbody > tr > td.success, + #ex-debug-toolbar .table > tbody > tr > th.success, + #ex-debug-toolbar .table > tbody > tr.success > td, + #ex-debug-toolbar .table > tbody > tr.success > th, + #ex-debug-toolbar .table > tfoot > tr > td.success, + #ex-debug-toolbar .table > tfoot > tr > th.success, + #ex-debug-toolbar .table > tfoot > tr.success > td, + #ex-debug-toolbar .table > tfoot > tr.success > th { + background-color: #dff0d8; } + #ex-debug-toolbar .table-hover > tbody > tr > td.success:hover, + #ex-debug-toolbar .table-hover > tbody > tr > th.success:hover, + #ex-debug-toolbar .table-hover > tbody > tr.success:hover > td, + #ex-debug-toolbar .table-hover > tbody > tr:hover > .success, + #ex-debug-toolbar .table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; } + #ex-debug-toolbar .table > thead > tr > td.info, + #ex-debug-toolbar .table > thead > tr > th.info, + #ex-debug-toolbar .table > thead > tr.info > td, + #ex-debug-toolbar .table > thead > tr.info > th, + #ex-debug-toolbar .table > tbody > tr > td.info, + #ex-debug-toolbar .table > tbody > tr > th.info, + #ex-debug-toolbar .table > tbody > tr.info > td, + #ex-debug-toolbar .table > tbody > tr.info > th, + #ex-debug-toolbar .table > tfoot > tr > td.info, + #ex-debug-toolbar .table > tfoot > tr > th.info, + #ex-debug-toolbar .table > tfoot > tr.info > td, + #ex-debug-toolbar .table > tfoot > tr.info > th { + background-color: #d9edf7; } + #ex-debug-toolbar .table-hover > tbody > tr > td.info:hover, + #ex-debug-toolbar .table-hover > tbody > tr > th.info:hover, + #ex-debug-toolbar .table-hover > tbody > tr.info:hover > td, + #ex-debug-toolbar .table-hover > tbody > tr:hover > .info, + #ex-debug-toolbar .table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; } + #ex-debug-toolbar .table > thead > tr > td.warning, + #ex-debug-toolbar .table > thead > tr > th.warning, + #ex-debug-toolbar .table > thead > tr.warning > td, + #ex-debug-toolbar .table > thead > tr.warning > th, + #ex-debug-toolbar .table > tbody > tr > td.warning, + #ex-debug-toolbar .table > tbody > tr > th.warning, + #ex-debug-toolbar .table > tbody > tr.warning > td, + #ex-debug-toolbar .table > tbody > tr.warning > th, + #ex-debug-toolbar .table > tfoot > tr > td.warning, + #ex-debug-toolbar .table > tfoot > tr > th.warning, + #ex-debug-toolbar .table > tfoot > tr.warning > td, + #ex-debug-toolbar .table > tfoot > tr.warning > th { + background-color: #fcf8e3; } + #ex-debug-toolbar .table-hover > tbody > tr > td.warning:hover, + #ex-debug-toolbar .table-hover > tbody > tr > th.warning:hover, + #ex-debug-toolbar .table-hover > tbody > tr.warning:hover > td, + #ex-debug-toolbar .table-hover > tbody > tr:hover > .warning, + #ex-debug-toolbar .table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; } + #ex-debug-toolbar .table > thead > tr > td.danger, + #ex-debug-toolbar .table > thead > tr > th.danger, + #ex-debug-toolbar .table > thead > tr.danger > td, + #ex-debug-toolbar .table > thead > tr.danger > th, + #ex-debug-toolbar .table > tbody > tr > td.danger, + #ex-debug-toolbar .table > tbody > tr > th.danger, + #ex-debug-toolbar .table > tbody > tr.danger > td, + #ex-debug-toolbar .table > tbody > tr.danger > th, + #ex-debug-toolbar .table > tfoot > tr > td.danger, + #ex-debug-toolbar .table > tfoot > tr > th.danger, + #ex-debug-toolbar .table > tfoot > tr.danger > td, + #ex-debug-toolbar .table > tfoot > tr.danger > th { + background-color: #f2dede; } + #ex-debug-toolbar .table-hover > tbody > tr > td.danger:hover, + #ex-debug-toolbar .table-hover > tbody > tr > th.danger:hover, + #ex-debug-toolbar .table-hover > tbody > tr.danger:hover > td, + #ex-debug-toolbar .table-hover > tbody > tr:hover > .danger, + #ex-debug-toolbar .table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; } + #ex-debug-toolbar .table-responsive { + overflow-x: auto; + min-height: 0.01%; } + @media screen and (max-width: 767px) { + #ex-debug-toolbar .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; } + #ex-debug-toolbar .table-responsive > .table { + margin-bottom: 0; } + #ex-debug-toolbar .table-responsive > .table > thead > tr > th, + #ex-debug-toolbar .table-responsive > .table > thead > tr > td, + #ex-debug-toolbar .table-responsive > .table > tbody > tr > th, + #ex-debug-toolbar .table-responsive > .table > tbody > tr > td, + #ex-debug-toolbar .table-responsive > .table > tfoot > tr > th, + #ex-debug-toolbar .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; } + #ex-debug-toolbar .table-responsive > .table-bordered { + border: 0; } + #ex-debug-toolbar .table-responsive > .table-bordered > thead > tr > th:first-child, + #ex-debug-toolbar .table-responsive > .table-bordered > thead > tr > td:first-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr > th:first-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr > td:first-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr > th:first-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; } + #ex-debug-toolbar .table-responsive > .table-bordered > thead > tr > th:last-child, + #ex-debug-toolbar .table-responsive > .table-bordered > thead > tr > td:last-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr > th:last-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr > td:last-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr > th:last-child, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; } + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr:last-child > th, + #ex-debug-toolbar .table-responsive > .table-bordered > tbody > tr:last-child > td, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr:last-child > th, + #ex-debug-toolbar .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; } } + #ex-debug-toolbar fieldset { + padding: 0; + margin: 0; + border: 0; + min-width: 0; } + #ex-debug-toolbar legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; } + #ex-debug-toolbar label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; } + #ex-debug-toolbar input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + #ex-debug-toolbar input[type="radio"], + #ex-debug-toolbar input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; } + #ex-debug-toolbar input[type="file"] { + display: block; } + #ex-debug-toolbar input[type="range"] { + display: block; + width: 100%; } + #ex-debug-toolbar select[multiple], + #ex-debug-toolbar select[size] { + height: auto; } + #ex-debug-toolbar input[type="file"]:focus, + #ex-debug-toolbar input[type="radio"]:focus, + #ex-debug-toolbar input[type="checkbox"]:focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + #ex-debug-toolbar output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857; + color: #555555; } + #ex-debug-toolbar .form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857; + color: #555555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + 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 0.15s, box-shadow ease-in-out 0.15s; + -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; } + #ex-debug-toolbar .form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); } + #ex-debug-toolbar .form-control::-moz-placeholder { + color: #999; + opacity: 1; } + #ex-debug-toolbar .form-control:-ms-input-placeholder { + color: #999; } + #ex-debug-toolbar .form-control::-webkit-input-placeholder { + color: #999; } + #ex-debug-toolbar .form-control::-ms-expand { + border: 0; + background-color: transparent; } + #ex-debug-toolbar .form-control[disabled], #ex-debug-toolbar .form-control[readonly], + fieldset[disabled] #ex-debug-toolbar .form-control { + background-color: #eeeeee; + opacity: 1; } + #ex-debug-toolbar .form-control[disabled], + fieldset[disabled] #ex-debug-toolbar .form-control { + cursor: not-allowed; } + #ex-debug-toolbar textarea.form-control { + height: auto; } + #ex-debug-toolbar input[type="search"] { + -webkit-appearance: none; } + @media screen and (-webkit-min-device-pixel-ratio: 0) { + #ex-debug-toolbar input[type="date"].form-control, + #ex-debug-toolbar input[type="time"].form-control, + #ex-debug-toolbar input[type="datetime-local"].form-control, + #ex-debug-toolbar input[type="month"].form-control { + line-height: 34px; } + #ex-debug-toolbar input[type="date"].input-sm, #ex-debug-toolbar .input-group-sm > input[type="date"].form-control, #ex-debug-toolbar .input-group-sm > input[type="date"].input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > input[type="date"].btn, + .input-group-sm #ex-debug-toolbar input[type="date"], + #ex-debug-toolbar input[type="time"].input-sm, #ex-debug-toolbar .input-group-sm > input[type="time"].form-control, #ex-debug-toolbar .input-group-sm > input[type="time"].input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > input[type="time"].btn, + .input-group-sm + #ex-debug-toolbar input[type="time"], + #ex-debug-toolbar input[type="datetime-local"].input-sm, #ex-debug-toolbar .input-group-sm > input[type="datetime-local"].form-control, #ex-debug-toolbar .input-group-sm > input[type="datetime-local"].input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > input[type="datetime-local"].btn, + .input-group-sm + #ex-debug-toolbar input[type="datetime-local"], + #ex-debug-toolbar input[type="month"].input-sm, #ex-debug-toolbar .input-group-sm > input[type="month"].form-control, #ex-debug-toolbar .input-group-sm > input[type="month"].input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > input[type="month"].btn, + .input-group-sm + #ex-debug-toolbar input[type="month"] { + line-height: 30px; } + #ex-debug-toolbar input[type="date"].input-lg, #ex-debug-toolbar .input-group-lg > input[type="date"].form-control, #ex-debug-toolbar .input-group-lg > input[type="date"].input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > input[type="date"].btn, + .input-group-lg #ex-debug-toolbar input[type="date"], + #ex-debug-toolbar input[type="time"].input-lg, #ex-debug-toolbar .input-group-lg > input[type="time"].form-control, #ex-debug-toolbar .input-group-lg > input[type="time"].input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > input[type="time"].btn, + .input-group-lg + #ex-debug-toolbar input[type="time"], + #ex-debug-toolbar input[type="datetime-local"].input-lg, #ex-debug-toolbar .input-group-lg > input[type="datetime-local"].form-control, #ex-debug-toolbar .input-group-lg > input[type="datetime-local"].input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > input[type="datetime-local"].btn, + .input-group-lg + #ex-debug-toolbar input[type="datetime-local"], + #ex-debug-toolbar input[type="month"].input-lg, #ex-debug-toolbar .input-group-lg > input[type="month"].form-control, #ex-debug-toolbar .input-group-lg > input[type="month"].input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > input[type="month"].btn, + .input-group-lg + #ex-debug-toolbar input[type="month"] { + line-height: 46px; } } + #ex-debug-toolbar .form-group { + margin-bottom: 15px; } + #ex-debug-toolbar .radio, + #ex-debug-toolbar .checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; } + #ex-debug-toolbar .radio label, + #ex-debug-toolbar .checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; } + #ex-debug-toolbar .radio input[type="radio"], + #ex-debug-toolbar .radio-inline input[type="radio"], + #ex-debug-toolbar .checkbox input[type="checkbox"], + #ex-debug-toolbar .checkbox-inline input[type="checkbox"] { + position: absolute; + margin-left: -20px; + margin-top: 4px \9; } + #ex-debug-toolbar .radio + .radio, + #ex-debug-toolbar .checkbox + .checkbox { + margin-top: -5px; } + #ex-debug-toolbar .radio-inline, + #ex-debug-toolbar .checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + vertical-align: middle; + font-weight: normal; + cursor: pointer; } + #ex-debug-toolbar .radio-inline + .radio-inline, + #ex-debug-toolbar .checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; } + #ex-debug-toolbar input[type="radio"][disabled], #ex-debug-toolbar input[type="radio"].disabled, + fieldset[disabled] #ex-debug-toolbar input[type="radio"], + #ex-debug-toolbar input[type="checkbox"][disabled], + #ex-debug-toolbar input[type="checkbox"].disabled, + fieldset[disabled] + #ex-debug-toolbar input[type="checkbox"] { + cursor: not-allowed; } + #ex-debug-toolbar .radio-inline.disabled, + fieldset[disabled] #ex-debug-toolbar .radio-inline, + #ex-debug-toolbar .checkbox-inline.disabled, + fieldset[disabled] + #ex-debug-toolbar .checkbox-inline { + cursor: not-allowed; } + #ex-debug-toolbar .radio.disabled label, + fieldset[disabled] #ex-debug-toolbar .radio label, + #ex-debug-toolbar .checkbox.disabled label, + fieldset[disabled] + #ex-debug-toolbar .checkbox label { + cursor: not-allowed; } + #ex-debug-toolbar .form-control-static { + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; + min-height: 34px; } + #ex-debug-toolbar .form-control-static.input-lg, #ex-debug-toolbar .input-group-lg > .form-control-static.form-control, #ex-debug-toolbar .input-group-lg > .form-control-static.input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > .form-control-static.btn, #ex-debug-toolbar .form-control-static.input-sm, #ex-debug-toolbar .input-group-sm > .form-control-static.form-control, #ex-debug-toolbar .input-group-sm > .form-control-static.input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > .form-control-static.btn { + padding-left: 0; + padding-right: 0; } + #ex-debug-toolbar .input-sm, #ex-debug-toolbar .input-group-sm > .form-control, #ex-debug-toolbar .input-group-sm > .input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + #ex-debug-toolbar select.input-sm, #ex-debug-toolbar .input-group-sm > select.form-control, #ex-debug-toolbar .input-group-sm > select.input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > select.btn { + height: 30px; + line-height: 30px; } + #ex-debug-toolbar textarea.input-sm, #ex-debug-toolbar .input-group-sm > textarea.form-control, #ex-debug-toolbar .input-group-sm > textarea.input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > textarea.btn, + #ex-debug-toolbar select[multiple].input-sm, #ex-debug-toolbar .input-group-sm > select[multiple].form-control, #ex-debug-toolbar .input-group-sm > select[multiple].input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > select[multiple].btn { + height: auto; } + #ex-debug-toolbar .form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + #ex-debug-toolbar .form-group-sm select.form-control { + height: 30px; + line-height: 30px; } + #ex-debug-toolbar .form-group-sm textarea.form-control, + #ex-debug-toolbar .form-group-sm select[multiple].form-control { + height: auto; } + #ex-debug-toolbar .form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 6px 10px; + font-size: 12px; + line-height: 1.5; } + #ex-debug-toolbar .input-lg, #ex-debug-toolbar .input-group-lg > .form-control, #ex-debug-toolbar .input-group-lg > .input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33333; + border-radius: 6px; } + #ex-debug-toolbar select.input-lg, #ex-debug-toolbar .input-group-lg > select.form-control, #ex-debug-toolbar .input-group-lg > select.input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > select.btn { + height: 46px; + line-height: 46px; } + #ex-debug-toolbar textarea.input-lg, #ex-debug-toolbar .input-group-lg > textarea.form-control, #ex-debug-toolbar .input-group-lg > textarea.input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > textarea.btn, + #ex-debug-toolbar select[multiple].input-lg, #ex-debug-toolbar .input-group-lg > select[multiple].form-control, #ex-debug-toolbar .input-group-lg > select[multiple].input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > select[multiple].btn { + height: auto; } + #ex-debug-toolbar .form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33333; + border-radius: 6px; } + #ex-debug-toolbar .form-group-lg select.form-control { + height: 46px; + line-height: 46px; } + #ex-debug-toolbar .form-group-lg textarea.form-control, + #ex-debug-toolbar .form-group-lg select[multiple].form-control { + height: auto; } + #ex-debug-toolbar .form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 11px 16px; + font-size: 18px; + line-height: 1.33333; } + #ex-debug-toolbar .has-feedback { + position: relative; } + #ex-debug-toolbar .has-feedback .form-control { + padding-right: 42.5px; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .input-lg + .form-control-feedback, #ex-debug-toolbar .input-group-lg > .form-control + .form-control-feedback, #ex-debug-toolbar .input-group-lg > .input-group-addon + .form-control-feedback, #ex-debug-toolbar .input-group-lg > .input-group-btn > .btn + .form-control-feedback, + #ex-debug-toolbar .input-group-lg + .form-control-feedback, + #ex-debug-toolbar .form-group-lg .form-control + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; } + #ex-debug-toolbar .input-sm + .form-control-feedback, #ex-debug-toolbar .input-group-sm > .form-control + .form-control-feedback, #ex-debug-toolbar .input-group-sm > .input-group-addon + .form-control-feedback, #ex-debug-toolbar .input-group-sm > .input-group-btn > .btn + .form-control-feedback, + #ex-debug-toolbar .input-group-sm + .form-control-feedback, + #ex-debug-toolbar .form-group-sm .form-control + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; } + #ex-debug-toolbar .has-success .help-block, + #ex-debug-toolbar .has-success .control-label, + #ex-debug-toolbar .has-success .radio, + #ex-debug-toolbar .has-success .checkbox, + #ex-debug-toolbar .has-success .radio-inline, + #ex-debug-toolbar .has-success .checkbox-inline, + #ex-debug-toolbar .has-success.radio label, + #ex-debug-toolbar .has-success.checkbox label, + #ex-debug-toolbar .has-success.radio-inline label, + #ex-debug-toolbar .has-success.checkbox-inline label { + color: #3c763d; } + #ex-debug-toolbar .has-success .form-control { + border-color: #3c763d; + -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); } + #ex-debug-toolbar .has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168; } + #ex-debug-toolbar .has-success .input-group-addon { + color: #3c763d; + border-color: #3c763d; + background-color: #dff0d8; } + #ex-debug-toolbar .has-success .form-control-feedback { + color: #3c763d; } + #ex-debug-toolbar .has-warning .help-block, + #ex-debug-toolbar .has-warning .control-label, + #ex-debug-toolbar .has-warning .radio, + #ex-debug-toolbar .has-warning .checkbox, + #ex-debug-toolbar .has-warning .radio-inline, + #ex-debug-toolbar .has-warning .checkbox-inline, + #ex-debug-toolbar .has-warning.radio label, + #ex-debug-toolbar .has-warning.checkbox label, + #ex-debug-toolbar .has-warning.radio-inline label, + #ex-debug-toolbar .has-warning.checkbox-inline label { + color: #8a6d3b; } + #ex-debug-toolbar .has-warning .form-control { + border-color: #8a6d3b; + -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); } + #ex-debug-toolbar .has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b; } + #ex-debug-toolbar .has-warning .input-group-addon { + color: #8a6d3b; + border-color: #8a6d3b; + background-color: #fcf8e3; } + #ex-debug-toolbar .has-warning .form-control-feedback { + color: #8a6d3b; } + #ex-debug-toolbar .has-error .help-block, + #ex-debug-toolbar .has-error .control-label, + #ex-debug-toolbar .has-error .radio, + #ex-debug-toolbar .has-error .checkbox, + #ex-debug-toolbar .has-error .radio-inline, + #ex-debug-toolbar .has-error .checkbox-inline, + #ex-debug-toolbar .has-error.radio label, + #ex-debug-toolbar .has-error.checkbox label, + #ex-debug-toolbar .has-error.radio-inline label, + #ex-debug-toolbar .has-error.checkbox-inline label { + color: #a94442; } + #ex-debug-toolbar .has-error .form-control { + border-color: #a94442; + -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); } + #ex-debug-toolbar .has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483; } + #ex-debug-toolbar .has-error .input-group-addon { + color: #a94442; + border-color: #a94442; + background-color: #f2dede; } + #ex-debug-toolbar .has-error .form-control-feedback { + color: #a94442; } + #ex-debug-toolbar .has-feedback label ~ .form-control-feedback { + top: 25px; } + #ex-debug-toolbar .has-feedback label.sr-only ~ .form-control-feedback { + top: 0; } + #ex-debug-toolbar .help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; } + @media (min-width: 768px) { + #ex-debug-toolbar .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; } + #ex-debug-toolbar .form-inline .form-control-static { + display: inline-block; } + #ex-debug-toolbar .form-inline .input-group { + display: inline-table; + vertical-align: middle; } + #ex-debug-toolbar .form-inline .input-group .input-group-addon, + #ex-debug-toolbar .form-inline .input-group .input-group-btn, + #ex-debug-toolbar .form-inline .input-group .form-control { + width: auto; } + #ex-debug-toolbar .form-inline .input-group > .form-control { + width: 100%; } + #ex-debug-toolbar .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .form-inline .radio, + #ex-debug-toolbar .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .form-inline .radio label, + #ex-debug-toolbar .form-inline .checkbox label { + padding-left: 0; } + #ex-debug-toolbar .form-inline .radio input[type="radio"], + #ex-debug-toolbar .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; } + #ex-debug-toolbar .form-inline .has-feedback .form-control-feedback { + top: 0; } } + #ex-debug-toolbar .form-horizontal .radio, + #ex-debug-toolbar .form-horizontal .checkbox, + #ex-debug-toolbar .form-horizontal .radio-inline, + #ex-debug-toolbar .form-horizontal .checkbox-inline { + margin-top: 0; + margin-bottom: 0; + padding-top: 7px; } + #ex-debug-toolbar .form-horizontal .radio, + #ex-debug-toolbar .form-horizontal .checkbox { + min-height: 27px; } + #ex-debug-toolbar .form-horizontal .form-group { + margin-left: -15px; + margin-right: -15px; } + #ex-debug-toolbar .form-horizontal .form-group:before, #ex-debug-toolbar .form-horizontal .form-group:after { + content: " "; + display: table; } + #ex-debug-toolbar .form-horizontal .form-group:after { + clear: both; } + @media (min-width: 768px) { + #ex-debug-toolbar .form-horizontal .control-label { + text-align: right; + margin-bottom: 0; + padding-top: 7px; } } + #ex-debug-toolbar .form-horizontal .has-feedback .form-control-feedback { + right: 15px; } + @media (min-width: 768px) { + #ex-debug-toolbar .form-horizontal .form-group-lg .control-label { + padding-top: 11px; + font-size: 18px; } } + @media (min-width: 768px) { + #ex-debug-toolbar .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + font-size: 12px; } } + #ex-debug-toolbar .btn { + display: inline-block; + margin-bottom: 0; + font-weight: normal; + text-align: center; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + background-image: none; + border: 1px solid transparent; + white-space: nowrap; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + #ex-debug-toolbar .btn:focus, #ex-debug-toolbar .btn.focus, #ex-debug-toolbar .btn:active:focus, #ex-debug-toolbar .btn:active.focus, #ex-debug-toolbar .btn.active:focus, #ex-debug-toolbar .btn.active.focus { + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + #ex-debug-toolbar .btn:hover, #ex-debug-toolbar .btn:focus, #ex-debug-toolbar .btn.focus { + color: #333; + text-decoration: none; } + #ex-debug-toolbar .btn:active, #ex-debug-toolbar .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); } + #ex-debug-toolbar .btn.disabled, #ex-debug-toolbar .btn[disabled], + fieldset[disabled] #ex-debug-toolbar .btn { + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; } + #ex-debug-toolbar a.btn.disabled, #ex-debug-toolbar .navbar-nav.nav > li > span.btn.disabled, + fieldset[disabled] #ex-debug-toolbar a.btn, + fieldset[disabled] #ex-debug-toolbar .navbar-nav.nav > li > span.btn { + pointer-events: none; } + #ex-debug-toolbar .btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; } + #ex-debug-toolbar .btn-default:focus, #ex-debug-toolbar .btn-default.focus { + color: #333; + background-color: #e6e6e6; + border-color: #8c8c8c; } + #ex-debug-toolbar .btn-default:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; } + #ex-debug-toolbar .btn-default:active, #ex-debug-toolbar .btn-default.active, + .open > #ex-debug-toolbar .btn-default.dropdown-toggle { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; } + #ex-debug-toolbar .btn-default:active:hover, #ex-debug-toolbar .btn-default:active:focus, #ex-debug-toolbar .btn-default:active.focus, #ex-debug-toolbar .btn-default.active:hover, #ex-debug-toolbar .btn-default.active:focus, #ex-debug-toolbar .btn-default.active.focus, + .open > #ex-debug-toolbar .btn-default.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-default.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-default.dropdown-toggle.focus { + color: #333; + background-color: #d4d4d4; + border-color: #8c8c8c; } + #ex-debug-toolbar .btn-default:active, #ex-debug-toolbar .btn-default.active, + .open > #ex-debug-toolbar .btn-default.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-default.disabled:hover, #ex-debug-toolbar .btn-default.disabled:focus, #ex-debug-toolbar .btn-default.disabled.focus, #ex-debug-toolbar .btn-default[disabled]:hover, #ex-debug-toolbar .btn-default[disabled]:focus, #ex-debug-toolbar .btn-default[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-default:hover, + fieldset[disabled] #ex-debug-toolbar .btn-default:focus, + fieldset[disabled] #ex-debug-toolbar .btn-default.focus { + background-color: #fff; + border-color: #ccc; } + #ex-debug-toolbar .btn-default .badge { + color: #fff; + background-color: #333; } + #ex-debug-toolbar .btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; } + #ex-debug-toolbar .btn-primary:focus, #ex-debug-toolbar .btn-primary.focus { + color: #fff; + background-color: #286090; + border-color: #122b40; } + #ex-debug-toolbar .btn-primary:hover { + color: #fff; + background-color: #286090; + border-color: #204d74; } + #ex-debug-toolbar .btn-primary:active, #ex-debug-toolbar .btn-primary.active, + .open > #ex-debug-toolbar .btn-primary.dropdown-toggle { + color: #fff; + background-color: #286090; + border-color: #204d74; } + #ex-debug-toolbar .btn-primary:active:hover, #ex-debug-toolbar .btn-primary:active:focus, #ex-debug-toolbar .btn-primary:active.focus, #ex-debug-toolbar .btn-primary.active:hover, #ex-debug-toolbar .btn-primary.active:focus, #ex-debug-toolbar .btn-primary.active.focus, + .open > #ex-debug-toolbar .btn-primary.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-primary.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-primary.dropdown-toggle.focus { + color: #fff; + background-color: #204d74; + border-color: #122b40; } + #ex-debug-toolbar .btn-primary:active, #ex-debug-toolbar .btn-primary.active, + .open > #ex-debug-toolbar .btn-primary.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-primary.disabled:hover, #ex-debug-toolbar .btn-primary.disabled:focus, #ex-debug-toolbar .btn-primary.disabled.focus, #ex-debug-toolbar .btn-primary[disabled]:hover, #ex-debug-toolbar .btn-primary[disabled]:focus, #ex-debug-toolbar .btn-primary[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-primary:hover, + fieldset[disabled] #ex-debug-toolbar .btn-primary:focus, + fieldset[disabled] #ex-debug-toolbar .btn-primary.focus { + background-color: #337ab7; + border-color: #2e6da4; } + #ex-debug-toolbar .btn-primary .badge { + color: #337ab7; + background-color: #fff; } + #ex-debug-toolbar .btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; } + #ex-debug-toolbar .btn-success:focus, #ex-debug-toolbar .btn-success.focus { + color: #fff; + background-color: #449d44; + border-color: #255625; } + #ex-debug-toolbar .btn-success:hover { + color: #fff; + background-color: #449d44; + border-color: #398439; } + #ex-debug-toolbar .btn-success:active, #ex-debug-toolbar .btn-success.active, + .open > #ex-debug-toolbar .btn-success.dropdown-toggle { + color: #fff; + background-color: #449d44; + border-color: #398439; } + #ex-debug-toolbar .btn-success:active:hover, #ex-debug-toolbar .btn-success:active:focus, #ex-debug-toolbar .btn-success:active.focus, #ex-debug-toolbar .btn-success.active:hover, #ex-debug-toolbar .btn-success.active:focus, #ex-debug-toolbar .btn-success.active.focus, + .open > #ex-debug-toolbar .btn-success.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-success.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-success.dropdown-toggle.focus { + color: #fff; + background-color: #398439; + border-color: #255625; } + #ex-debug-toolbar .btn-success:active, #ex-debug-toolbar .btn-success.active, + .open > #ex-debug-toolbar .btn-success.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-success.disabled:hover, #ex-debug-toolbar .btn-success.disabled:focus, #ex-debug-toolbar .btn-success.disabled.focus, #ex-debug-toolbar .btn-success[disabled]:hover, #ex-debug-toolbar .btn-success[disabled]:focus, #ex-debug-toolbar .btn-success[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-success:hover, + fieldset[disabled] #ex-debug-toolbar .btn-success:focus, + fieldset[disabled] #ex-debug-toolbar .btn-success.focus { + background-color: #5cb85c; + border-color: #4cae4c; } + #ex-debug-toolbar .btn-success .badge { + color: #5cb85c; + background-color: #fff; } + #ex-debug-toolbar .btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; } + #ex-debug-toolbar .btn-info:focus, #ex-debug-toolbar .btn-info.focus { + color: #fff; + background-color: #31b0d5; + border-color: #1b6d85; } + #ex-debug-toolbar .btn-info:hover { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; } + #ex-debug-toolbar .btn-info:active, #ex-debug-toolbar .btn-info.active, + .open > #ex-debug-toolbar .btn-info.dropdown-toggle { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; } + #ex-debug-toolbar .btn-info:active:hover, #ex-debug-toolbar .btn-info:active:focus, #ex-debug-toolbar .btn-info:active.focus, #ex-debug-toolbar .btn-info.active:hover, #ex-debug-toolbar .btn-info.active:focus, #ex-debug-toolbar .btn-info.active.focus, + .open > #ex-debug-toolbar .btn-info.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-info.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-info.dropdown-toggle.focus { + color: #fff; + background-color: #269abc; + border-color: #1b6d85; } + #ex-debug-toolbar .btn-info:active, #ex-debug-toolbar .btn-info.active, + .open > #ex-debug-toolbar .btn-info.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-info.disabled:hover, #ex-debug-toolbar .btn-info.disabled:focus, #ex-debug-toolbar .btn-info.disabled.focus, #ex-debug-toolbar .btn-info[disabled]:hover, #ex-debug-toolbar .btn-info[disabled]:focus, #ex-debug-toolbar .btn-info[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-info:hover, + fieldset[disabled] #ex-debug-toolbar .btn-info:focus, + fieldset[disabled] #ex-debug-toolbar .btn-info.focus { + background-color: #5bc0de; + border-color: #46b8da; } + #ex-debug-toolbar .btn-info .badge { + color: #5bc0de; + background-color: #fff; } + #ex-debug-toolbar .btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; } + #ex-debug-toolbar .btn-warning:focus, #ex-debug-toolbar .btn-warning.focus { + color: #fff; + background-color: #ec971f; + border-color: #985f0d; } + #ex-debug-toolbar .btn-warning:hover { + color: #fff; + background-color: #ec971f; + border-color: #d58512; } + #ex-debug-toolbar .btn-warning:active, #ex-debug-toolbar .btn-warning.active, + .open > #ex-debug-toolbar .btn-warning.dropdown-toggle { + color: #fff; + background-color: #ec971f; + border-color: #d58512; } + #ex-debug-toolbar .btn-warning:active:hover, #ex-debug-toolbar .btn-warning:active:focus, #ex-debug-toolbar .btn-warning:active.focus, #ex-debug-toolbar .btn-warning.active:hover, #ex-debug-toolbar .btn-warning.active:focus, #ex-debug-toolbar .btn-warning.active.focus, + .open > #ex-debug-toolbar .btn-warning.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-warning.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-warning.dropdown-toggle.focus { + color: #fff; + background-color: #d58512; + border-color: #985f0d; } + #ex-debug-toolbar .btn-warning:active, #ex-debug-toolbar .btn-warning.active, + .open > #ex-debug-toolbar .btn-warning.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-warning.disabled:hover, #ex-debug-toolbar .btn-warning.disabled:focus, #ex-debug-toolbar .btn-warning.disabled.focus, #ex-debug-toolbar .btn-warning[disabled]:hover, #ex-debug-toolbar .btn-warning[disabled]:focus, #ex-debug-toolbar .btn-warning[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-warning:hover, + fieldset[disabled] #ex-debug-toolbar .btn-warning:focus, + fieldset[disabled] #ex-debug-toolbar .btn-warning.focus { + background-color: #f0ad4e; + border-color: #eea236; } + #ex-debug-toolbar .btn-warning .badge { + color: #f0ad4e; + background-color: #fff; } + #ex-debug-toolbar .btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; } + #ex-debug-toolbar .btn-danger:focus, #ex-debug-toolbar .btn-danger.focus { + color: #fff; + background-color: #c9302c; + border-color: #761c19; } + #ex-debug-toolbar .btn-danger:hover { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; } + #ex-debug-toolbar .btn-danger:active, #ex-debug-toolbar .btn-danger.active, + .open > #ex-debug-toolbar .btn-danger.dropdown-toggle { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; } + #ex-debug-toolbar .btn-danger:active:hover, #ex-debug-toolbar .btn-danger:active:focus, #ex-debug-toolbar .btn-danger:active.focus, #ex-debug-toolbar .btn-danger.active:hover, #ex-debug-toolbar .btn-danger.active:focus, #ex-debug-toolbar .btn-danger.active.focus, + .open > #ex-debug-toolbar .btn-danger.dropdown-toggle:hover, + .open > #ex-debug-toolbar .btn-danger.dropdown-toggle:focus, + .open > #ex-debug-toolbar .btn-danger.dropdown-toggle.focus { + color: #fff; + background-color: #ac2925; + border-color: #761c19; } + #ex-debug-toolbar .btn-danger:active, #ex-debug-toolbar .btn-danger.active, + .open > #ex-debug-toolbar .btn-danger.dropdown-toggle { + background-image: none; } + #ex-debug-toolbar .btn-danger.disabled:hover, #ex-debug-toolbar .btn-danger.disabled:focus, #ex-debug-toolbar .btn-danger.disabled.focus, #ex-debug-toolbar .btn-danger[disabled]:hover, #ex-debug-toolbar .btn-danger[disabled]:focus, #ex-debug-toolbar .btn-danger[disabled].focus, + fieldset[disabled] #ex-debug-toolbar .btn-danger:hover, + fieldset[disabled] #ex-debug-toolbar .btn-danger:focus, + fieldset[disabled] #ex-debug-toolbar .btn-danger.focus { + background-color: #d9534f; + border-color: #d43f3a; } + #ex-debug-toolbar .btn-danger .badge { + color: #d9534f; + background-color: #fff; } + #ex-debug-toolbar .btn-link { + color: #337ab7; + font-weight: normal; + border-radius: 0; } + #ex-debug-toolbar .btn-link, #ex-debug-toolbar .btn-link:active, #ex-debug-toolbar .btn-link.active, #ex-debug-toolbar .btn-link[disabled], + fieldset[disabled] #ex-debug-toolbar .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; } + #ex-debug-toolbar .btn-link, #ex-debug-toolbar .btn-link:hover, #ex-debug-toolbar .btn-link:focus, #ex-debug-toolbar .btn-link:active { + border-color: transparent; } + #ex-debug-toolbar .btn-link:hover, #ex-debug-toolbar .btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; } + #ex-debug-toolbar .btn-link[disabled]:hover, #ex-debug-toolbar .btn-link[disabled]:focus, + fieldset[disabled] #ex-debug-toolbar .btn-link:hover, + fieldset[disabled] #ex-debug-toolbar .btn-link:focus { + color: #777777; + text-decoration: none; } + #ex-debug-toolbar .btn-lg, #ex-debug-toolbar .btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33333; + border-radius: 6px; } + #ex-debug-toolbar .btn-sm, #ex-debug-toolbar .btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + #ex-debug-toolbar .btn-xs, #ex-debug-toolbar .btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + #ex-debug-toolbar .btn-block { + display: block; + width: 100%; } + #ex-debug-toolbar .btn-block + .btn-block { + margin-top: 5px; } + #ex-debug-toolbar input[type="submit"].btn-block, + #ex-debug-toolbar input[type="reset"].btn-block, + #ex-debug-toolbar input[type="button"].btn-block { + width: 100%; } + #ex-debug-toolbar .fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + -o-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; } + #ex-debug-toolbar .fade.in { + opacity: 1; } + #ex-debug-toolbar .collapse { + display: none; } + #ex-debug-toolbar .collapse.in { + display: block; } + #ex-debug-toolbar tr.collapse.in { + display: table-row; } + #ex-debug-toolbar tbody.collapse.in { + display: table-row-group; } + #ex-debug-toolbar .collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-property: height, visibility; + transition-property: height, visibility; + -webkit-transition-duration: 0.35s; + transition-duration: 0.35s; + -webkit-transition-timing-function: ease; + transition-timing-function: ease; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .dropup, + #ex-debug-toolbar .dropdown { + position: relative; } + #ex-debug-toolbar .dropdown-toggle:focus { + outline: 0; } + #ex-debug-toolbar .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: #fff; + border: 1px solid #ccc; + 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); + background-clip: padding-box; } + #ex-debug-toolbar .dropdown-menu.pull-right { + right: 0; + left: auto; } + #ex-debug-toolbar .dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + #ex-debug-toolbar .dropdown-menu > li > a, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li > span { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857; + color: #333333; + white-space: nowrap; } + #ex-debug-toolbar .dropdown-menu > li > a:hover, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li > span:hover, #ex-debug-toolbar .dropdown-menu > li > a:focus, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li > span:focus { + text-decoration: none; + color: #262626; + background-color: #f5f5f5; } + #ex-debug-toolbar .dropdown-menu > .active > a, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.active > span, #ex-debug-toolbar .dropdown-menu > .active > a:hover, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.active > span:hover, #ex-debug-toolbar .dropdown-menu > .active > a:focus, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.active > span:focus { + color: #fff; + text-decoration: none; + outline: 0; + background-color: #337ab7; } + #ex-debug-toolbar .dropdown-menu > .disabled > a, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.disabled > span, #ex-debug-toolbar .dropdown-menu > .disabled > a:hover, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.disabled > span:hover, #ex-debug-toolbar .dropdown-menu > .disabled > a:focus, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.disabled > span:focus { + color: #777777; } + #ex-debug-toolbar .dropdown-menu > .disabled > a:hover, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.disabled > span:hover, #ex-debug-toolbar .dropdown-menu > .disabled > a:focus, #ex-debug-toolbar .navbar-nav.nav.dropdown-menu > li.disabled > span:focus { + text-decoration: none; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + cursor: not-allowed; } + #ex-debug-toolbar .open > .dropdown-menu { + display: block; } + #ex-debug-toolbar .open > a, #ex-debug-toolbar .navbar-nav.nav > li.open > span { + outline: 0; } + #ex-debug-toolbar .dropdown-menu-right { + left: auto; + right: 0; } + #ex-debug-toolbar .dropdown-menu-left { + left: 0; + right: auto; } + #ex-debug-toolbar .dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857; + color: #777777; + white-space: nowrap; } + #ex-debug-toolbar .dropdown-backdrop { + position: fixed; + left: 0; + right: 0; + bottom: 0; + top: 0; + z-index: 990; } + #ex-debug-toolbar .pull-right > .dropdown-menu { + right: 0; + left: auto; } + #ex-debug-toolbar .dropup .caret, + #ex-debug-toolbar .navbar-fixed-bottom .dropdown .caret { + border-top: 0; + border-bottom: 4px dashed; + border-bottom: 4px solid \9; + content: ""; } + #ex-debug-toolbar .dropup .dropdown-menu, + #ex-debug-toolbar .navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-right .dropdown-menu { + right: 0; + left: auto; } + #ex-debug-toolbar .navbar-right .dropdown-menu-left { + left: 0; + right: auto; } } + #ex-debug-toolbar .btn-group, + #ex-debug-toolbar .btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; } + #ex-debug-toolbar .btn-group > .btn, + #ex-debug-toolbar .btn-group-vertical > .btn { + position: relative; + float: left; } + #ex-debug-toolbar .btn-group > .btn:hover, #ex-debug-toolbar .btn-group > .btn:focus, #ex-debug-toolbar .btn-group > .btn:active, #ex-debug-toolbar .btn-group > .btn.active, + #ex-debug-toolbar .btn-group-vertical > .btn:hover, + #ex-debug-toolbar .btn-group-vertical > .btn:focus, + #ex-debug-toolbar .btn-group-vertical > .btn:active, + #ex-debug-toolbar .btn-group-vertical > .btn.active { + z-index: 2; } + #ex-debug-toolbar .btn-group .btn + .btn, + #ex-debug-toolbar .btn-group .btn + .btn-group, + #ex-debug-toolbar .btn-group .btn-group + .btn, + #ex-debug-toolbar .btn-group .btn-group + .btn-group { + margin-left: -1px; } + #ex-debug-toolbar .btn-toolbar { + margin-left: -5px; } + #ex-debug-toolbar .btn-toolbar:before, #ex-debug-toolbar .btn-toolbar:after { + content: " "; + display: table; } + #ex-debug-toolbar .btn-toolbar:after { + clear: both; } + #ex-debug-toolbar .btn-toolbar .btn, + #ex-debug-toolbar .btn-toolbar .btn-group, + #ex-debug-toolbar .btn-toolbar .input-group { + float: left; } + #ex-debug-toolbar .btn-toolbar > .btn, + #ex-debug-toolbar .btn-toolbar > .btn-group, + #ex-debug-toolbar .btn-toolbar > .input-group { + margin-left: 5px; } + #ex-debug-toolbar .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; } + #ex-debug-toolbar .btn-group > .btn:first-child { + margin-left: 0; } + #ex-debug-toolbar .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + #ex-debug-toolbar .btn-group > .btn:last-child:not(:first-child), + #ex-debug-toolbar .btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .btn-group > .btn-group { + float: left; } + #ex-debug-toolbar .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; } + #ex-debug-toolbar .btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, + #ex-debug-toolbar .btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + #ex-debug-toolbar .btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .btn-group .dropdown-toggle:active, + #ex-debug-toolbar .btn-group.open .dropdown-toggle { + outline: 0; } + #ex-debug-toolbar .btn-group > .btn + .dropdown-toggle { + padding-left: 8px; + padding-right: 8px; } + #ex-debug-toolbar .btn-group > .btn-lg + .dropdown-toggle, #ex-debug-toolbar .btn-group-lg.btn-group > .btn + .dropdown-toggle { + padding-left: 12px; + padding-right: 12px; } + #ex-debug-toolbar .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); } + #ex-debug-toolbar .btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; } + #ex-debug-toolbar .btn .caret { + margin-left: 0; } + #ex-debug-toolbar .btn-lg .caret, #ex-debug-toolbar .btn-group-lg > .btn .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; } + #ex-debug-toolbar .dropup .btn-lg .caret, #ex-debug-toolbar .dropup .btn-group-lg > .btn .caret { + border-width: 0 5px 5px; } + #ex-debug-toolbar .btn-group-vertical > .btn, + #ex-debug-toolbar .btn-group-vertical > .btn-group, + #ex-debug-toolbar .btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; } + #ex-debug-toolbar .btn-group-vertical > .btn-group:before, #ex-debug-toolbar .btn-group-vertical > .btn-group:after { + content: " "; + display: table; } + #ex-debug-toolbar .btn-group-vertical > .btn-group:after { + clear: both; } + #ex-debug-toolbar .btn-group-vertical > .btn-group > .btn { + float: none; } + #ex-debug-toolbar .btn-group-vertical > .btn + .btn, + #ex-debug-toolbar .btn-group-vertical > .btn + .btn-group, + #ex-debug-toolbar .btn-group-vertical > .btn-group + .btn, + #ex-debug-toolbar .btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; } + #ex-debug-toolbar .btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; } + #ex-debug-toolbar .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, + #ex-debug-toolbar .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + #ex-debug-toolbar .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; } + #ex-debug-toolbar .btn-group-justified > .btn, + #ex-debug-toolbar .btn-group-justified > .btn-group { + float: none; + display: table-cell; + width: 1%; } + #ex-debug-toolbar .btn-group-justified > .btn-group .btn { + width: 100%; } + #ex-debug-toolbar .btn-group-justified > .btn-group .dropdown-menu { + left: auto; } + #ex-debug-toolbar [data-toggle="buttons"] > .btn input[type="radio"], + #ex-debug-toolbar [data-toggle="buttons"] > .btn input[type="checkbox"], + #ex-debug-toolbar [data-toggle="buttons"] > .btn-group > .btn input[type="radio"], + #ex-debug-toolbar [data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; } + #ex-debug-toolbar .input-group { + position: relative; + display: table; + border-collapse: separate; } + #ex-debug-toolbar .input-group[class*="col-"] { + float: none; + padding-left: 0; + padding-right: 0; } + #ex-debug-toolbar .input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; } + #ex-debug-toolbar .input-group .form-control:focus { + z-index: 3; } + #ex-debug-toolbar .input-group-addon, + #ex-debug-toolbar .input-group-btn, + #ex-debug-toolbar .input-group .form-control { + display: table-cell; } + #ex-debug-toolbar .input-group-addon:not(:first-child):not(:last-child), + #ex-debug-toolbar .input-group-btn:not(:first-child):not(:last-child), + #ex-debug-toolbar .input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; } + #ex-debug-toolbar .input-group-addon, + #ex-debug-toolbar .input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; } + #ex-debug-toolbar .input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555555; + text-align: center; + background-color: #eeeeee; + border: 1px solid #ccc; + border-radius: 4px; } + #ex-debug-toolbar .input-group-addon.input-sm, #ex-debug-toolbar .input-group-sm > .input-group-addon, #ex-debug-toolbar .input-group-sm > .input-group-btn > .input-group-addon.btn { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; } + #ex-debug-toolbar .input-group-addon.input-lg, #ex-debug-toolbar .input-group-lg > .input-group-addon, #ex-debug-toolbar .input-group-lg > .input-group-btn > .input-group-addon.btn { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; } + #ex-debug-toolbar .input-group-addon input[type="radio"], + #ex-debug-toolbar .input-group-addon input[type="checkbox"] { + margin-top: 0; } + #ex-debug-toolbar .input-group .form-control:first-child, + #ex-debug-toolbar .input-group-addon:first-child, + #ex-debug-toolbar .input-group-btn:first-child > .btn, + #ex-debug-toolbar .input-group-btn:first-child > .btn-group > .btn, + #ex-debug-toolbar .input-group-btn:first-child > .dropdown-toggle, + #ex-debug-toolbar .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), + #ex-debug-toolbar .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-top-right-radius: 0; } + #ex-debug-toolbar .input-group-addon:first-child { + border-right: 0; } + #ex-debug-toolbar .input-group .form-control:last-child, + #ex-debug-toolbar .input-group-addon:last-child, + #ex-debug-toolbar .input-group-btn:last-child > .btn, + #ex-debug-toolbar .input-group-btn:last-child > .btn-group > .btn, + #ex-debug-toolbar .input-group-btn:last-child > .dropdown-toggle, + #ex-debug-toolbar .input-group-btn:first-child > .btn:not(:first-child), + #ex-debug-toolbar .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-bottom-left-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .input-group-addon:last-child { + border-left: 0; } + #ex-debug-toolbar .input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; } + #ex-debug-toolbar .input-group-btn > .btn { + position: relative; } + #ex-debug-toolbar .input-group-btn > .btn + .btn { + margin-left: -1px; } + #ex-debug-toolbar .input-group-btn > .btn:hover, #ex-debug-toolbar .input-group-btn > .btn:focus, #ex-debug-toolbar .input-group-btn > .btn:active { + z-index: 2; } + #ex-debug-toolbar .input-group-btn:first-child > .btn, + #ex-debug-toolbar .input-group-btn:first-child > .btn-group { + margin-right: -1px; } + #ex-debug-toolbar .input-group-btn:last-child > .btn, + #ex-debug-toolbar .input-group-btn:last-child > .btn-group { + z-index: 2; + margin-left: -1px; } + #ex-debug-toolbar .nav { + margin-bottom: 0; + padding-left: 0; + list-style: none; } + #ex-debug-toolbar .nav:before, #ex-debug-toolbar .nav:after { + content: " "; + display: table; } + #ex-debug-toolbar .nav:after { + clear: both; } + #ex-debug-toolbar .nav > li { + position: relative; + display: block; } + #ex-debug-toolbar .nav > li > a, #ex-debug-toolbar .navbar-nav.nav > li > span { + position: relative; + display: block; + padding: 10px 15px; } + #ex-debug-toolbar .nav > li > a:hover, #ex-debug-toolbar .navbar-nav.nav > li > span:hover, #ex-debug-toolbar .nav > li > a:focus, #ex-debug-toolbar .navbar-nav.nav > li > span:focus { + text-decoration: none; + background-color: #eeeeee; } + #ex-debug-toolbar .nav > li.disabled > a, #ex-debug-toolbar .navbar-nav.nav > li.disabled > span { + color: #777777; } + #ex-debug-toolbar .nav > li.disabled > a:hover, #ex-debug-toolbar .navbar-nav.nav > li.disabled > span:hover, #ex-debug-toolbar .nav > li.disabled > a:focus, #ex-debug-toolbar .navbar-nav.nav > li.disabled > span:focus { + color: #777777; + text-decoration: none; + background-color: transparent; + cursor: not-allowed; } + #ex-debug-toolbar .nav .open > a, #ex-debug-toolbar .navbar-nav.nav > li.open > span, #ex-debug-toolbar .nav .open > a:hover, #ex-debug-toolbar .navbar-nav.nav > li.open > span:hover, #ex-debug-toolbar .nav .open > a:focus, #ex-debug-toolbar .navbar-nav.nav > li.open > span:focus { + background-color: #eeeeee; + border-color: #337ab7; } + #ex-debug-toolbar .nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + #ex-debug-toolbar .nav > li > a > img, #ex-debug-toolbar .navbar-nav.nav > li > span > img { + max-width: none; } + #ex-debug-toolbar .nav-tabs { + border-bottom: 1px solid #ddd; } + #ex-debug-toolbar .nav-tabs > li { + float: left; + margin-bottom: -1px; } + #ex-debug-toolbar .nav-tabs > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs > li > span { + margin-right: 2px; + line-height: 1.42857; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; } + #ex-debug-toolbar .nav-tabs > li > a:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs > li > span:hover { + border-color: #eeeeee #eeeeee #ddd; } + #ex-debug-toolbar .nav-tabs > li.active > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs > li.active > span, #ex-debug-toolbar .nav-tabs > li.active > a:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs > li.active > span:hover, #ex-debug-toolbar .nav-tabs > li.active > a:focus, #ex-debug-toolbar .navbar-nav.nav.nav-tabs > li.active > span:focus { + color: #555555; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; + cursor: default; } + #ex-debug-toolbar .nav-pills > li { + float: left; } + #ex-debug-toolbar .nav-pills > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-pills > li > span { + border-radius: 4px; } + #ex-debug-toolbar .nav-pills > li + li { + margin-left: 2px; } + #ex-debug-toolbar .nav-pills > li.active > a, #ex-debug-toolbar .navbar-nav.nav.nav-pills > li.active > span, #ex-debug-toolbar .nav-pills > li.active > a:hover, #ex-debug-toolbar .navbar-nav.nav.nav-pills > li.active > span:hover, #ex-debug-toolbar .nav-pills > li.active > a:focus, #ex-debug-toolbar .navbar-nav.nav.nav-pills > li.active > span:focus { + color: #fff; + background-color: #337ab7; } + #ex-debug-toolbar .nav-stacked > li { + float: none; } + #ex-debug-toolbar .nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; } + #ex-debug-toolbar .nav-justified, #ex-debug-toolbar .nav-tabs.nav-justified { + width: 100%; } + #ex-debug-toolbar .nav-justified > li, #ex-debug-toolbar .nav-tabs.nav-justified > li { + float: none; } + #ex-debug-toolbar .nav-justified > li > a, #ex-debug-toolbar .nav-tabs.nav-justified > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-justified > li > span { + text-align: center; + margin-bottom: 5px; } + #ex-debug-toolbar .nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; } + @media (min-width: 768px) { + #ex-debug-toolbar .nav-justified > li, #ex-debug-toolbar .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; } + #ex-debug-toolbar .nav-justified > li > a, #ex-debug-toolbar .nav-tabs.nav-justified > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-justified > li > span { + margin-bottom: 0; } } + #ex-debug-toolbar .nav-tabs-justified, #ex-debug-toolbar .nav-tabs.nav-justified { + border-bottom: 0; } + #ex-debug-toolbar .nav-tabs-justified > li > a, #ex-debug-toolbar .nav-tabs.nav-justified > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li > span, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li > span { + margin-right: 0; + border-radius: 4px; } + #ex-debug-toolbar .nav-tabs-justified > .active > a, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span, + #ex-debug-toolbar .nav-tabs-justified > .active > a:hover, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span:hover, + #ex-debug-toolbar .nav-tabs-justified > .active > a:focus, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a:focus, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span:focus, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span:focus { + border: 1px solid #ddd; } + @media (min-width: 768px) { + #ex-debug-toolbar .nav-tabs-justified > li > a, #ex-debug-toolbar .nav-tabs.nav-justified > li > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li > span, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li > span { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; } + #ex-debug-toolbar .nav-tabs-justified > .active > a, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span, + #ex-debug-toolbar .nav-tabs-justified > .active > a:hover, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span:hover, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span:hover, + #ex-debug-toolbar .nav-tabs-justified > .active > a:focus, #ex-debug-toolbar .nav-tabs.nav-justified > .active > a:focus, #ex-debug-toolbar .navbar-nav.nav.nav-tabs-justified > li.active > span:focus, #ex-debug-toolbar .navbar-nav.nav.nav-tabs.nav-justified > li.active > span:focus { + border-bottom-color: #fff; } } + #ex-debug-toolbar .tab-content > .tab-pane { + display: none; } + #ex-debug-toolbar .tab-content > .active { + display: block; } + #ex-debug-toolbar .nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; } + #ex-debug-toolbar .navbar:before, #ex-debug-toolbar .navbar:after { + content: " "; + display: table; } + #ex-debug-toolbar .navbar:after { + clear: both; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar { + border-radius: 4px; } } + #ex-debug-toolbar .navbar-header:before, #ex-debug-toolbar .navbar-header:after { + content: " "; + display: table; } + #ex-debug-toolbar .navbar-header:after { + clear: both; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-header { + float: left; } } + #ex-debug-toolbar .navbar-collapse { + overflow-x: visible; + padding-right: 15px; + padding-left: 15px; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; } + #ex-debug-toolbar .navbar-collapse:before, #ex-debug-toolbar .navbar-collapse:after { + content: " "; + display: table; } + #ex-debug-toolbar .navbar-collapse:after { + clear: both; } + #ex-debug-toolbar .navbar-collapse.in { + overflow-y: auto; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; } + #ex-debug-toolbar .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; } + #ex-debug-toolbar .navbar-collapse.in { + overflow-y: visible; } + .navbar-fixed-top #ex-debug-toolbar .navbar-collapse, + .navbar-static-top #ex-debug-toolbar .navbar-collapse, + .navbar-fixed-bottom #ex-debug-toolbar .navbar-collapse { + padding-left: 0; + padding-right: 0; } } + #ex-debug-toolbar .navbar-fixed-top .navbar-collapse, + #ex-debug-toolbar .navbar-fixed-bottom .navbar-collapse { + max-height: 340px; } + @media (max-device-width: 480px) and (orientation: landscape) { + #ex-debug-toolbar .navbar-fixed-top .navbar-collapse, + #ex-debug-toolbar .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; } } + #ex-debug-toolbar .container > .navbar-header, + #ex-debug-toolbar .container > .navbar-collapse, + #ex-debug-toolbar .container-fluid > .navbar-header, + #ex-debug-toolbar .container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; } + @media (min-width: 768px) { + #ex-debug-toolbar .container > .navbar-header, + #ex-debug-toolbar .container > .navbar-collapse, + #ex-debug-toolbar .container-fluid > .navbar-header, + #ex-debug-toolbar .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; } } + #ex-debug-toolbar .navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-static-top { + border-radius: 0; } } + #ex-debug-toolbar .navbar-fixed-top, + #ex-debug-toolbar .navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-fixed-top, + #ex-debug-toolbar .navbar-fixed-bottom { + border-radius: 0; } } + #ex-debug-toolbar .navbar-fixed-top { + top: 0; + border-width: 0 0 1px; } + #ex-debug-toolbar .navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; } + #ex-debug-toolbar .navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; + height: 50px; } + #ex-debug-toolbar .navbar-brand:hover, #ex-debug-toolbar .navbar-brand:focus { + text-decoration: none; } + #ex-debug-toolbar .navbar-brand > img { + display: block; } + @media (min-width: 768px) { + .navbar > .container #ex-debug-toolbar .navbar-brand, + .navbar > .container-fluid #ex-debug-toolbar .navbar-brand { + margin-left: -15px; } } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .navbar-toggle:focus { + outline: 0; } + #ex-debug-toolbar .navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; } + #ex-debug-toolbar .navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-toggle { + display: none; } } + #ex-debug-toolbar .navbar-nav { + margin: 7.5px -15px; } + #ex-debug-toolbar .navbar-nav > li > a, #ex-debug-toolbar .navbar-nav.nav > li > span { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; } + @media (max-width: 767px) { + #ex-debug-toolbar .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; } + #ex-debug-toolbar .navbar-nav .open .dropdown-menu > li > a, #ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span, + #ex-debug-toolbar .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; } + #ex-debug-toolbar .navbar-nav .open .dropdown-menu > li > a, #ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span { + line-height: 20px; } + #ex-debug-toolbar .navbar-nav .open .dropdown-menu > li > a:hover, #ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:hover, #ex-debug-toolbar .navbar-nav .open .dropdown-menu > li > a:focus, #ex-debug-toolbar .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:focus { + background-image: none; } } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-nav { + float: left; + margin: 0; } + #ex-debug-toolbar .navbar-nav > li { + float: left; } + #ex-debug-toolbar .navbar-nav > li > a, #ex-debug-toolbar .navbar-nav.nav > li > span { + padding-top: 15px; + padding-bottom: 15px; } } + #ex-debug-toolbar .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: 8px; + margin-bottom: 8px; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; } + #ex-debug-toolbar .navbar-form .form-control-static { + display: inline-block; } + #ex-debug-toolbar .navbar-form .input-group { + display: inline-table; + vertical-align: middle; } + #ex-debug-toolbar .navbar-form .input-group .input-group-addon, + #ex-debug-toolbar .navbar-form .input-group .input-group-btn, + #ex-debug-toolbar .navbar-form .input-group .form-control { + width: auto; } + #ex-debug-toolbar .navbar-form .input-group > .form-control { + width: 100%; } + #ex-debug-toolbar .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .navbar-form .radio, + #ex-debug-toolbar .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; } + #ex-debug-toolbar .navbar-form .radio label, + #ex-debug-toolbar .navbar-form .checkbox label { + padding-left: 0; } + #ex-debug-toolbar .navbar-form .radio input[type="radio"], + #ex-debug-toolbar .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; } + #ex-debug-toolbar .navbar-form .has-feedback .form-control-feedback { + top: 0; } } + @media (max-width: 767px) { + #ex-debug-toolbar .navbar-form .form-group { + margin-bottom: 5px; } + #ex-debug-toolbar .navbar-form .form-group:last-child { + margin-bottom: 0; } } + @media (min-width: 768px) { + #ex-debug-toolbar .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; } } + #ex-debug-toolbar .navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .navbar-btn { + margin-top: 8px; + margin-bottom: 8px; } + #ex-debug-toolbar .navbar-btn.btn-sm, #ex-debug-toolbar .btn-group-sm > .navbar-btn.btn { + margin-top: 10px; + margin-bottom: 10px; } + #ex-debug-toolbar .navbar-btn.btn-xs, #ex-debug-toolbar .btn-group-xs > .navbar-btn.btn { + margin-top: 14px; + margin-bottom: 14px; } + #ex-debug-toolbar .navbar-text { + margin-top: 15px; + margin-bottom: 15px; } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-text { + float: left; + margin-left: 15px; + margin-right: 15px; } } + @media (min-width: 768px) { + #ex-debug-toolbar .navbar-left { + float: left !important; } + #ex-debug-toolbar .navbar-right { + float: right !important; + margin-right: -15px; } + #ex-debug-toolbar .navbar-right ~ .navbar-right { + margin-right: 0; } } + #ex-debug-toolbar .navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; } + #ex-debug-toolbar .navbar-default .navbar-brand { + color: #777; } + #ex-debug-toolbar .navbar-default .navbar-brand:hover, #ex-debug-toolbar .navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; } + #ex-debug-toolbar .navbar-default .navbar-text { + color: #777; } + #ex-debug-toolbar .navbar-default .navbar-nav > li > a, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li > span { + color: #777; } + #ex-debug-toolbar .navbar-default .navbar-nav > li > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav > li > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li > span:focus { + color: #333; + background-color: transparent; } + #ex-debug-toolbar .navbar-default .navbar-nav > .active > a, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.active > span, #ex-debug-toolbar .navbar-default .navbar-nav > .active > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.active > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav > .active > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.active > span:focus { + color: #555; + background-color: #e7e7e7; } + #ex-debug-toolbar .navbar-default .navbar-nav > .disabled > a, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.disabled > span, #ex-debug-toolbar .navbar-default .navbar-nav > .disabled > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.disabled > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav > .disabled > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.disabled > span:focus { + color: #ccc; + background-color: transparent; } + #ex-debug-toolbar .navbar-default .navbar-toggle { + border-color: #ddd; } + #ex-debug-toolbar .navbar-default .navbar-toggle:hover, #ex-debug-toolbar .navbar-default .navbar-toggle:focus { + background-color: #ddd; } + #ex-debug-toolbar .navbar-default .navbar-toggle .icon-bar { + background-color: #888; } + #ex-debug-toolbar .navbar-default .navbar-collapse, + #ex-debug-toolbar .navbar-default .navbar-form { + border-color: #e7e7e7; } + #ex-debug-toolbar .navbar-default .navbar-nav > .open > a, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.open > span, #ex-debug-toolbar .navbar-default .navbar-nav > .open > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.open > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav > .open > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav.nav > li.open > span:focus { + background-color: #e7e7e7; + color: #555; } + @media (max-width: 767px) { + #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > li > a, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span { + color: #777; } + #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:focus { + color: #333; + background-color: transparent; } + #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .active > a, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span, #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span:focus { + color: #555; + background-color: #e7e7e7; } + #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span, #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span:hover, #ex-debug-toolbar .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus, #ex-debug-toolbar .navbar-default .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span:focus { + color: #ccc; + background-color: transparent; } } + #ex-debug-toolbar .navbar-default .navbar-link { + color: #777; } + #ex-debug-toolbar .navbar-default .navbar-link:hover { + color: #333; } + #ex-debug-toolbar .navbar-default .btn-link { + color: #777; } + #ex-debug-toolbar .navbar-default .btn-link:hover, #ex-debug-toolbar .navbar-default .btn-link:focus { + color: #333; } + #ex-debug-toolbar .navbar-default .btn-link[disabled]:hover, #ex-debug-toolbar .navbar-default .btn-link[disabled]:focus, + fieldset[disabled] #ex-debug-toolbar .navbar-default .btn-link:hover, + fieldset[disabled] #ex-debug-toolbar .navbar-default .btn-link:focus { + color: #ccc; } + #ex-debug-toolbar .navbar-inverse { + background-color: #222; + border-color: #090909; } + #ex-debug-toolbar .navbar-inverse .navbar-brand { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .navbar-brand:hover, #ex-debug-toolbar .navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; } + #ex-debug-toolbar .navbar-inverse .navbar-text { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .navbar-nav > li > a, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li > span { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .navbar-nav > li > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav > li > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li > span:focus { + color: #fff; + background-color: transparent; } + #ex-debug-toolbar .navbar-inverse .navbar-nav > .active > a, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.active > span, #ex-debug-toolbar .navbar-inverse .navbar-nav > .active > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.active > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav > .active > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.active > span:focus { + color: #fff; + background-color: #090909; } + #ex-debug-toolbar .navbar-inverse .navbar-nav > .disabled > a, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.disabled > span, #ex-debug-toolbar .navbar-inverse .navbar-nav > .disabled > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.disabled > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav > .disabled > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.disabled > span:focus { + color: #444; + background-color: transparent; } + #ex-debug-toolbar .navbar-inverse .navbar-toggle { + border-color: #333; } + #ex-debug-toolbar .navbar-inverse .navbar-toggle:hover, #ex-debug-toolbar .navbar-inverse .navbar-toggle:focus { + background-color: #333; } + #ex-debug-toolbar .navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; } + #ex-debug-toolbar .navbar-inverse .navbar-collapse, + #ex-debug-toolbar .navbar-inverse .navbar-form { + border-color: #101010; } + #ex-debug-toolbar .navbar-inverse .navbar-nav > .open > a, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.open > span, #ex-debug-toolbar .navbar-inverse .navbar-nav > .open > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.open > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav > .open > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav.nav > li.open > span:focus { + background-color: #090909; + color: #fff; } + @media (max-width: 767px) { + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #090909; } + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #090909; } + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > li > a, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li > span:focus { + color: #fff; + background-color: transparent; } + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.active > span:focus { + color: #fff; + background-color: #090909; } + #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span:hover, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus, #ex-debug-toolbar .navbar-inverse .navbar-nav .open .navbar-nav.nav.dropdown-menu > li.disabled > span:focus { + color: #444; + background-color: transparent; } } + #ex-debug-toolbar .navbar-inverse .navbar-link { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .navbar-link:hover { + color: #fff; } + #ex-debug-toolbar .navbar-inverse .btn-link { + color: #9d9d9d; } + #ex-debug-toolbar .navbar-inverse .btn-link:hover, #ex-debug-toolbar .navbar-inverse .btn-link:focus { + color: #fff; } + #ex-debug-toolbar .navbar-inverse .btn-link[disabled]:hover, #ex-debug-toolbar .navbar-inverse .btn-link[disabled]:focus, + fieldset[disabled] #ex-debug-toolbar .navbar-inverse .btn-link:hover, + fieldset[disabled] #ex-debug-toolbar .navbar-inverse .btn-link:focus { + color: #444; } + #ex-debug-toolbar .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; } + #ex-debug-toolbar .breadcrumb > li { + display: inline-block; } + #ex-debug-toolbar .breadcrumb > li + li:before { + content: "/ "; + padding: 0 5px; + color: #ccc; } + #ex-debug-toolbar .breadcrumb > .active { + color: #777777; } + #ex-debug-toolbar .pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; } + #ex-debug-toolbar .pagination > li { + display: inline; } + #ex-debug-toolbar .pagination > li > a, #ex-debug-toolbar .navbar-nav.nav.pagination > li > span, + #ex-debug-toolbar .pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + line-height: 1.42857; + text-decoration: none; + color: #337ab7; + background-color: #fff; + border: 1px solid #ddd; + margin-left: -1px; } + #ex-debug-toolbar .pagination > li:first-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination > li:first-child > span, + #ex-debug-toolbar .pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; } + #ex-debug-toolbar .pagination > li:last-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination > li:last-child > span, + #ex-debug-toolbar .pagination > li:last-child > span { + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; } + #ex-debug-toolbar .pagination > li > a:hover, #ex-debug-toolbar .navbar-nav.nav.pagination > li > span:hover, #ex-debug-toolbar .pagination > li > a:focus, #ex-debug-toolbar .navbar-nav.nav.pagination > li > span:focus, + #ex-debug-toolbar .pagination > li > span:hover, + #ex-debug-toolbar .pagination > li > span:focus { + z-index: 2; + color: #23527c; + background-color: #eeeeee; + border-color: #ddd; } + #ex-debug-toolbar .pagination > .active > a, #ex-debug-toolbar .navbar-nav.nav.pagination > li.active > span, #ex-debug-toolbar .pagination > .active > a:hover, #ex-debug-toolbar .navbar-nav.nav.pagination > li.active > span:hover, #ex-debug-toolbar .pagination > .active > a:focus, #ex-debug-toolbar .navbar-nav.nav.pagination > li.active > span:focus, + #ex-debug-toolbar .pagination > .active > span, + #ex-debug-toolbar .pagination > .active > span:hover, + #ex-debug-toolbar .pagination > .active > span:focus { + z-index: 3; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; + cursor: default; } + #ex-debug-toolbar .pagination > .disabled > span, + #ex-debug-toolbar .pagination > .disabled > span:hover, + #ex-debug-toolbar .pagination > .disabled > span:focus, + #ex-debug-toolbar .pagination > .disabled > a, #ex-debug-toolbar .navbar-nav.nav.pagination > li.disabled > span, + #ex-debug-toolbar .pagination > .disabled > a:hover, #ex-debug-toolbar .navbar-nav.nav.pagination > li.disabled > span:hover, + #ex-debug-toolbar .pagination > .disabled > a:focus, #ex-debug-toolbar .navbar-nav.nav.pagination > li.disabled > span:focus { + color: #777777; + background-color: #fff; + border-color: #ddd; + cursor: not-allowed; } + #ex-debug-toolbar .pagination-lg > li > a, #ex-debug-toolbar .navbar-nav.nav.pagination-lg > li > span, + #ex-debug-toolbar .pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33333; } + #ex-debug-toolbar .pagination-lg > li:first-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination-lg > li:first-child > span, + #ex-debug-toolbar .pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; } + #ex-debug-toolbar .pagination-lg > li:last-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination-lg > li:last-child > span, + #ex-debug-toolbar .pagination-lg > li:last-child > span { + border-bottom-right-radius: 6px; + border-top-right-radius: 6px; } + #ex-debug-toolbar .pagination-sm > li > a, #ex-debug-toolbar .navbar-nav.nav.pagination-sm > li > span, + #ex-debug-toolbar .pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; } + #ex-debug-toolbar .pagination-sm > li:first-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination-sm > li:first-child > span, + #ex-debug-toolbar .pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; } + #ex-debug-toolbar .pagination-sm > li:last-child > a, #ex-debug-toolbar .navbar-nav.nav.pagination-sm > li:last-child > span, + #ex-debug-toolbar .pagination-sm > li:last-child > span { + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; } + #ex-debug-toolbar .pager { + padding-left: 0; + margin: 20px 0; + list-style: none; + text-align: center; } + #ex-debug-toolbar .pager:before, #ex-debug-toolbar .pager:after { + content: " "; + display: table; } + #ex-debug-toolbar .pager:after { + clear: both; } + #ex-debug-toolbar .pager li { + display: inline; } + #ex-debug-toolbar .pager li > a, #ex-debug-toolbar .pager .navbar-nav.nav > li > span, + #ex-debug-toolbar .pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; } + #ex-debug-toolbar .pager li > a:hover, #ex-debug-toolbar .pager .navbar-nav.nav > li > span:hover, + #ex-debug-toolbar .pager li > a:focus, #ex-debug-toolbar .pager .navbar-nav.nav > li > span:focus { + text-decoration: none; + background-color: #eeeeee; } + #ex-debug-toolbar .pager .next > a, #ex-debug-toolbar .pager .navbar-nav.nav > li.next > span, + #ex-debug-toolbar .pager .next > span { + float: right; } + #ex-debug-toolbar .pager .previous > a, #ex-debug-toolbar .pager .navbar-nav.nav > li.previous > span, + #ex-debug-toolbar .pager .previous > span { + float: left; } + #ex-debug-toolbar .pager .disabled > a, #ex-debug-toolbar .pager .navbar-nav.nav > li.disabled > span, + #ex-debug-toolbar .pager .disabled > a:hover, #ex-debug-toolbar .pager .navbar-nav.nav > li.disabled > span:hover, + #ex-debug-toolbar .pager .disabled > a:focus, #ex-debug-toolbar .pager .navbar-nav.nav > li.disabled > span:focus, + #ex-debug-toolbar .pager .disabled > span { + color: #777777; + background-color: #fff; + cursor: not-allowed; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .label:empty { + display: none; } + .btn #ex-debug-toolbar .label { + position: relative; + top: -1px; } + #ex-debug-toolbar a.label:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.label:hover, #ex-debug-toolbar a.label:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; } + #ex-debug-toolbar .label-default { + background-color: #777777; } + #ex-debug-toolbar .label-default[href]:hover, #ex-debug-toolbar .label-default[href]:focus { + background-color: #5e5e5e; } + #ex-debug-toolbar .label-primary { + background-color: #337ab7; } + #ex-debug-toolbar .label-primary[href]:hover, #ex-debug-toolbar .label-primary[href]:focus { + background-color: #286090; } + #ex-debug-toolbar .label-success { + background-color: #5cb85c; } + #ex-debug-toolbar .label-success[href]:hover, #ex-debug-toolbar .label-success[href]:focus { + background-color: #449d44; } + #ex-debug-toolbar .label-info { + background-color: #5bc0de; } + #ex-debug-toolbar .label-info[href]:hover, #ex-debug-toolbar .label-info[href]:focus { + background-color: #31b0d5; } + #ex-debug-toolbar .label-warning { + background-color: #f0ad4e; } + #ex-debug-toolbar .label-warning[href]:hover, #ex-debug-toolbar .label-warning[href]:focus { + background-color: #ec971f; } + #ex-debug-toolbar .label-danger { + background-color: #d9534f; } + #ex-debug-toolbar .label-danger[href]:hover, #ex-debug-toolbar .label-danger[href]:focus { + background-color: #c9302c; } + #ex-debug-toolbar .badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + color: #fff; + line-height: 1; + vertical-align: middle; + white-space: nowrap; + text-align: center; + background-color: #777777; + border-radius: 10px; } + #ex-debug-toolbar .badge:empty { + display: none; } + .btn #ex-debug-toolbar .badge { + position: relative; + top: -1px; } + .btn-xs #ex-debug-toolbar .badge, #ex-debug-toolbar .btn-group-xs > .btn #ex-debug-toolbar .badge, + .btn-group-xs > .btn #ex-debug-toolbar .badge { + top: 0; + padding: 1px 5px; } + .list-group-item.active > #ex-debug-toolbar .badge, + .nav-pills > .active > a > #ex-debug-toolbar .badge, #ex-debug-toolbar + .navbar-nav.nav.nav-pills > li.active > span > #ex-debug-toolbar .badge { + color: #337ab7; + background-color: #fff; } + .list-group-item > #ex-debug-toolbar .badge { + float: right; } + .list-group-item > #ex-debug-toolbar .badge + #ex-debug-toolbar .badge { + margin-right: 5px; } + .nav-pills > li > a > #ex-debug-toolbar .badge, #ex-debug-toolbar .navbar-nav.nav.nav-pills > li > span > #ex-debug-toolbar .badge { + margin-left: 3px; } + #ex-debug-toolbar a.badge:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.badge:hover, #ex-debug-toolbar a.badge:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; } + #ex-debug-toolbar .jumbotron { + padding-top: 30px; + padding-bottom: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eeeeee; } + #ex-debug-toolbar .jumbotron h1, + #ex-debug-toolbar .jumbotron .h1 { + color: inherit; } + #ex-debug-toolbar .jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; } + #ex-debug-toolbar .jumbotron > hr { + border-top-color: #d5d5d5; } + .container #ex-debug-toolbar .jumbotron, + .container-fluid #ex-debug-toolbar .jumbotron { + border-radius: 6px; + padding-left: 15px; + padding-right: 15px; } + #ex-debug-toolbar .jumbotron .container { + max-width: 100%; } + @media screen and (min-width: 768px) { + #ex-debug-toolbar .jumbotron { + padding-top: 48px; + padding-bottom: 48px; } + .container #ex-debug-toolbar .jumbotron, + .container-fluid #ex-debug-toolbar .jumbotron { + padding-left: 60px; + padding-right: 60px; } + #ex-debug-toolbar .jumbotron h1, + #ex-debug-toolbar .jumbotron .h1 { + font-size: 63px; } } + #ex-debug-toolbar .thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857; + background-color: #fff; + border: 1px solid #ddd; + 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; } + #ex-debug-toolbar .thumbnail > img, + #ex-debug-toolbar .thumbnail a > img, #ex-debug-toolbar .thumbnail .navbar-nav.nav > li > span > img { + display: block; + max-width: 100%; + height: auto; + margin-left: auto; + margin-right: auto; } + #ex-debug-toolbar .thumbnail .caption { + padding: 9px; + color: #333333; } + #ex-debug-toolbar a.thumbnail:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.thumbnail:hover, + #ex-debug-toolbar a.thumbnail:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.thumbnail:focus, + #ex-debug-toolbar a.thumbnail.active, #ex-debug-toolbar .navbar-nav.nav > li > span.thumbnail.active { + border-color: #337ab7; } + #ex-debug-toolbar .alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; } + #ex-debug-toolbar .alert h4 { + margin-top: 0; + color: inherit; } + #ex-debug-toolbar .alert .alert-link { + font-weight: bold; } + #ex-debug-toolbar .alert > p, + #ex-debug-toolbar .alert > ul { + margin-bottom: 0; } + #ex-debug-toolbar .alert > p + p { + margin-top: 5px; } + #ex-debug-toolbar .alert-dismissable, + #ex-debug-toolbar .alert-dismissible { + padding-right: 35px; } + #ex-debug-toolbar .alert-dismissable .close, + #ex-debug-toolbar .alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; } + #ex-debug-toolbar .alert-success { + background-color: #dff0d8; + border-color: #d6e9c6; + color: #3c763d; } + #ex-debug-toolbar .alert-success hr { + border-top-color: #c9e2b3; } + #ex-debug-toolbar .alert-success .alert-link { + color: #2b542c; } + #ex-debug-toolbar .alert-info { + background-color: #d9edf7; + border-color: #bce8f1; + color: #31708f; } + #ex-debug-toolbar .alert-info hr { + border-top-color: #a6e1ec; } + #ex-debug-toolbar .alert-info .alert-link { + color: #245269; } + #ex-debug-toolbar .alert-warning { + background-color: #fcf8e3; + border-color: #faebcc; + color: #8a6d3b; } + #ex-debug-toolbar .alert-warning hr { + border-top-color: #f7e1b5; } + #ex-debug-toolbar .alert-warning .alert-link { + color: #66512c; } + #ex-debug-toolbar .alert-danger { + background-color: #f2dede; + border-color: #ebccd1; + color: #a94442; } + #ex-debug-toolbar .alert-danger hr { + border-top-color: #e4b9c0; } + #ex-debug-toolbar .alert-danger .alert-link { + color: #843534; } + +@-webkit-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; } } + #ex-debug-toolbar .progress { + overflow: hidden; + height: 20px; + margin-bottom: 20px; + background-color: #f5f5f5; + 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); } + #ex-debug-toolbar .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, 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; } + #ex-debug-toolbar .progress-striped .progress-bar, + #ex-debug-toolbar .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); + background-size: 40px 40px; } + #ex-debug-toolbar .progress.active .progress-bar, + #ex-debug-toolbar .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; } + #ex-debug-toolbar .progress-bar-success { + background-color: #5cb85c; } + .progress-striped #ex-debug-toolbar .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); } + #ex-debug-toolbar .progress-bar-info { + background-color: #5bc0de; } + .progress-striped #ex-debug-toolbar .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); } + #ex-debug-toolbar .progress-bar-warning { + background-color: #f0ad4e; } + .progress-striped #ex-debug-toolbar .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); } + #ex-debug-toolbar .progress-bar-danger { + background-color: #d9534f; } + .progress-striped #ex-debug-toolbar .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); } + #ex-debug-toolbar .media { + margin-top: 15px; } + #ex-debug-toolbar .media:first-child { + margin-top: 0; } + #ex-debug-toolbar .media, + #ex-debug-toolbar .media-body { + zoom: 1; + overflow: hidden; } + #ex-debug-toolbar .media-body { + width: 10000px; } + #ex-debug-toolbar .media-object { + display: block; } + #ex-debug-toolbar .media-object.img-thumbnail { + max-width: none; } + #ex-debug-toolbar .media-right, + #ex-debug-toolbar .media > .pull-right { + padding-left: 10px; } + #ex-debug-toolbar .media-left, + #ex-debug-toolbar .media > .pull-left { + padding-right: 10px; } + #ex-debug-toolbar .media-left, + #ex-debug-toolbar .media-right, + #ex-debug-toolbar .media-body { + display: table-cell; + vertical-align: top; } + #ex-debug-toolbar .media-middle { + vertical-align: middle; } + #ex-debug-toolbar .media-bottom { + vertical-align: bottom; } + #ex-debug-toolbar .media-heading { + margin-top: 0; + margin-bottom: 5px; } + #ex-debug-toolbar .media-list { + padding-left: 0; + list-style: none; } + #ex-debug-toolbar .list-group { + margin-bottom: 20px; + padding-left: 0; } + #ex-debug-toolbar .list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; } + #ex-debug-toolbar .list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; } + #ex-debug-toolbar .list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; } + #ex-debug-toolbar a.list-group-item, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item, + #ex-debug-toolbar button.list-group-item { + color: #555; } + #ex-debug-toolbar a.list-group-item .list-group-item-heading, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item .list-group-item-heading, + #ex-debug-toolbar button.list-group-item .list-group-item-heading { + color: #333; } + #ex-debug-toolbar a.list-group-item:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item:hover, #ex-debug-toolbar a.list-group-item:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item:focus, + #ex-debug-toolbar button.list-group-item:hover, + #ex-debug-toolbar button.list-group-item:focus { + text-decoration: none; + color: #555; + background-color: #f5f5f5; } + #ex-debug-toolbar button.list-group-item { + width: 100%; + text-align: left; } + #ex-debug-toolbar .list-group-item.disabled, #ex-debug-toolbar .list-group-item.disabled:hover, #ex-debug-toolbar .list-group-item.disabled:focus { + background-color: #eeeeee; + color: #777777; + cursor: not-allowed; } + #ex-debug-toolbar .list-group-item.disabled .list-group-item-heading, #ex-debug-toolbar .list-group-item.disabled:hover .list-group-item-heading, #ex-debug-toolbar .list-group-item.disabled:focus .list-group-item-heading { + color: inherit; } + #ex-debug-toolbar .list-group-item.disabled .list-group-item-text, #ex-debug-toolbar .list-group-item.disabled:hover .list-group-item-text, #ex-debug-toolbar .list-group-item.disabled:focus .list-group-item-text { + color: #777777; } + #ex-debug-toolbar .list-group-item.active, #ex-debug-toolbar .list-group-item.active:hover, #ex-debug-toolbar .list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; } + #ex-debug-toolbar .list-group-item.active .list-group-item-heading, + #ex-debug-toolbar .list-group-item.active .list-group-item-heading > small, + #ex-debug-toolbar .list-group-item.active .list-group-item-heading > .small, #ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading, + #ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading > small, + #ex-debug-toolbar .list-group-item.active:hover .list-group-item-heading > .small, #ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading, + #ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading > small, + #ex-debug-toolbar .list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; } + #ex-debug-toolbar .list-group-item.active .list-group-item-text, #ex-debug-toolbar .list-group-item.active:hover .list-group-item-text, #ex-debug-toolbar .list-group-item.active:focus .list-group-item-text { + color: #c7ddef; } + #ex-debug-toolbar .list-group-item-success { + color: #3c763d; + background-color: #dff0d8; } + #ex-debug-toolbar a.list-group-item-success, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success, + #ex-debug-toolbar button.list-group-item-success { + color: #3c763d; } + #ex-debug-toolbar a.list-group-item-success .list-group-item-heading, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success .list-group-item-heading, + #ex-debug-toolbar button.list-group-item-success .list-group-item-heading { + color: inherit; } + #ex-debug-toolbar a.list-group-item-success:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success:hover, #ex-debug-toolbar a.list-group-item-success:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success:focus, + #ex-debug-toolbar button.list-group-item-success:hover, + #ex-debug-toolbar button.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; } + #ex-debug-toolbar a.list-group-item-success.active, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success.active, #ex-debug-toolbar a.list-group-item-success.active:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success.active:hover, #ex-debug-toolbar a.list-group-item-success.active:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-success.active:focus, + #ex-debug-toolbar button.list-group-item-success.active, + #ex-debug-toolbar button.list-group-item-success.active:hover, + #ex-debug-toolbar button.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; } + #ex-debug-toolbar .list-group-item-info { + color: #31708f; + background-color: #d9edf7; } + #ex-debug-toolbar a.list-group-item-info, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info, + #ex-debug-toolbar button.list-group-item-info { + color: #31708f; } + #ex-debug-toolbar a.list-group-item-info .list-group-item-heading, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info .list-group-item-heading, + #ex-debug-toolbar button.list-group-item-info .list-group-item-heading { + color: inherit; } + #ex-debug-toolbar a.list-group-item-info:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info:hover, #ex-debug-toolbar a.list-group-item-info:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info:focus, + #ex-debug-toolbar button.list-group-item-info:hover, + #ex-debug-toolbar button.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; } + #ex-debug-toolbar a.list-group-item-info.active, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info.active, #ex-debug-toolbar a.list-group-item-info.active:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info.active:hover, #ex-debug-toolbar a.list-group-item-info.active:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-info.active:focus, + #ex-debug-toolbar button.list-group-item-info.active, + #ex-debug-toolbar button.list-group-item-info.active:hover, + #ex-debug-toolbar button.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; } + #ex-debug-toolbar .list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; } + #ex-debug-toolbar a.list-group-item-warning, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning, + #ex-debug-toolbar button.list-group-item-warning { + color: #8a6d3b; } + #ex-debug-toolbar a.list-group-item-warning .list-group-item-heading, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning .list-group-item-heading, + #ex-debug-toolbar button.list-group-item-warning .list-group-item-heading { + color: inherit; } + #ex-debug-toolbar a.list-group-item-warning:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning:hover, #ex-debug-toolbar a.list-group-item-warning:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning:focus, + #ex-debug-toolbar button.list-group-item-warning:hover, + #ex-debug-toolbar button.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; } + #ex-debug-toolbar a.list-group-item-warning.active, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning.active, #ex-debug-toolbar a.list-group-item-warning.active:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning.active:hover, #ex-debug-toolbar a.list-group-item-warning.active:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-warning.active:focus, + #ex-debug-toolbar button.list-group-item-warning.active, + #ex-debug-toolbar button.list-group-item-warning.active:hover, + #ex-debug-toolbar button.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; } + #ex-debug-toolbar .list-group-item-danger { + color: #a94442; + background-color: #f2dede; } + #ex-debug-toolbar a.list-group-item-danger, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger, + #ex-debug-toolbar button.list-group-item-danger { + color: #a94442; } + #ex-debug-toolbar a.list-group-item-danger .list-group-item-heading, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger .list-group-item-heading, + #ex-debug-toolbar button.list-group-item-danger .list-group-item-heading { + color: inherit; } + #ex-debug-toolbar a.list-group-item-danger:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger:hover, #ex-debug-toolbar a.list-group-item-danger:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger:focus, + #ex-debug-toolbar button.list-group-item-danger:hover, + #ex-debug-toolbar button.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; } + #ex-debug-toolbar a.list-group-item-danger.active, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger.active, #ex-debug-toolbar a.list-group-item-danger.active:hover, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger.active:hover, #ex-debug-toolbar a.list-group-item-danger.active:focus, #ex-debug-toolbar .navbar-nav.nav > li > span.list-group-item-danger.active:focus, + #ex-debug-toolbar button.list-group-item-danger.active, + #ex-debug-toolbar button.list-group-item-danger.active:hover, + #ex-debug-toolbar button.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; } + #ex-debug-toolbar .list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; } + #ex-debug-toolbar .list-group-item-text { + margin-bottom: 0; + line-height: 1.3; } + #ex-debug-toolbar .panel { + margin-bottom: 20px; + background-color: #fff; + 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); } + #ex-debug-toolbar .panel-body { + padding: 15px; } + #ex-debug-toolbar .panel-body:before, #ex-debug-toolbar .panel-body:after { + content: " "; + display: table; } + #ex-debug-toolbar .panel-body:after { + clear: both; } + #ex-debug-toolbar .panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; } + #ex-debug-toolbar .panel-heading > .dropdown .dropdown-toggle { + color: inherit; } + #ex-debug-toolbar .panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; } + #ex-debug-toolbar .panel-title > a, #ex-debug-toolbar .navbar-nav.nav > li.panel-title > span, + #ex-debug-toolbar .panel-title > small, + #ex-debug-toolbar .panel-title > .small, + #ex-debug-toolbar .panel-title > small > a, + #ex-debug-toolbar .panel-title > .small > a, #ex-debug-toolbar .navbar-nav.nav.panel-title > li.small > span { + color: inherit; } + #ex-debug-toolbar .panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + #ex-debug-toolbar .panel > .list-group, + #ex-debug-toolbar .panel > .panel-collapse > .list-group { + margin-bottom: 0; } + #ex-debug-toolbar .panel > .list-group .list-group-item, + #ex-debug-toolbar .panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; } + #ex-debug-toolbar .panel > .list-group:first-child .list-group-item:first-child, + #ex-debug-toolbar .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; } + #ex-debug-toolbar .panel > .list-group:last-child .list-group-item:last-child, + #ex-debug-toolbar .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; } + #ex-debug-toolbar .panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; } + #ex-debug-toolbar .panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; } + #ex-debug-toolbar .list-group + .panel-footer { + border-top-width: 0; } + #ex-debug-toolbar .panel > .table, + #ex-debug-toolbar .panel > .table-responsive > .table, + #ex-debug-toolbar .panel > .panel-collapse > .table { + margin-bottom: 0; } + #ex-debug-toolbar .panel > .table caption, + #ex-debug-toolbar .panel > .table-responsive > .table caption, + #ex-debug-toolbar .panel > .panel-collapse > .table caption { + padding-left: 15px; + padding-right: 15px; } + #ex-debug-toolbar .panel > .table:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child { + border-top-right-radius: 3px; + border-top-left-radius: 3px; } + #ex-debug-toolbar .panel > .table:first-child > thead:first-child > tr:first-child, + #ex-debug-toolbar .panel > .table:first-child > tbody:first-child > tr:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + #ex-debug-toolbar .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, + #ex-debug-toolbar .panel > .table:first-child > thead:first-child > tr:first-child th:first-child, + #ex-debug-toolbar .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, + #ex-debug-toolbar .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; } + #ex-debug-toolbar .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, + #ex-debug-toolbar .panel > .table:first-child > thead:first-child > tr:first-child th:last-child, + #ex-debug-toolbar .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, + #ex-debug-toolbar .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, + #ex-debug-toolbar .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; } + #ex-debug-toolbar .panel > .table:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + #ex-debug-toolbar .panel > .table:last-child > tbody:last-child > tr:last-child, + #ex-debug-toolbar .panel > .table:last-child > tfoot:last-child > tr:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; } + #ex-debug-toolbar .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, + #ex-debug-toolbar .panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, + #ex-debug-toolbar .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, + #ex-debug-toolbar .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; } + #ex-debug-toolbar .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, + #ex-debug-toolbar .panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, + #ex-debug-toolbar .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, + #ex-debug-toolbar .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, + #ex-debug-toolbar .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; } + #ex-debug-toolbar .panel > .panel-body + .table, + #ex-debug-toolbar .panel > .panel-body + .table-responsive, + #ex-debug-toolbar .panel > .table + .panel-body, + #ex-debug-toolbar .panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; } + #ex-debug-toolbar .panel > .table > tbody:first-child > tr:first-child th, + #ex-debug-toolbar .panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; } + #ex-debug-toolbar .panel > .table-bordered, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered { + border: 0; } + #ex-debug-toolbar .panel > .table-bordered > thead > tr > th:first-child, + #ex-debug-toolbar .panel > .table-bordered > thead > tr > td:first-child, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr > th:first-child, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr > td:first-child, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr > th:first-child, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr > td:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr > td:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; } + #ex-debug-toolbar .panel > .table-bordered > thead > tr > th:last-child, + #ex-debug-toolbar .panel > .table-bordered > thead > tr > td:last-child, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr > th:last-child, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr > td:last-child, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr > th:last-child, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr > td:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr > td:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; } + #ex-debug-toolbar .panel > .table-bordered > thead > tr:first-child > td, + #ex-debug-toolbar .panel > .table-bordered > thead > tr:first-child > th, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr:first-child > td, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr:first-child > th, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; } + #ex-debug-toolbar .panel > .table-bordered > tbody > tr:last-child > td, + #ex-debug-toolbar .panel > .table-bordered > tbody > tr:last-child > th, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr:last-child > td, + #ex-debug-toolbar .panel > .table-bordered > tfoot > tr:last-child > th, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, + #ex-debug-toolbar .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; } + #ex-debug-toolbar .panel > .table-responsive { + border: 0; + margin-bottom: 0; } + #ex-debug-toolbar .panel-group { + margin-bottom: 20px; } + #ex-debug-toolbar .panel-group .panel { + margin-bottom: 0; + border-radius: 4px; } + #ex-debug-toolbar .panel-group .panel + .panel { + margin-top: 5px; } + #ex-debug-toolbar .panel-group .panel-heading { + border-bottom: 0; } + #ex-debug-toolbar .panel-group .panel-heading + .panel-collapse > .panel-body, + #ex-debug-toolbar .panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; } + #ex-debug-toolbar .panel-group .panel-footer { + border-top: 0; } + #ex-debug-toolbar .panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; } + #ex-debug-toolbar .panel-default { + border-color: #ddd; } + #ex-debug-toolbar .panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #ddd; } + #ex-debug-toolbar .panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; } + #ex-debug-toolbar .panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333333; } + #ex-debug-toolbar .panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; } + #ex-debug-toolbar .panel-primary { + border-color: #337ab7; } + #ex-debug-toolbar .panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; } + #ex-debug-toolbar .panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; } + #ex-debug-toolbar .panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; } + #ex-debug-toolbar .panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; } + #ex-debug-toolbar .panel-success { + border-color: #d6e9c6; } + #ex-debug-toolbar .panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; } + #ex-debug-toolbar .panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; } + #ex-debug-toolbar .panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; } + #ex-debug-toolbar .panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; } + #ex-debug-toolbar .panel-info { + border-color: #bce8f1; } + #ex-debug-toolbar .panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; } + #ex-debug-toolbar .panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; } + #ex-debug-toolbar .panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; } + #ex-debug-toolbar .panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; } + #ex-debug-toolbar .panel-warning { + border-color: #faebcc; } + #ex-debug-toolbar .panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; } + #ex-debug-toolbar .panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; } + #ex-debug-toolbar .panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; } + #ex-debug-toolbar .panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; } + #ex-debug-toolbar .panel-danger { + border-color: #ebccd1; } + #ex-debug-toolbar .panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; } + #ex-debug-toolbar .panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; } + #ex-debug-toolbar .panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; } + #ex-debug-toolbar .panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; } + #ex-debug-toolbar .embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; } + #ex-debug-toolbar .embed-responsive .embed-responsive-item, + #ex-debug-toolbar .embed-responsive iframe, + #ex-debug-toolbar .embed-responsive embed, + #ex-debug-toolbar .embed-responsive object, + #ex-debug-toolbar .embed-responsive video { + position: absolute; + top: 0; + left: 0; + bottom: 0; + height: 100%; + width: 100%; + border: 0; } + #ex-debug-toolbar .embed-responsive-16by9 { + padding-bottom: 56.25%; } + #ex-debug-toolbar .embed-responsive-4by3 { + padding-bottom: 75%; } + #ex-debug-toolbar .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, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); } + #ex-debug-toolbar .well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); } + #ex-debug-toolbar .well-lg { + padding: 24px; + border-radius: 6px; } + #ex-debug-toolbar .well-sm { + padding: 9px; + border-radius: 3px; } + #ex-debug-toolbar .close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: 0.2; + filter: alpha(opacity=20); } + #ex-debug-toolbar .close:hover, #ex-debug-toolbar .close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); } + #ex-debug-toolbar button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; } + #ex-debug-toolbar .modal-open { + overflow: hidden; } + #ex-debug-toolbar .modal { + display: none; + overflow: hidden; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + -webkit-overflow-scrolling: touch; + outline: 0; } + #ex-debug-toolbar .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; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; } + #ex-debug-toolbar .modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); } + #ex-debug-toolbar .modal-open .modal { + overflow-x: hidden; + overflow-y: auto; } + #ex-debug-toolbar .modal-dialog { + position: relative; + width: auto; + margin: 10px; } + #ex-debug-toolbar .modal-content { + position: relative; + background-color: #fff; + border: 1px solid #999; + 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); + background-clip: padding-box; + outline: 0; } + #ex-debug-toolbar .modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; } + #ex-debug-toolbar .modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); } + #ex-debug-toolbar .modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); } + #ex-debug-toolbar .modal-header { + padding: 15px; + border-bottom: 1px solid #e5e5e5; } + #ex-debug-toolbar .modal-header:before, #ex-debug-toolbar .modal-header:after { + content: " "; + display: table; } + #ex-debug-toolbar .modal-header:after { + clear: both; } + #ex-debug-toolbar .modal-header .close { + margin-top: -2px; } + #ex-debug-toolbar .modal-title { + margin: 0; + line-height: 1.42857; } + #ex-debug-toolbar .modal-body { + position: relative; + padding: 15px; } + #ex-debug-toolbar .modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; } + #ex-debug-toolbar .modal-footer:before, #ex-debug-toolbar .modal-footer:after { + content: " "; + display: table; } + #ex-debug-toolbar .modal-footer:after { + clear: both; } + #ex-debug-toolbar .modal-footer .btn + .btn { + margin-left: 5px; + margin-bottom: 0; } + #ex-debug-toolbar .modal-footer .btn-group .btn + .btn { + margin-left: -1px; } + #ex-debug-toolbar .modal-footer .btn-block + .btn-block { + margin-left: 0; } + #ex-debug-toolbar .modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; } + @media (min-width: 768px) { + #ex-debug-toolbar .modal-dialog { + width: 600px; + margin: 30px auto; } + #ex-debug-toolbar .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); } + #ex-debug-toolbar .modal-sm { + width: 300px; } } + @media (min-width: 992px) { + #ex-debug-toolbar .modal-lg { + width: 900px; } } + #ex-debug-toolbar .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.42857; + 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); } + #ex-debug-toolbar .tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); } + #ex-debug-toolbar .tooltip.top { + margin-top: -3px; + padding: 5px 0; } + #ex-debug-toolbar .tooltip.right { + margin-left: 3px; + padding: 0 5px; } + #ex-debug-toolbar .tooltip.bottom { + margin-top: 3px; + padding: 5px 0; } + #ex-debug-toolbar .tooltip.left { + margin-left: -3px; + padding: 0 5px; } + #ex-debug-toolbar .tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 4px; } + #ex-debug-toolbar .tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + #ex-debug-toolbar .tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; } + #ex-debug-toolbar .tooltip.top-left .tooltip-arrow { + bottom: 0; + right: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; } + #ex-debug-toolbar .tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; } + #ex-debug-toolbar .tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; } + #ex-debug-toolbar .tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; } + #ex-debug-toolbar .tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + #ex-debug-toolbar .tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + #ex-debug-toolbar .tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + #ex-debug-toolbar .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.42857; + 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: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + 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); } + #ex-debug-toolbar .popover.top { + margin-top: -10px; } + #ex-debug-toolbar .popover.right { + margin-left: 10px; } + #ex-debug-toolbar .popover.bottom { + margin-top: 10px; } + #ex-debug-toolbar .popover.left { + margin-left: -10px; } + #ex-debug-toolbar .popover-title { + margin: 0; + padding: 8px 14px; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; } + #ex-debug-toolbar .popover-content { + padding: 9px 14px; } + #ex-debug-toolbar .popover > .arrow, #ex-debug-toolbar .popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + #ex-debug-toolbar .popover > .arrow { + border-width: 11px; } + #ex-debug-toolbar .popover > .arrow:after { + border-width: 10px; + content: ""; } + #ex-debug-toolbar .popover.top > .arrow { + left: 50%; + margin-left: -11px; + border-bottom-width: 0; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + bottom: -11px; } + #ex-debug-toolbar .popover.top > .arrow:after { + content: " "; + bottom: 1px; + margin-left: -10px; + border-bottom-width: 0; + border-top-color: #fff; } + #ex-debug-toolbar .popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-left-width: 0; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); } + #ex-debug-toolbar .popover.right > .arrow:after { + content: " "; + left: 1px; + bottom: -10px; + border-left-width: 0; + border-right-color: #fff; } + #ex-debug-toolbar .popover.bottom > .arrow { + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + top: -11px; } + #ex-debug-toolbar .popover.bottom > .arrow:after { + content: " "; + top: 1px; + margin-left: -10px; + border-top-width: 0; + border-bottom-color: #fff; } + #ex-debug-toolbar .popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); } + #ex-debug-toolbar .popover.left > .arrow:after { + content: " "; + right: 1px; + border-right-width: 0; + border-left-color: #fff; + bottom: -10px; } + #ex-debug-toolbar .carousel { + position: relative; } + #ex-debug-toolbar .carousel-inner { + position: relative; + overflow: hidden; + width: 100%; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .carousel-inner > .item > img, + #ex-debug-toolbar .carousel-inner > .item > a > img, #ex-debug-toolbar .navbar-nav.nav.carousel-inner > li.item > span > img { + display: block; + max-width: 100%; + height: auto; + line-height: 1; } + @media all and (transform-3d), (-webkit-transform-3d) { + #ex-debug-toolbar .carousel-inner > .item { + -webkit-transition: -webkit-transform 0.6s ease-in-out; + -moz-transition: -moz-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; + -moz-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + -moz-perspective: 1000px; + perspective: 1000px; } + #ex-debug-toolbar .carousel-inner > .item.next, #ex-debug-toolbar .carousel-inner > .item.active.right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + left: 0; } + #ex-debug-toolbar .carousel-inner > .item.prev, #ex-debug-toolbar .carousel-inner > .item.active.left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + left: 0; } + #ex-debug-toolbar .carousel-inner > .item.next.left, #ex-debug-toolbar .carousel-inner > .item.prev.right, #ex-debug-toolbar .carousel-inner > .item.active { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + left: 0; } } + #ex-debug-toolbar .carousel-inner > .active, + #ex-debug-toolbar .carousel-inner > .next, + #ex-debug-toolbar .carousel-inner > .prev { + display: block; } + #ex-debug-toolbar .carousel-inner > .active { + left: 0; } + #ex-debug-toolbar .carousel-inner > .next, + #ex-debug-toolbar .carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; } + #ex-debug-toolbar .carousel-inner > .next { + left: 100%; } + #ex-debug-toolbar .carousel-inner > .prev { + left: -100%; } + #ex-debug-toolbar .carousel-inner > .next.left, + #ex-debug-toolbar .carousel-inner > .prev.right { + left: 0; } + #ex-debug-toolbar .carousel-inner > .active.left { + left: -100%; } + #ex-debug-toolbar .carousel-inner > .active.right { + left: 100%; } + #ex-debug-toolbar .carousel-control { + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 15%; + opacity: 0.5; + filter: alpha(opacity=50); + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + background-color: transparent; } + #ex-debug-toolbar .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: 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); } + #ex-debug-toolbar .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: 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); } + #ex-debug-toolbar .carousel-control:hover, #ex-debug-toolbar .carousel-control:focus { + outline: 0; + color: #fff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); } + #ex-debug-toolbar .carousel-control .icon-prev, + #ex-debug-toolbar .carousel-control .icon-next, + #ex-debug-toolbar .carousel-control .glyphicon-chevron-left, + #ex-debug-toolbar .carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + margin-top: -10px; + z-index: 5; + display: inline-block; } + #ex-debug-toolbar .carousel-control .icon-prev, + #ex-debug-toolbar .carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; } + #ex-debug-toolbar .carousel-control .icon-next, + #ex-debug-toolbar .carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; } + #ex-debug-toolbar .carousel-control .icon-prev, + #ex-debug-toolbar .carousel-control .icon-next { + width: 20px; + height: 20px; + line-height: 1; + font-family: serif; } + #ex-debug-toolbar .carousel-control .icon-prev:before { + content: '\2039'; } + #ex-debug-toolbar .carousel-control .icon-next:before { + content: '\203a'; } + #ex-debug-toolbar .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; } + #ex-debug-toolbar .carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + border: 1px solid #fff; + border-radius: 10px; + cursor: pointer; + background-color: #000 \9; + background-color: transparent; } + #ex-debug-toolbar .carousel-indicators .active { + margin: 0; + width: 12px; + height: 12px; + background-color: #fff; } + #ex-debug-toolbar .carousel-caption { + position: absolute; + left: 15%; + right: 15%; + bottom: 20px; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); } + #ex-debug-toolbar .carousel-caption .btn { + text-shadow: none; } + @media screen and (min-width: 768px) { + #ex-debug-toolbar .carousel-control .glyphicon-chevron-left, + #ex-debug-toolbar .carousel-control .glyphicon-chevron-right, + #ex-debug-toolbar .carousel-control .icon-prev, + #ex-debug-toolbar .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -10px; + font-size: 30px; } + #ex-debug-toolbar .carousel-control .glyphicon-chevron-left, + #ex-debug-toolbar .carousel-control .icon-prev { + margin-left: -10px; } + #ex-debug-toolbar .carousel-control .glyphicon-chevron-right, + #ex-debug-toolbar .carousel-control .icon-next { + margin-right: -10px; } + #ex-debug-toolbar .carousel-caption { + left: 20%; + right: 20%; + padding-bottom: 30px; } + #ex-debug-toolbar .carousel-indicators { + bottom: 20px; } } + #ex-debug-toolbar .clearfix:before, #ex-debug-toolbar .clearfix:after { + content: " "; + display: table; } + #ex-debug-toolbar .clearfix:after { + clear: both; } + #ex-debug-toolbar .center-block { + display: block; + margin-left: auto; + margin-right: auto; } + #ex-debug-toolbar .pull-right { + float: right !important; } + #ex-debug-toolbar .pull-left { + float: left !important; } + #ex-debug-toolbar .hide { + display: none !important; } + #ex-debug-toolbar .show { + display: block !important; } + #ex-debug-toolbar .invisible { + visibility: hidden; } + #ex-debug-toolbar .text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; } + #ex-debug-toolbar .hidden { + display: none !important; } + #ex-debug-toolbar .affix { + position: fixed; } + +@-ms-viewport { + width: device-width; } + #ex-debug-toolbar .visible-xs { + display: none !important; } + #ex-debug-toolbar .visible-sm { + display: none !important; } + #ex-debug-toolbar .visible-md { + display: none !important; } + #ex-debug-toolbar .visible-lg { + display: none !important; } + #ex-debug-toolbar .visible-xs-block, + #ex-debug-toolbar .visible-xs-inline, + #ex-debug-toolbar .visible-xs-inline-block, + #ex-debug-toolbar .visible-sm-block, + #ex-debug-toolbar .visible-sm-inline, + #ex-debug-toolbar .visible-sm-inline-block, + #ex-debug-toolbar .visible-md-block, + #ex-debug-toolbar .visible-md-inline, + #ex-debug-toolbar .visible-md-inline-block, + #ex-debug-toolbar .visible-lg-block, + #ex-debug-toolbar .visible-lg-inline, + #ex-debug-toolbar .visible-lg-inline-block { + display: none !important; } + @media (max-width: 767px) { + #ex-debug-toolbar .visible-xs { + display: block !important; } + #ex-debug-toolbar table.visible-xs { + display: table !important; } + #ex-debug-toolbar tr.visible-xs { + display: table-row !important; } + #ex-debug-toolbar th.visible-xs, + #ex-debug-toolbar td.visible-xs { + display: table-cell !important; } } + @media (max-width: 767px) { + #ex-debug-toolbar .visible-xs-block { + display: block !important; } } + @media (max-width: 767px) { + #ex-debug-toolbar .visible-xs-inline { + display: inline !important; } } + @media (max-width: 767px) { + #ex-debug-toolbar .visible-xs-inline-block { + display: inline-block !important; } } + @media (min-width: 768px) and (max-width: 991px) { + #ex-debug-toolbar .visible-sm { + display: block !important; } + #ex-debug-toolbar table.visible-sm { + display: table !important; } + #ex-debug-toolbar tr.visible-sm { + display: table-row !important; } + #ex-debug-toolbar th.visible-sm, + #ex-debug-toolbar td.visible-sm { + display: table-cell !important; } } + @media (min-width: 768px) and (max-width: 991px) { + #ex-debug-toolbar .visible-sm-block { + display: block !important; } } + @media (min-width: 768px) and (max-width: 991px) { + #ex-debug-toolbar .visible-sm-inline { + display: inline !important; } } + @media (min-width: 768px) and (max-width: 991px) { + #ex-debug-toolbar .visible-sm-inline-block { + display: inline-block !important; } } + @media (min-width: 992px) and (max-width: 1199px) { + #ex-debug-toolbar .visible-md { + display: block !important; } + #ex-debug-toolbar table.visible-md { + display: table !important; } + #ex-debug-toolbar tr.visible-md { + display: table-row !important; } + #ex-debug-toolbar th.visible-md, + #ex-debug-toolbar td.visible-md { + display: table-cell !important; } } + @media (min-width: 992px) and (max-width: 1199px) { + #ex-debug-toolbar .visible-md-block { + display: block !important; } } + @media (min-width: 992px) and (max-width: 1199px) { + #ex-debug-toolbar .visible-md-inline { + display: inline !important; } } + @media (min-width: 992px) and (max-width: 1199px) { + #ex-debug-toolbar .visible-md-inline-block { + display: inline-block !important; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .visible-lg { + display: block !important; } + #ex-debug-toolbar table.visible-lg { + display: table !important; } + #ex-debug-toolbar tr.visible-lg { + display: table-row !important; } + #ex-debug-toolbar th.visible-lg, + #ex-debug-toolbar td.visible-lg { + display: table-cell !important; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .visible-lg-block { + display: block !important; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .visible-lg-inline { + display: inline !important; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .visible-lg-inline-block { + display: inline-block !important; } } + @media (max-width: 767px) { + #ex-debug-toolbar .hidden-xs { + display: none !important; } } + @media (min-width: 768px) and (max-width: 991px) { + #ex-debug-toolbar .hidden-sm { + display: none !important; } } + @media (min-width: 992px) and (max-width: 1199px) { + #ex-debug-toolbar .hidden-md { + display: none !important; } } + @media (min-width: 1200px) { + #ex-debug-toolbar .hidden-lg { + display: none !important; } } + #ex-debug-toolbar .visible-print { + display: none !important; } + @media print { + #ex-debug-toolbar .visible-print { + display: block !important; } + #ex-debug-toolbar table.visible-print { + display: table !important; } + #ex-debug-toolbar tr.visible-print { + display: table-row !important; } + #ex-debug-toolbar th.visible-print, + #ex-debug-toolbar td.visible-print { + display: table-cell !important; } } + #ex-debug-toolbar .visible-print-block { + display: none !important; } + @media print { + #ex-debug-toolbar .visible-print-block { + display: block !important; } } + #ex-debug-toolbar .visible-print-inline { + display: none !important; } + @media print { + #ex-debug-toolbar .visible-print-inline { + display: inline !important; } } + #ex-debug-toolbar .visible-print-inline-block { + display: none !important; } + @media print { + #ex-debug-toolbar .visible-print-inline-block { + display: inline-block !important; } } + @media print { + #ex-debug-toolbar .hidden-print { + display: none !important; } } + #ex-debug-toolbar code[class*="language-"], + #ex-debug-toolbar pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; } + #ex-debug-toolbar pre[class*="language-"]::-moz-selection, #ex-debug-toolbar pre[class*="language-"] ::-moz-selection, + #ex-debug-toolbar code[class*="language-"]::-moz-selection, #ex-debug-toolbar code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; } + #ex-debug-toolbar pre[class*="language-"]::selection, #ex-debug-toolbar pre[class*="language-"] ::selection, + #ex-debug-toolbar code[class*="language-"]::selection, #ex-debug-toolbar code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; } + @media print { + #ex-debug-toolbar code[class*="language-"], + #ex-debug-toolbar pre[class*="language-"] { + text-shadow: none; } } + #ex-debug-toolbar pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; } + #ex-debug-toolbar :not(pre) > code[class*="language-"], + #ex-debug-toolbar pre[class*="language-"] { + background: #f5f2f0; } + #ex-debug-toolbar :not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; } + #ex-debug-toolbar .token.comment, + #ex-debug-toolbar .token.prolog, + #ex-debug-toolbar .token.doctype, + #ex-debug-toolbar .token.cdata { + color: slategray; } + #ex-debug-toolbar .token.punctuation { + color: #999; } + #ex-debug-toolbar .namespace { + opacity: .7; } + #ex-debug-toolbar .token.property, + #ex-debug-toolbar .token.tag, + #ex-debug-toolbar .token.boolean, + #ex-debug-toolbar .token.number, + #ex-debug-toolbar .token.constant, + #ex-debug-toolbar .token.symbol, + #ex-debug-toolbar .token.deleted { + color: #905; } + #ex-debug-toolbar .token.selector, + #ex-debug-toolbar .token.attr-name, + #ex-debug-toolbar .token.string, + #ex-debug-toolbar .token.char, + #ex-debug-toolbar .token.builtin, + #ex-debug-toolbar .token.inserted { + color: #690; } + #ex-debug-toolbar .token.operator, + #ex-debug-toolbar .token.entity, + #ex-debug-toolbar .token.url, + #ex-debug-toolbar .language-css .token.string, + #ex-debug-toolbar .style .token.string { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); } + #ex-debug-toolbar .token.atrule, + #ex-debug-toolbar .token.attr-value, + #ex-debug-toolbar .token.keyword { + color: #07a; } + #ex-debug-toolbar .token.function { + color: #DD4A68; } + #ex-debug-toolbar .token.regex, + #ex-debug-toolbar .token.important, + #ex-debug-toolbar .token.variable { + color: #e90; } + #ex-debug-toolbar .token.important, + #ex-debug-toolbar .token.bold { + font-weight: bold; } + #ex-debug-toolbar .token.italic { + font-style: italic; } + #ex-debug-toolbar .token.entity { + cursor: help; } + #ex-debug-toolbar pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; } + #ex-debug-toolbar pre.line-numbers > code { + position: relative; } + #ex-debug-toolbar .line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; + /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + #ex-debug-toolbar .line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; } + #ex-debug-toolbar .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; } + #ex-debug-toolbar pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; } + #ex-debug-toolbar .line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; + /* Same as .prism’s padding-top */ + background: rgba(153, 122, 102, 0.08); + background: linear-gradient(to right, rgba(153, 122, 102, 0.1) 70%, rgba(153, 122, 102, 0)); + pointer-events: none; + line-height: inherit; + white-space: pre; } + #ex-debug-toolbar .line-highlight:before, + #ex-debug-toolbar .line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: rgba(153, 122, 102, 0.4); + color: #f5f2f0; + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; } + #ex-debug-toolbar .line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; } + #ex-debug-toolbar .terminal { + background-color: #000; + color: #fff; + font-family: courier-new, courier, monospace; + font-feature-settings: "liga" 0; + position: relative; + user-select: none; + -ms-user-select: none; + -webkit-user-select: none; } + #ex-debug-toolbar .terminal.focus, + #ex-debug-toolbar .terminal:focus { + outline: none; } + #ex-debug-toolbar .terminal .xterm-helpers { + position: absolute; + top: 0; } + #ex-debug-toolbar .terminal .xterm-helper-textarea { + /* + * HACK: to fix IE's blinking cursor + * Move textarea out of the screen to the far left, so that the cursor is not visible. + */ + position: absolute; + opacity: 0; + left: -9999em; + top: 0; + width: 0; + height: 0; + z-index: -10; + /** Prevent wrapping so the IME appears against the textarea at the correct position */ + white-space: nowrap; + overflow: hidden; + resize: none; } + #ex-debug-toolbar .terminal a, #ex-debug-toolbar .terminal .navbar-nav.nav > li > span { + color: inherit; + text-decoration: none; } + #ex-debug-toolbar .terminal a:hover, #ex-debug-toolbar .terminal .navbar-nav.nav > li > span:hover { + cursor: pointer; + text-decoration: underline; } + #ex-debug-toolbar .terminal a.xterm-invalid-link:hover, #ex-debug-toolbar .terminal .navbar-nav.nav > li > span.xterm-invalid-link:hover { + cursor: text; + text-decoration: none; } + #ex-debug-toolbar .terminal.focus:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor { + background-color: #fff; + color: #000; } + #ex-debug-toolbar .terminal:not(.focus) .terminal-cursor { + outline: 1px solid #fff; + outline-offset: -1px; + background-color: transparent; } + #ex-debug-toolbar .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink-on .terminal-cursor { + background-color: transparent; + color: inherit; } + #ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor, + #ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor { + position: relative; } + #ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor::before, + #ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor::before { + content: ""; + display: block; + position: absolute; + background-color: #fff; } + #ex-debug-toolbar .terminal.xterm-cursor-style-bar .terminal-cursor::before { + top: 0; + bottom: 0; + left: 0; + width: 1px; } + #ex-debug-toolbar .terminal.xterm-cursor-style-underline .terminal-cursor::before { + bottom: 0; + left: 0; + right: 0; + height: 1px; } + #ex-debug-toolbar .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before, + #ex-debug-toolbar .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before { + background-color: transparent; } + #ex-debug-toolbar .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before, + #ex-debug-toolbar .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before { + background-color: #fff; } + #ex-debug-toolbar .terminal .composition-view { + background: #000; + color: #FFF; + display: none; + position: absolute; + white-space: nowrap; + z-index: 1; } + #ex-debug-toolbar .terminal .composition-view.active { + display: block; } + #ex-debug-toolbar .terminal .xterm-viewport { + /* On OS X this is required in order for the scroll bar to appear fully opaque */ + background-color: #000; + overflow-y: scroll; } + #ex-debug-toolbar .terminal .xterm-wide-char, + #ex-debug-toolbar .terminal .xterm-normal-char { + display: inline-block; } + #ex-debug-toolbar .terminal .xterm-rows { + position: absolute; + left: 0; + top: 0; } + #ex-debug-toolbar .terminal .xterm-rows > div { + /* Lines containing spans and text nodes ocassionally wrap despite being the same width (#327) */ + white-space: nowrap; } + #ex-debug-toolbar .terminal .xterm-scroll-area { + visibility: hidden; } + #ex-debug-toolbar .terminal .xterm-char-measure-element { + display: inline-block; + visibility: hidden; + position: absolute; + left: -9999em; } + #ex-debug-toolbar .terminal.enable-mouse-events { + /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */ + cursor: default; } + #ex-debug-toolbar .terminal .xterm-selection { + position: absolute; + top: 0; + left: 0; + z-index: 1; + opacity: 0.3; + pointer-events: none; } + #ex-debug-toolbar .terminal .xterm-selection div { + position: absolute; + background-color: #fff; } + #ex-debug-toolbar .terminal .xterm-bold { + font-weight: bold; } + #ex-debug-toolbar .terminal .xterm-underline { + text-decoration: underline; } + #ex-debug-toolbar .terminal .xterm-blink { + text-decoration: blink; } + #ex-debug-toolbar .terminal .xterm-hidden { + visibility: hidden; } + #ex-debug-toolbar .terminal .xterm-color-0 { + color: #2e3436; } + #ex-debug-toolbar .terminal .xterm-bg-color-0 { + background-color: #2e3436; } + #ex-debug-toolbar .terminal .xterm-color-1 { + color: #cc0000; } + #ex-debug-toolbar .terminal .xterm-bg-color-1 { + background-color: #cc0000; } + #ex-debug-toolbar .terminal .xterm-color-2 { + color: #4e9a06; } + #ex-debug-toolbar .terminal .xterm-bg-color-2 { + background-color: #4e9a06; } + #ex-debug-toolbar .terminal .xterm-color-3 { + color: #c4a000; } + #ex-debug-toolbar .terminal .xterm-bg-color-3 { + background-color: #c4a000; } + #ex-debug-toolbar .terminal .xterm-color-4 { + color: #3465a4; } + #ex-debug-toolbar .terminal .xterm-bg-color-4 { + background-color: #3465a4; } + #ex-debug-toolbar .terminal .xterm-color-5 { + color: #75507b; } + #ex-debug-toolbar .terminal .xterm-bg-color-5 { + background-color: #75507b; } + #ex-debug-toolbar .terminal .xterm-color-6 { + color: #06989a; } + #ex-debug-toolbar .terminal .xterm-bg-color-6 { + background-color: #06989a; } + #ex-debug-toolbar .terminal .xterm-color-7 { + color: #d3d7cf; } + #ex-debug-toolbar .terminal .xterm-bg-color-7 { + background-color: #d3d7cf; } + #ex-debug-toolbar .terminal .xterm-color-8 { + color: #555753; } + #ex-debug-toolbar .terminal .xterm-bg-color-8 { + background-color: #555753; } + #ex-debug-toolbar .terminal .xterm-color-9 { + color: #ef2929; } + #ex-debug-toolbar .terminal .xterm-bg-color-9 { + background-color: #ef2929; } + #ex-debug-toolbar .terminal .xterm-color-10 { + color: #8ae234; } + #ex-debug-toolbar .terminal .xterm-bg-color-10 { + background-color: #8ae234; } + #ex-debug-toolbar .terminal .xterm-color-11 { + color: #fce94f; } + #ex-debug-toolbar .terminal .xterm-bg-color-11 { + background-color: #fce94f; } + #ex-debug-toolbar .terminal .xterm-color-12 { + color: #729fcf; } + #ex-debug-toolbar .terminal .xterm-bg-color-12 { + background-color: #729fcf; } + #ex-debug-toolbar .terminal .xterm-color-13 { + color: #ad7fa8; } + #ex-debug-toolbar .terminal .xterm-bg-color-13 { + background-color: #ad7fa8; } + #ex-debug-toolbar .terminal .xterm-color-14 { + color: #34e2e2; } + #ex-debug-toolbar .terminal .xterm-bg-color-14 { + background-color: #34e2e2; } + #ex-debug-toolbar .terminal .xterm-color-15 { + color: #eeeeec; } + #ex-debug-toolbar .terminal .xterm-bg-color-15 { + background-color: #eeeeec; } + #ex-debug-toolbar .terminal .xterm-color-16 { + color: #000000; } + #ex-debug-toolbar .terminal .xterm-bg-color-16 { + background-color: #000000; } + #ex-debug-toolbar .terminal .xterm-color-17 { + color: #00005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-17 { + background-color: #00005f; } + #ex-debug-toolbar .terminal .xterm-color-18 { + color: #000087; } + #ex-debug-toolbar .terminal .xterm-bg-color-18 { + background-color: #000087; } + #ex-debug-toolbar .terminal .xterm-color-19 { + color: #0000af; } + #ex-debug-toolbar .terminal .xterm-bg-color-19 { + background-color: #0000af; } + #ex-debug-toolbar .terminal .xterm-color-20 { + color: #0000d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-20 { + background-color: #0000d7; } + #ex-debug-toolbar .terminal .xterm-color-21 { + color: #0000ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-21 { + background-color: #0000ff; } + #ex-debug-toolbar .terminal .xterm-color-22 { + color: #005f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-22 { + background-color: #005f00; } + #ex-debug-toolbar .terminal .xterm-color-23 { + color: #005f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-23 { + background-color: #005f5f; } + #ex-debug-toolbar .terminal .xterm-color-24 { + color: #005f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-24 { + background-color: #005f87; } + #ex-debug-toolbar .terminal .xterm-color-25 { + color: #005faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-25 { + background-color: #005faf; } + #ex-debug-toolbar .terminal .xterm-color-26 { + color: #005fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-26 { + background-color: #005fd7; } + #ex-debug-toolbar .terminal .xterm-color-27 { + color: #005fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-27 { + background-color: #005fff; } + #ex-debug-toolbar .terminal .xterm-color-28 { + color: #008700; } + #ex-debug-toolbar .terminal .xterm-bg-color-28 { + background-color: #008700; } + #ex-debug-toolbar .terminal .xterm-color-29 { + color: #00875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-29 { + background-color: #00875f; } + #ex-debug-toolbar .terminal .xterm-color-30 { + color: #008787; } + #ex-debug-toolbar .terminal .xterm-bg-color-30 { + background-color: #008787; } + #ex-debug-toolbar .terminal .xterm-color-31 { + color: #0087af; } + #ex-debug-toolbar .terminal .xterm-bg-color-31 { + background-color: #0087af; } + #ex-debug-toolbar .terminal .xterm-color-32 { + color: #0087d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-32 { + background-color: #0087d7; } + #ex-debug-toolbar .terminal .xterm-color-33 { + color: #0087ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-33 { + background-color: #0087ff; } + #ex-debug-toolbar .terminal .xterm-color-34 { + color: #00af00; } + #ex-debug-toolbar .terminal .xterm-bg-color-34 { + background-color: #00af00; } + #ex-debug-toolbar .terminal .xterm-color-35 { + color: #00af5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-35 { + background-color: #00af5f; } + #ex-debug-toolbar .terminal .xterm-color-36 { + color: #00af87; } + #ex-debug-toolbar .terminal .xterm-bg-color-36 { + background-color: #00af87; } + #ex-debug-toolbar .terminal .xterm-color-37 { + color: #00afaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-37 { + background-color: #00afaf; } + #ex-debug-toolbar .terminal .xterm-color-38 { + color: #00afd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-38 { + background-color: #00afd7; } + #ex-debug-toolbar .terminal .xterm-color-39 { + color: #00afff; } + #ex-debug-toolbar .terminal .xterm-bg-color-39 { + background-color: #00afff; } + #ex-debug-toolbar .terminal .xterm-color-40 { + color: #00d700; } + #ex-debug-toolbar .terminal .xterm-bg-color-40 { + background-color: #00d700; } + #ex-debug-toolbar .terminal .xterm-color-41 { + color: #00d75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-41 { + background-color: #00d75f; } + #ex-debug-toolbar .terminal .xterm-color-42 { + color: #00d787; } + #ex-debug-toolbar .terminal .xterm-bg-color-42 { + background-color: #00d787; } + #ex-debug-toolbar .terminal .xterm-color-43 { + color: #00d7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-43 { + background-color: #00d7af; } + #ex-debug-toolbar .terminal .xterm-color-44 { + color: #00d7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-44 { + background-color: #00d7d7; } + #ex-debug-toolbar .terminal .xterm-color-45 { + color: #00d7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-45 { + background-color: #00d7ff; } + #ex-debug-toolbar .terminal .xterm-color-46 { + color: #00ff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-46 { + background-color: #00ff00; } + #ex-debug-toolbar .terminal .xterm-color-47 { + color: #00ff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-47 { + background-color: #00ff5f; } + #ex-debug-toolbar .terminal .xterm-color-48 { + color: #00ff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-48 { + background-color: #00ff87; } + #ex-debug-toolbar .terminal .xterm-color-49 { + color: #00ffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-49 { + background-color: #00ffaf; } + #ex-debug-toolbar .terminal .xterm-color-50 { + color: #00ffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-50 { + background-color: #00ffd7; } + #ex-debug-toolbar .terminal .xterm-color-51 { + color: #00ffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-51 { + background-color: #00ffff; } + #ex-debug-toolbar .terminal .xterm-color-52 { + color: #5f0000; } + #ex-debug-toolbar .terminal .xterm-bg-color-52 { + background-color: #5f0000; } + #ex-debug-toolbar .terminal .xterm-color-53 { + color: #5f005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-53 { + background-color: #5f005f; } + #ex-debug-toolbar .terminal .xterm-color-54 { + color: #5f0087; } + #ex-debug-toolbar .terminal .xterm-bg-color-54 { + background-color: #5f0087; } + #ex-debug-toolbar .terminal .xterm-color-55 { + color: #5f00af; } + #ex-debug-toolbar .terminal .xterm-bg-color-55 { + background-color: #5f00af; } + #ex-debug-toolbar .terminal .xterm-color-56 { + color: #5f00d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-56 { + background-color: #5f00d7; } + #ex-debug-toolbar .terminal .xterm-color-57 { + color: #5f00ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-57 { + background-color: #5f00ff; } + #ex-debug-toolbar .terminal .xterm-color-58 { + color: #5f5f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-58 { + background-color: #5f5f00; } + #ex-debug-toolbar .terminal .xterm-color-59 { + color: #5f5f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-59 { + background-color: #5f5f5f; } + #ex-debug-toolbar .terminal .xterm-color-60 { + color: #5f5f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-60 { + background-color: #5f5f87; } + #ex-debug-toolbar .terminal .xterm-color-61 { + color: #5f5faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-61 { + background-color: #5f5faf; } + #ex-debug-toolbar .terminal .xterm-color-62 { + color: #5f5fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-62 { + background-color: #5f5fd7; } + #ex-debug-toolbar .terminal .xterm-color-63 { + color: #5f5fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-63 { + background-color: #5f5fff; } + #ex-debug-toolbar .terminal .xterm-color-64 { + color: #5f8700; } + #ex-debug-toolbar .terminal .xterm-bg-color-64 { + background-color: #5f8700; } + #ex-debug-toolbar .terminal .xterm-color-65 { + color: #5f875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-65 { + background-color: #5f875f; } + #ex-debug-toolbar .terminal .xterm-color-66 { + color: #5f8787; } + #ex-debug-toolbar .terminal .xterm-bg-color-66 { + background-color: #5f8787; } + #ex-debug-toolbar .terminal .xterm-color-67 { + color: #5f87af; } + #ex-debug-toolbar .terminal .xterm-bg-color-67 { + background-color: #5f87af; } + #ex-debug-toolbar .terminal .xterm-color-68 { + color: #5f87d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-68 { + background-color: #5f87d7; } + #ex-debug-toolbar .terminal .xterm-color-69 { + color: #5f87ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-69 { + background-color: #5f87ff; } + #ex-debug-toolbar .terminal .xterm-color-70 { + color: #5faf00; } + #ex-debug-toolbar .terminal .xterm-bg-color-70 { + background-color: #5faf00; } + #ex-debug-toolbar .terminal .xterm-color-71 { + color: #5faf5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-71 { + background-color: #5faf5f; } + #ex-debug-toolbar .terminal .xterm-color-72 { + color: #5faf87; } + #ex-debug-toolbar .terminal .xterm-bg-color-72 { + background-color: #5faf87; } + #ex-debug-toolbar .terminal .xterm-color-73 { + color: #5fafaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-73 { + background-color: #5fafaf; } + #ex-debug-toolbar .terminal .xterm-color-74 { + color: #5fafd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-74 { + background-color: #5fafd7; } + #ex-debug-toolbar .terminal .xterm-color-75 { + color: #5fafff; } + #ex-debug-toolbar .terminal .xterm-bg-color-75 { + background-color: #5fafff; } + #ex-debug-toolbar .terminal .xterm-color-76 { + color: #5fd700; } + #ex-debug-toolbar .terminal .xterm-bg-color-76 { + background-color: #5fd700; } + #ex-debug-toolbar .terminal .xterm-color-77 { + color: #5fd75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-77 { + background-color: #5fd75f; } + #ex-debug-toolbar .terminal .xterm-color-78 { + color: #5fd787; } + #ex-debug-toolbar .terminal .xterm-bg-color-78 { + background-color: #5fd787; } + #ex-debug-toolbar .terminal .xterm-color-79 { + color: #5fd7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-79 { + background-color: #5fd7af; } + #ex-debug-toolbar .terminal .xterm-color-80 { + color: #5fd7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-80 { + background-color: #5fd7d7; } + #ex-debug-toolbar .terminal .xterm-color-81 { + color: #5fd7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-81 { + background-color: #5fd7ff; } + #ex-debug-toolbar .terminal .xterm-color-82 { + color: #5fff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-82 { + background-color: #5fff00; } + #ex-debug-toolbar .terminal .xterm-color-83 { + color: #5fff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-83 { + background-color: #5fff5f; } + #ex-debug-toolbar .terminal .xterm-color-84 { + color: #5fff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-84 { + background-color: #5fff87; } + #ex-debug-toolbar .terminal .xterm-color-85 { + color: #5fffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-85 { + background-color: #5fffaf; } + #ex-debug-toolbar .terminal .xterm-color-86 { + color: #5fffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-86 { + background-color: #5fffd7; } + #ex-debug-toolbar .terminal .xterm-color-87 { + color: #5fffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-87 { + background-color: #5fffff; } + #ex-debug-toolbar .terminal .xterm-color-88 { + color: #870000; } + #ex-debug-toolbar .terminal .xterm-bg-color-88 { + background-color: #870000; } + #ex-debug-toolbar .terminal .xterm-color-89 { + color: #87005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-89 { + background-color: #87005f; } + #ex-debug-toolbar .terminal .xterm-color-90 { + color: #870087; } + #ex-debug-toolbar .terminal .xterm-bg-color-90 { + background-color: #870087; } + #ex-debug-toolbar .terminal .xterm-color-91 { + color: #8700af; } + #ex-debug-toolbar .terminal .xterm-bg-color-91 { + background-color: #8700af; } + #ex-debug-toolbar .terminal .xterm-color-92 { + color: #8700d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-92 { + background-color: #8700d7; } + #ex-debug-toolbar .terminal .xterm-color-93 { + color: #8700ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-93 { + background-color: #8700ff; } + #ex-debug-toolbar .terminal .xterm-color-94 { + color: #875f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-94 { + background-color: #875f00; } + #ex-debug-toolbar .terminal .xterm-color-95 { + color: #875f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-95 { + background-color: #875f5f; } + #ex-debug-toolbar .terminal .xterm-color-96 { + color: #875f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-96 { + background-color: #875f87; } + #ex-debug-toolbar .terminal .xterm-color-97 { + color: #875faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-97 { + background-color: #875faf; } + #ex-debug-toolbar .terminal .xterm-color-98 { + color: #875fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-98 { + background-color: #875fd7; } + #ex-debug-toolbar .terminal .xterm-color-99 { + color: #875fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-99 { + background-color: #875fff; } + #ex-debug-toolbar .terminal .xterm-color-100 { + color: #878700; } + #ex-debug-toolbar .terminal .xterm-bg-color-100 { + background-color: #878700; } + #ex-debug-toolbar .terminal .xterm-color-101 { + color: #87875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-101 { + background-color: #87875f; } + #ex-debug-toolbar .terminal .xterm-color-102 { + color: #878787; } + #ex-debug-toolbar .terminal .xterm-bg-color-102 { + background-color: #878787; } + #ex-debug-toolbar .terminal .xterm-color-103 { + color: #8787af; } + #ex-debug-toolbar .terminal .xterm-bg-color-103 { + background-color: #8787af; } + #ex-debug-toolbar .terminal .xterm-color-104 { + color: #8787d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-104 { + background-color: #8787d7; } + #ex-debug-toolbar .terminal .xterm-color-105 { + color: #8787ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-105 { + background-color: #8787ff; } + #ex-debug-toolbar .terminal .xterm-color-106 { + color: #87af00; } + #ex-debug-toolbar .terminal .xterm-bg-color-106 { + background-color: #87af00; } + #ex-debug-toolbar .terminal .xterm-color-107 { + color: #87af5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-107 { + background-color: #87af5f; } + #ex-debug-toolbar .terminal .xterm-color-108 { + color: #87af87; } + #ex-debug-toolbar .terminal .xterm-bg-color-108 { + background-color: #87af87; } + #ex-debug-toolbar .terminal .xterm-color-109 { + color: #87afaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-109 { + background-color: #87afaf; } + #ex-debug-toolbar .terminal .xterm-color-110 { + color: #87afd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-110 { + background-color: #87afd7; } + #ex-debug-toolbar .terminal .xterm-color-111 { + color: #87afff; } + #ex-debug-toolbar .terminal .xterm-bg-color-111 { + background-color: #87afff; } + #ex-debug-toolbar .terminal .xterm-color-112 { + color: #87d700; } + #ex-debug-toolbar .terminal .xterm-bg-color-112 { + background-color: #87d700; } + #ex-debug-toolbar .terminal .xterm-color-113 { + color: #87d75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-113 { + background-color: #87d75f; } + #ex-debug-toolbar .terminal .xterm-color-114 { + color: #87d787; } + #ex-debug-toolbar .terminal .xterm-bg-color-114 { + background-color: #87d787; } + #ex-debug-toolbar .terminal .xterm-color-115 { + color: #87d7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-115 { + background-color: #87d7af; } + #ex-debug-toolbar .terminal .xterm-color-116 { + color: #87d7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-116 { + background-color: #87d7d7; } + #ex-debug-toolbar .terminal .xterm-color-117 { + color: #87d7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-117 { + background-color: #87d7ff; } + #ex-debug-toolbar .terminal .xterm-color-118 { + color: #87ff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-118 { + background-color: #87ff00; } + #ex-debug-toolbar .terminal .xterm-color-119 { + color: #87ff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-119 { + background-color: #87ff5f; } + #ex-debug-toolbar .terminal .xterm-color-120 { + color: #87ff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-120 { + background-color: #87ff87; } + #ex-debug-toolbar .terminal .xterm-color-121 { + color: #87ffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-121 { + background-color: #87ffaf; } + #ex-debug-toolbar .terminal .xterm-color-122 { + color: #87ffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-122 { + background-color: #87ffd7; } + #ex-debug-toolbar .terminal .xterm-color-123 { + color: #87ffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-123 { + background-color: #87ffff; } + #ex-debug-toolbar .terminal .xterm-color-124 { + color: #af0000; } + #ex-debug-toolbar .terminal .xterm-bg-color-124 { + background-color: #af0000; } + #ex-debug-toolbar .terminal .xterm-color-125 { + color: #af005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-125 { + background-color: #af005f; } + #ex-debug-toolbar .terminal .xterm-color-126 { + color: #af0087; } + #ex-debug-toolbar .terminal .xterm-bg-color-126 { + background-color: #af0087; } + #ex-debug-toolbar .terminal .xterm-color-127 { + color: #af00af; } + #ex-debug-toolbar .terminal .xterm-bg-color-127 { + background-color: #af00af; } + #ex-debug-toolbar .terminal .xterm-color-128 { + color: #af00d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-128 { + background-color: #af00d7; } + #ex-debug-toolbar .terminal .xterm-color-129 { + color: #af00ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-129 { + background-color: #af00ff; } + #ex-debug-toolbar .terminal .xterm-color-130 { + color: #af5f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-130 { + background-color: #af5f00; } + #ex-debug-toolbar .terminal .xterm-color-131 { + color: #af5f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-131 { + background-color: #af5f5f; } + #ex-debug-toolbar .terminal .xterm-color-132 { + color: #af5f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-132 { + background-color: #af5f87; } + #ex-debug-toolbar .terminal .xterm-color-133 { + color: #af5faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-133 { + background-color: #af5faf; } + #ex-debug-toolbar .terminal .xterm-color-134 { + color: #af5fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-134 { + background-color: #af5fd7; } + #ex-debug-toolbar .terminal .xterm-color-135 { + color: #af5fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-135 { + background-color: #af5fff; } + #ex-debug-toolbar .terminal .xterm-color-136 { + color: #af8700; } + #ex-debug-toolbar .terminal .xterm-bg-color-136 { + background-color: #af8700; } + #ex-debug-toolbar .terminal .xterm-color-137 { + color: #af875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-137 { + background-color: #af875f; } + #ex-debug-toolbar .terminal .xterm-color-138 { + color: #af8787; } + #ex-debug-toolbar .terminal .xterm-bg-color-138 { + background-color: #af8787; } + #ex-debug-toolbar .terminal .xterm-color-139 { + color: #af87af; } + #ex-debug-toolbar .terminal .xterm-bg-color-139 { + background-color: #af87af; } + #ex-debug-toolbar .terminal .xterm-color-140 { + color: #af87d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-140 { + background-color: #af87d7; } + #ex-debug-toolbar .terminal .xterm-color-141 { + color: #af87ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-141 { + background-color: #af87ff; } + #ex-debug-toolbar .terminal .xterm-color-142 { + color: #afaf00; } + #ex-debug-toolbar .terminal .xterm-bg-color-142 { + background-color: #afaf00; } + #ex-debug-toolbar .terminal .xterm-color-143 { + color: #afaf5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-143 { + background-color: #afaf5f; } + #ex-debug-toolbar .terminal .xterm-color-144 { + color: #afaf87; } + #ex-debug-toolbar .terminal .xterm-bg-color-144 { + background-color: #afaf87; } + #ex-debug-toolbar .terminal .xterm-color-145 { + color: #afafaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-145 { + background-color: #afafaf; } + #ex-debug-toolbar .terminal .xterm-color-146 { + color: #afafd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-146 { + background-color: #afafd7; } + #ex-debug-toolbar .terminal .xterm-color-147 { + color: #afafff; } + #ex-debug-toolbar .terminal .xterm-bg-color-147 { + background-color: #afafff; } + #ex-debug-toolbar .terminal .xterm-color-148 { + color: #afd700; } + #ex-debug-toolbar .terminal .xterm-bg-color-148 { + background-color: #afd700; } + #ex-debug-toolbar .terminal .xterm-color-149 { + color: #afd75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-149 { + background-color: #afd75f; } + #ex-debug-toolbar .terminal .xterm-color-150 { + color: #afd787; } + #ex-debug-toolbar .terminal .xterm-bg-color-150 { + background-color: #afd787; } + #ex-debug-toolbar .terminal .xterm-color-151 { + color: #afd7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-151 { + background-color: #afd7af; } + #ex-debug-toolbar .terminal .xterm-color-152 { + color: #afd7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-152 { + background-color: #afd7d7; } + #ex-debug-toolbar .terminal .xterm-color-153 { + color: #afd7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-153 { + background-color: #afd7ff; } + #ex-debug-toolbar .terminal .xterm-color-154 { + color: #afff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-154 { + background-color: #afff00; } + #ex-debug-toolbar .terminal .xterm-color-155 { + color: #afff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-155 { + background-color: #afff5f; } + #ex-debug-toolbar .terminal .xterm-color-156 { + color: #afff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-156 { + background-color: #afff87; } + #ex-debug-toolbar .terminal .xterm-color-157 { + color: #afffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-157 { + background-color: #afffaf; } + #ex-debug-toolbar .terminal .xterm-color-158 { + color: #afffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-158 { + background-color: #afffd7; } + #ex-debug-toolbar .terminal .xterm-color-159 { + color: #afffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-159 { + background-color: #afffff; } + #ex-debug-toolbar .terminal .xterm-color-160 { + color: #d70000; } + #ex-debug-toolbar .terminal .xterm-bg-color-160 { + background-color: #d70000; } + #ex-debug-toolbar .terminal .xterm-color-161 { + color: #d7005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-161 { + background-color: #d7005f; } + #ex-debug-toolbar .terminal .xterm-color-162 { + color: #d70087; } + #ex-debug-toolbar .terminal .xterm-bg-color-162 { + background-color: #d70087; } + #ex-debug-toolbar .terminal .xterm-color-163 { + color: #d700af; } + #ex-debug-toolbar .terminal .xterm-bg-color-163 { + background-color: #d700af; } + #ex-debug-toolbar .terminal .xterm-color-164 { + color: #d700d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-164 { + background-color: #d700d7; } + #ex-debug-toolbar .terminal .xterm-color-165 { + color: #d700ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-165 { + background-color: #d700ff; } + #ex-debug-toolbar .terminal .xterm-color-166 { + color: #d75f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-166 { + background-color: #d75f00; } + #ex-debug-toolbar .terminal .xterm-color-167 { + color: #d75f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-167 { + background-color: #d75f5f; } + #ex-debug-toolbar .terminal .xterm-color-168 { + color: #d75f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-168 { + background-color: #d75f87; } + #ex-debug-toolbar .terminal .xterm-color-169 { + color: #d75faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-169 { + background-color: #d75faf; } + #ex-debug-toolbar .terminal .xterm-color-170 { + color: #d75fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-170 { + background-color: #d75fd7; } + #ex-debug-toolbar .terminal .xterm-color-171 { + color: #d75fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-171 { + background-color: #d75fff; } + #ex-debug-toolbar .terminal .xterm-color-172 { + color: #d78700; } + #ex-debug-toolbar .terminal .xterm-bg-color-172 { + background-color: #d78700; } + #ex-debug-toolbar .terminal .xterm-color-173 { + color: #d7875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-173 { + background-color: #d7875f; } + #ex-debug-toolbar .terminal .xterm-color-174 { + color: #d78787; } + #ex-debug-toolbar .terminal .xterm-bg-color-174 { + background-color: #d78787; } + #ex-debug-toolbar .terminal .xterm-color-175 { + color: #d787af; } + #ex-debug-toolbar .terminal .xterm-bg-color-175 { + background-color: #d787af; } + #ex-debug-toolbar .terminal .xterm-color-176 { + color: #d787d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-176 { + background-color: #d787d7; } + #ex-debug-toolbar .terminal .xterm-color-177 { + color: #d787ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-177 { + background-color: #d787ff; } + #ex-debug-toolbar .terminal .xterm-color-178 { + color: #d7af00; } + #ex-debug-toolbar .terminal .xterm-bg-color-178 { + background-color: #d7af00; } + #ex-debug-toolbar .terminal .xterm-color-179 { + color: #d7af5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-179 { + background-color: #d7af5f; } + #ex-debug-toolbar .terminal .xterm-color-180 { + color: #d7af87; } + #ex-debug-toolbar .terminal .xterm-bg-color-180 { + background-color: #d7af87; } + #ex-debug-toolbar .terminal .xterm-color-181 { + color: #d7afaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-181 { + background-color: #d7afaf; } + #ex-debug-toolbar .terminal .xterm-color-182 { + color: #d7afd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-182 { + background-color: #d7afd7; } + #ex-debug-toolbar .terminal .xterm-color-183 { + color: #d7afff; } + #ex-debug-toolbar .terminal .xterm-bg-color-183 { + background-color: #d7afff; } + #ex-debug-toolbar .terminal .xterm-color-184 { + color: #d7d700; } + #ex-debug-toolbar .terminal .xterm-bg-color-184 { + background-color: #d7d700; } + #ex-debug-toolbar .terminal .xterm-color-185 { + color: #d7d75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-185 { + background-color: #d7d75f; } + #ex-debug-toolbar .terminal .xterm-color-186 { + color: #d7d787; } + #ex-debug-toolbar .terminal .xterm-bg-color-186 { + background-color: #d7d787; } + #ex-debug-toolbar .terminal .xterm-color-187 { + color: #d7d7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-187 { + background-color: #d7d7af; } + #ex-debug-toolbar .terminal .xterm-color-188 { + color: #d7d7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-188 { + background-color: #d7d7d7; } + #ex-debug-toolbar .terminal .xterm-color-189 { + color: #d7d7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-189 { + background-color: #d7d7ff; } + #ex-debug-toolbar .terminal .xterm-color-190 { + color: #d7ff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-190 { + background-color: #d7ff00; } + #ex-debug-toolbar .terminal .xterm-color-191 { + color: #d7ff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-191 { + background-color: #d7ff5f; } + #ex-debug-toolbar .terminal .xterm-color-192 { + color: #d7ff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-192 { + background-color: #d7ff87; } + #ex-debug-toolbar .terminal .xterm-color-193 { + color: #d7ffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-193 { + background-color: #d7ffaf; } + #ex-debug-toolbar .terminal .xterm-color-194 { + color: #d7ffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-194 { + background-color: #d7ffd7; } + #ex-debug-toolbar .terminal .xterm-color-195 { + color: #d7ffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-195 { + background-color: #d7ffff; } + #ex-debug-toolbar .terminal .xterm-color-196 { + color: #ff0000; } + #ex-debug-toolbar .terminal .xterm-bg-color-196 { + background-color: #ff0000; } + #ex-debug-toolbar .terminal .xterm-color-197 { + color: #ff005f; } + #ex-debug-toolbar .terminal .xterm-bg-color-197 { + background-color: #ff005f; } + #ex-debug-toolbar .terminal .xterm-color-198 { + color: #ff0087; } + #ex-debug-toolbar .terminal .xterm-bg-color-198 { + background-color: #ff0087; } + #ex-debug-toolbar .terminal .xterm-color-199 { + color: #ff00af; } + #ex-debug-toolbar .terminal .xterm-bg-color-199 { + background-color: #ff00af; } + #ex-debug-toolbar .terminal .xterm-color-200 { + color: #ff00d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-200 { + background-color: #ff00d7; } + #ex-debug-toolbar .terminal .xterm-color-201 { + color: #ff00ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-201 { + background-color: #ff00ff; } + #ex-debug-toolbar .terminal .xterm-color-202 { + color: #ff5f00; } + #ex-debug-toolbar .terminal .xterm-bg-color-202 { + background-color: #ff5f00; } + #ex-debug-toolbar .terminal .xterm-color-203 { + color: #ff5f5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-203 { + background-color: #ff5f5f; } + #ex-debug-toolbar .terminal .xterm-color-204 { + color: #ff5f87; } + #ex-debug-toolbar .terminal .xterm-bg-color-204 { + background-color: #ff5f87; } + #ex-debug-toolbar .terminal .xterm-color-205 { + color: #ff5faf; } + #ex-debug-toolbar .terminal .xterm-bg-color-205 { + background-color: #ff5faf; } + #ex-debug-toolbar .terminal .xterm-color-206 { + color: #ff5fd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-206 { + background-color: #ff5fd7; } + #ex-debug-toolbar .terminal .xterm-color-207 { + color: #ff5fff; } + #ex-debug-toolbar .terminal .xterm-bg-color-207 { + background-color: #ff5fff; } + #ex-debug-toolbar .terminal .xterm-color-208 { + color: #ff8700; } + #ex-debug-toolbar .terminal .xterm-bg-color-208 { + background-color: #ff8700; } + #ex-debug-toolbar .terminal .xterm-color-209 { + color: #ff875f; } + #ex-debug-toolbar .terminal .xterm-bg-color-209 { + background-color: #ff875f; } + #ex-debug-toolbar .terminal .xterm-color-210 { + color: #ff8787; } + #ex-debug-toolbar .terminal .xterm-bg-color-210 { + background-color: #ff8787; } + #ex-debug-toolbar .terminal .xterm-color-211 { + color: #ff87af; } + #ex-debug-toolbar .terminal .xterm-bg-color-211 { + background-color: #ff87af; } + #ex-debug-toolbar .terminal .xterm-color-212 { + color: #ff87d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-212 { + background-color: #ff87d7; } + #ex-debug-toolbar .terminal .xterm-color-213 { + color: #ff87ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-213 { + background-color: #ff87ff; } + #ex-debug-toolbar .terminal .xterm-color-214 { + color: #ffaf00; } + #ex-debug-toolbar .terminal .xterm-bg-color-214 { + background-color: #ffaf00; } + #ex-debug-toolbar .terminal .xterm-color-215 { + color: #ffaf5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-215 { + background-color: #ffaf5f; } + #ex-debug-toolbar .terminal .xterm-color-216 { + color: #ffaf87; } + #ex-debug-toolbar .terminal .xterm-bg-color-216 { + background-color: #ffaf87; } + #ex-debug-toolbar .terminal .xterm-color-217 { + color: #ffafaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-217 { + background-color: #ffafaf; } + #ex-debug-toolbar .terminal .xterm-color-218 { + color: #ffafd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-218 { + background-color: #ffafd7; } + #ex-debug-toolbar .terminal .xterm-color-219 { + color: #ffafff; } + #ex-debug-toolbar .terminal .xterm-bg-color-219 { + background-color: #ffafff; } + #ex-debug-toolbar .terminal .xterm-color-220 { + color: #ffd700; } + #ex-debug-toolbar .terminal .xterm-bg-color-220 { + background-color: #ffd700; } + #ex-debug-toolbar .terminal .xterm-color-221 { + color: #ffd75f; } + #ex-debug-toolbar .terminal .xterm-bg-color-221 { + background-color: #ffd75f; } + #ex-debug-toolbar .terminal .xterm-color-222 { + color: #ffd787; } + #ex-debug-toolbar .terminal .xterm-bg-color-222 { + background-color: #ffd787; } + #ex-debug-toolbar .terminal .xterm-color-223 { + color: #ffd7af; } + #ex-debug-toolbar .terminal .xterm-bg-color-223 { + background-color: #ffd7af; } + #ex-debug-toolbar .terminal .xterm-color-224 { + color: #ffd7d7; } + #ex-debug-toolbar .terminal .xterm-bg-color-224 { + background-color: #ffd7d7; } + #ex-debug-toolbar .terminal .xterm-color-225 { + color: #ffd7ff; } + #ex-debug-toolbar .terminal .xterm-bg-color-225 { + background-color: #ffd7ff; } + #ex-debug-toolbar .terminal .xterm-color-226 { + color: #ffff00; } + #ex-debug-toolbar .terminal .xterm-bg-color-226 { + background-color: #ffff00; } + #ex-debug-toolbar .terminal .xterm-color-227 { + color: #ffff5f; } + #ex-debug-toolbar .terminal .xterm-bg-color-227 { + background-color: #ffff5f; } + #ex-debug-toolbar .terminal .xterm-color-228 { + color: #ffff87; } + #ex-debug-toolbar .terminal .xterm-bg-color-228 { + background-color: #ffff87; } + #ex-debug-toolbar .terminal .xterm-color-229 { + color: #ffffaf; } + #ex-debug-toolbar .terminal .xterm-bg-color-229 { + background-color: #ffffaf; } + #ex-debug-toolbar .terminal .xterm-color-230 { + color: #ffffd7; } + #ex-debug-toolbar .terminal .xterm-bg-color-230 { + background-color: #ffffd7; } + #ex-debug-toolbar .terminal .xterm-color-231 { + color: #ffffff; } + #ex-debug-toolbar .terminal .xterm-bg-color-231 { + background-color: #ffffff; } + #ex-debug-toolbar .terminal .xterm-color-232 { + color: #080808; } + #ex-debug-toolbar .terminal .xterm-bg-color-232 { + background-color: #080808; } + #ex-debug-toolbar .terminal .xterm-color-233 { + color: #121212; } + #ex-debug-toolbar .terminal .xterm-bg-color-233 { + background-color: #121212; } + #ex-debug-toolbar .terminal .xterm-color-234 { + color: #1c1c1c; } + #ex-debug-toolbar .terminal .xterm-bg-color-234 { + background-color: #1c1c1c; } + #ex-debug-toolbar .terminal .xterm-color-235 { + color: #262626; } + #ex-debug-toolbar .terminal .xterm-bg-color-235 { + background-color: #262626; } + #ex-debug-toolbar .terminal .xterm-color-236 { + color: #303030; } + #ex-debug-toolbar .terminal .xterm-bg-color-236 { + background-color: #303030; } + #ex-debug-toolbar .terminal .xterm-color-237 { + color: #3a3a3a; } + #ex-debug-toolbar .terminal .xterm-bg-color-237 { + background-color: #3a3a3a; } + #ex-debug-toolbar .terminal .xterm-color-238 { + color: #444444; } + #ex-debug-toolbar .terminal .xterm-bg-color-238 { + background-color: #444444; } + #ex-debug-toolbar .terminal .xterm-color-239 { + color: #4e4e4e; } + #ex-debug-toolbar .terminal .xterm-bg-color-239 { + background-color: #4e4e4e; } + #ex-debug-toolbar .terminal .xterm-color-240 { + color: #585858; } + #ex-debug-toolbar .terminal .xterm-bg-color-240 { + background-color: #585858; } + #ex-debug-toolbar .terminal .xterm-color-241 { + color: #626262; } + #ex-debug-toolbar .terminal .xterm-bg-color-241 { + background-color: #626262; } + #ex-debug-toolbar .terminal .xterm-color-242 { + color: #6c6c6c; } + #ex-debug-toolbar .terminal .xterm-bg-color-242 { + background-color: #6c6c6c; } + #ex-debug-toolbar .terminal .xterm-color-243 { + color: #767676; } + #ex-debug-toolbar .terminal .xterm-bg-color-243 { + background-color: #767676; } + #ex-debug-toolbar .terminal .xterm-color-244 { + color: #808080; } + #ex-debug-toolbar .terminal .xterm-bg-color-244 { + background-color: #808080; } + #ex-debug-toolbar .terminal .xterm-color-245 { + color: #8a8a8a; } + #ex-debug-toolbar .terminal .xterm-bg-color-245 { + background-color: #8a8a8a; } + #ex-debug-toolbar .terminal .xterm-color-246 { + color: #949494; } + #ex-debug-toolbar .terminal .xterm-bg-color-246 { + background-color: #949494; } + #ex-debug-toolbar .terminal .xterm-color-247 { + color: #9e9e9e; } + #ex-debug-toolbar .terminal .xterm-bg-color-247 { + background-color: #9e9e9e; } + #ex-debug-toolbar .terminal .xterm-color-248 { + color: #a8a8a8; } + #ex-debug-toolbar .terminal .xterm-bg-color-248 { + background-color: #a8a8a8; } + #ex-debug-toolbar .terminal .xterm-color-249 { + color: #b2b2b2; } + #ex-debug-toolbar .terminal .xterm-bg-color-249 { + background-color: #b2b2b2; } + #ex-debug-toolbar .terminal .xterm-color-250 { + color: #bcbcbc; } + #ex-debug-toolbar .terminal .xterm-bg-color-250 { + background-color: #bcbcbc; } + #ex-debug-toolbar .terminal .xterm-color-251 { + color: #c6c6c6; } + #ex-debug-toolbar .terminal .xterm-bg-color-251 { + background-color: #c6c6c6; } + #ex-debug-toolbar .terminal .xterm-color-252 { + color: #d0d0d0; } + #ex-debug-toolbar .terminal .xterm-bg-color-252 { + background-color: #d0d0d0; } + #ex-debug-toolbar .terminal .xterm-color-253 { + color: #dadada; } + #ex-debug-toolbar .terminal .xterm-bg-color-253 { + background-color: #dadada; } + #ex-debug-toolbar .terminal .xterm-color-254 { + color: #e4e4e4; } + #ex-debug-toolbar .terminal .xterm-bg-color-254 { + background-color: #e4e4e4; } + #ex-debug-toolbar .terminal .xterm-color-255 { + color: #eeeeee; } + #ex-debug-toolbar .terminal .xterm-bg-color-255 { + background-color: #eeeeee; } + #ex-debug-toolbar .xterm.fullscreen { + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: auto; + height: auto; + z-index: 255; } + #ex-debug-toolbar .navbar { + min-height: 30px; + height: 30px; } + #ex-debug-toolbar .navbar-nav.nav > li > span { + padding-left: 5px; + padding-right: 5px; + padding-top: 5px; + cursor: pointer; } + #ex-debug-toolbar .navbar-nav.nav > li > span > i { + margin-right: 5px; } + #ex-debug-toolbar .navbar-brand { + padding: 2px 2px; + height: 30px; } + #ex-debug-toolbar .navbar-brand img { + height: 100%; } + #ex-debug-toolbar .toolbar-item { + margin-right: 5px; } + #ex-debug-toolbar .toolbar-item .label { + position: relative; + top: -2px; } + #ex-debug-toolbar .panel { + margin-bottom: 0; + bottom: 30px; + display: none; } + #ex-debug-toolbar .panel .panel-body { + padding: 5px 15px; + max-height: 200px; + overflow-y: auto; } + #ex-debug-toolbar .panel .panel-heading { + padding: 5px 15px; } + #ex-debug-toolbar .panel .table { + margin-top: 0; + margin-bottom: 0; } + #ex-debug-toolbar .panel .table caption { + padding-top: 4px; + padding-bottom: 4px; } + #ex-debug-toolbar .panel .table td, #ex-debug-toolbar .panel .table th { + padding-left: 5px; + padding-right: 5px; + padding-top: 1px; + padding-bottom: 1px; } + #ex-debug-toolbar .panel .table td p, #ex-debug-toolbar .panel .table th p { + margin: 0; } + #ex-debug-toolbar .nowrap { + white-space: nowrap; } + #ex-debug-toolbar table .hljs { + background: unset; + padding: unset; } + #ex-debug-toolbar .pointer { + cursor: pointer; } + #ex-debug-toolbar #terminal-container { + width: auto; + height: 480px; } + #ex-debug-toolbar .modal-top-action { + margin-right: 10px; } + #ex-debug-toolbar .fullscreen .modal-dialog { + width: 100%; + height: 100%; + margin: 0; + padding: 0; } + #ex-debug-toolbar .fullscreen .modal-content { + height: auto; + min-height: 100%; + border-radius: 0; } + #ex-debug-toolbar .fullscreen #terminal-container { + height: 100%; } + #ex-debug-toolbar .xterm.fullscreen { + top: 55px; } + #ex-debug-toolbar #code-snippet-container { + margin-top: 40px; + position: fixed; + left: 50%; } + #ex-debug-toolbar #breakpoint .panel-body { + height: 200px; } + #ex-debug-toolbar .historic-flag { + display: none; } + #ex-debug-toolbar .historic-flag .back-to-current-request { + font-weight: bold; + color: black; + font-size: 0.85em; + text-decoration: underline; } + #ex-debug-toolbar .historic-request .historic-flag { + display: block; } + #ex-debug-toolbar .historic-request .navbar { + background-color: #ececdb; } + #ex-debug-toolbar .history-point { + cursor: pointer; } + #ex-debug-toolbar .history-point.active { + cursor: default; } + #ex-debug-toolbar .history-point.prev-request { + display: none; } + #ex-debug-toolbar .history-point .history-collapse { + display: none; } + + +/*# sourceMappingURL=toolbar.css.map*/ \ No newline at end of file diff --git a/priv/static/js/toolbar.js b/priv/static/js/toolbar.js index c5c417d..c56f622 100644 --- a/priv/static/js/toolbar.js +++ b/priv/static/js/toolbar.js @@ -1,9 +1,21225 @@ -!function(){"use strict";var t="undefined"==typeof window?global:window;if("function"!=typeof t.require){var e={},n={},i={},r={}.hasOwnProperty,s=/^\.\.?(\/|$)/,o=function(t,e){for(var n,i=[],r=(s.test(e)?t+"/"+e:e).split("/"),o=0,a=r.length;o3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(t){"use strict";function e(){var t=document.createElement("bootstrap"),e={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var n in e)if(void 0!==t.style[n])return{end:e[n]};return!1}t.fn.emulateTransitionEnd=function(e){var n=!1,i=this;t(this).one("bsTransitionEnd",function(){n=!0});var r=function(){n||t(i).trigger(t.support.transition.end)};return setTimeout(r,e),this},t(function(){t.support.transition=e(),t.support.transition&&(t.event.special.bsTransitionEnd={bindType:t.support.transition.end,delegateType:t.support.transition.end,handle:function(e){if(t(e.target).is(this))return e.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var n=t(this),r=n.data("bs.alert");r||n.data("bs.alert",r=new i(this)),"string"==typeof e&&r[e].call(n)})}var n='[data-dismiss="alert"]',i=function(e){t(e).on("click",n,this.close)};i.VERSION="3.3.7",i.TRANSITION_DURATION=150,i.prototype.close=function(e){function n(){o.detach().trigger("closed.bs.alert").remove()}var r=t(this),s=r.attr("data-target");s||(s=r.attr("href"),s=s&&s.replace(/.*(?=#[^\s]*$)/,""));var o=t("#"===s?[]:s);e&&e.preventDefault(),o.length||(o=r.closest(".alert")),o.trigger(e=t.Event("close.bs.alert")),e.isDefaultPrevented()||(o.removeClass("in"),t.support.transition&&o.hasClass("fade")?o.one("bsTransitionEnd",n).emulateTransitionEnd(i.TRANSITION_DURATION):n())};var r=t.fn.alert;t.fn.alert=e,t.fn.alert.Constructor=i,t.fn.alert.noConflict=function(){return t.fn.alert=r,this},t(document).on("click.bs.alert.data-api",n,i.prototype.close)}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),r=i.data("bs.button"),s="object"==typeof e&&e;r||i.data("bs.button",r=new n(this,s)),"toggle"==e?r.toggle():e&&r.setState(e)})}var n=function(e,i){this.$element=t(e),this.options=t.extend({},n.DEFAULTS,i),this.isLoading=!1};n.VERSION="3.3.7",n.DEFAULTS={loadingText:"loading..."},n.prototype.setState=function(e){var n="disabled",i=this.$element,r=i.is("input")?"val":"html",s=i.data();e+="Text",null==s.resetText&&i.data("resetText",i[r]()),setTimeout(t.proxy(function(){i[r](null==s[e]?this.options[e]:s[e]),"loadingText"==e?(this.isLoading=!0,i.addClass(n).attr(n,n).prop(n,!0)):this.isLoading&&(this.isLoading=!1,i.removeClass(n).removeAttr(n).prop(n,!1))},this),0)},n.prototype.toggle=function(){var t=!0,e=this.$element.closest('[data-toggle="buttons"]');if(e.length){var n=this.$element.find("input");"radio"==n.prop("type")?(n.prop("checked")&&(t=!1),e.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==n.prop("type")&&(n.prop("checked")!==this.$element.hasClass("active")&&(t=!1),this.$element.toggleClass("active")),n.prop("checked",this.$element.hasClass("active")),t&&n.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var i=t.fn.button;t.fn.button=e,t.fn.button.Constructor=n,t.fn.button.noConflict=function(){return t.fn.button=i,this},t(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(n){var i=t(n.target).closest(".btn");e.call(i,"toggle"),t(n.target).is('input[type="radio"], input[type="checkbox"]')||(n.preventDefault(),i.is("input,button")?i.trigger("focus"):i.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(e){t(e.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(e.type))})}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),r=i.data("bs.carousel"),s=t.extend({},n.DEFAULTS,i.data(),"object"==typeof e&&e),o="string"==typeof e?e:s.slide;r||i.data("bs.carousel",r=new n(this,s)),"number"==typeof e?r.to(e):o?r[o]():s.interval&&r.pause().cycle()})}var n=function(e,n){this.$element=t(e),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",t.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",t.proxy(this.pause,this)).on("mouseleave.bs.carousel",t.proxy(this.cycle,this))};n.VERSION="3.3.7",n.TRANSITION_DURATION=600,n.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},n.prototype.keydown=function(t){if(!/input|textarea/i.test(t.target.tagName)){switch(t.which){case 37:this.prev();break;case 39:this.next();break;default:return}t.preventDefault()}},n.prototype.cycle=function(e){return e||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(t.proxy(this.next,this),this.options.interval)),this},n.prototype.getItemIndex=function(t){return this.$items=t.parent().children(".item"),this.$items.index(t||this.$active)},n.prototype.getItemForDirection=function(t,e){var n=this.getItemIndex(e),i="prev"==t&&0===n||"next"==t&&n==this.$items.length-1;if(i&&!this.options.wrap)return e;var r="prev"==t?-1:1,s=(n+r)%this.$items.length;return this.$items.eq(s)},n.prototype.to=function(t){var e=this,n=this.getItemIndex(this.$active=this.$element.find(".item.active"));if(!(t>this.$items.length-1||t<0))return this.sliding?this.$element.one("slid.bs.carousel",function(){e.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",this.$items.eq(t))},n.prototype.pause=function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&t.support.transition&&(this.$element.trigger(t.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},n.prototype.next=function(){if(!this.sliding)return this.slide("next")},n.prototype.prev=function(){if(!this.sliding)return this.slide("prev")},n.prototype.slide=function(e,i){var r=this.$element.find(".item.active"),s=i||this.getItemForDirection(e,r),o=this.interval,a="next"==e?"left":"right",l=this;if(s.hasClass("active"))return this.sliding=!1;var c=s[0],u=t.Event("slide.bs.carousel",{relatedTarget:c,direction:a});if(this.$element.trigger(u),!u.isDefaultPrevented()){if(this.sliding=!0,o&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var h=t(this.$indicators.children()[this.getItemIndex(s)]);h&&h.addClass("active")}var f=t.Event("slid.bs.carousel",{relatedTarget:c,direction:a});return t.support.transition&&this.$element.hasClass("slide")?(s.addClass(e),s[0].offsetWidth,r.addClass(a),s.addClass(a),r.one("bsTransitionEnd",function(){s.removeClass([e,a].join(" ")).addClass("active"),r.removeClass(["active",a].join(" ")),l.sliding=!1,setTimeout(function(){l.$element.trigger(f)},0)}).emulateTransitionEnd(n.TRANSITION_DURATION)):(r.removeClass("active"),s.addClass("active"),this.sliding=!1,this.$element.trigger(f)),o&&this.cycle(),this}};var i=t.fn.carousel;t.fn.carousel=e,t.fn.carousel.Constructor=n,t.fn.carousel.noConflict=function(){return t.fn.carousel=i,this};var r=function(n){var i,r=t(this),s=t(r.attr("data-target")||(i=r.attr("href"))&&i.replace(/.*(?=#[^\s]+$)/,""));if(s.hasClass("carousel")){var o=t.extend({},s.data(),r.data()),a=r.attr("data-slide-to");a&&(o.interval=!1),e.call(s,o),a&&s.data("bs.carousel").to(a),n.preventDefault()}};t(document).on("click.bs.carousel.data-api","[data-slide]",r).on("click.bs.carousel.data-api","[data-slide-to]",r),t(window).on("load",function(){t('[data-ride="carousel"]').each(function(){var n=t(this);e.call(n,n.data())})})}(jQuery),+function(t){"use strict";function e(e){var n,i=e.attr("data-target")||(n=e.attr("href"))&&n.replace(/.*(?=#[^\s]+$)/,"");return t(i)}function n(e){return this.each(function(){var n=t(this),r=n.data("bs.collapse"),s=t.extend({},i.DEFAULTS,n.data(),"object"==typeof e&&e);!r&&s.toggle&&/show|hide/.test(e)&&(s.toggle=!1),r||n.data("bs.collapse",r=new i(this,s)),"string"==typeof e&&r[e]()})}var i=function(e,n){this.$element=t(e),this.options=t.extend({},i.DEFAULTS,n),this.$trigger=t('[data-toggle="collapse"][href="#'+e.id+'"],[data-toggle="collapse"][data-target="#'+e.id+'"]'),this.transitioning=null,this.options.parent?this.$parent=this.getParent():this.addAriaAndCollapsedClass(this.$element,this.$trigger),this.options.toggle&&this.toggle()};i.VERSION="3.3.7",i.TRANSITION_DURATION=350,i.DEFAULTS={toggle:!0},i.prototype.dimension=function(){var t=this.$element.hasClass("width");return t?"width":"height"},i.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var e,r=this.$parent&&this.$parent.children(".panel").children(".in, .collapsing");if(!(r&&r.length&&(e=r.data("bs.collapse"),e&&e.transitioning))){var s=t.Event("show.bs.collapse");if(this.$element.trigger(s),!s.isDefaultPrevented()){r&&r.length&&(n.call(r,"hide"),e||r.data("bs.collapse",null));var o=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[o](0).attr("aria-expanded",!0),this.$trigger.removeClass("collapsed").attr("aria-expanded",!0),this.transitioning=1;var a=function(){this.$element.removeClass("collapsing").addClass("collapse in")[o](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!t.support.transition)return a.call(this);var l=t.camelCase(["scroll",o].join("-"));this.$element.one("bsTransitionEnd",t.proxy(a,this)).emulateTransitionEnd(i.TRANSITION_DURATION)[o](this.$element[0][l])}}}},i.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var e=t.Event("hide.bs.collapse");if(this.$element.trigger(e),!e.isDefaultPrevented()){var n=this.dimension();this.$element[n](this.$element[n]())[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 r=function(){this.transitioning=0,this.$element.removeClass("collapsing").addClass("collapse").trigger("hidden.bs.collapse")};return t.support.transition?void this.$element[n](0).one("bsTransitionEnd",t.proxy(r,this)).emulateTransitionEnd(i.TRANSITION_DURATION):r.call(this)}}},i.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()},i.prototype.getParent=function(){return t(this.options.parent).find('[data-toggle="collapse"][data-parent="'+this.options.parent+'"]').each(t.proxy(function(n,i){var r=t(i);this.addAriaAndCollapsedClass(e(r),r)},this)).end()},i.prototype.addAriaAndCollapsedClass=function(t,e){var n=t.hasClass("in");t.attr("aria-expanded",n),e.toggleClass("collapsed",!n).attr("aria-expanded",n)};var r=t.fn.collapse;t.fn.collapse=n,t.fn.collapse.Constructor=i,t.fn.collapse.noConflict=function(){return t.fn.collapse=r,this},t(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(i){var r=t(this);r.attr("data-target")||i.preventDefault();var s=e(r),o=s.data("bs.collapse"),a=o?"toggle":r.data();n.call(s,a)})}(jQuery),+function(t){"use strict";function e(e){var n=e.attr("data-target");n||(n=e.attr("href"),n=n&&/#[A-Za-z]/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,""));var i=n&&t(n);return i&&i.length?i:e.parent()}function n(n){n&&3===n.which||(t(r).remove(),t(s).each(function(){var i=t(this),r=e(i),s={relatedTarget:this};r.hasClass("open")&&(n&&"click"==n.type&&/input|textarea/i.test(n.target.tagName)&&t.contains(r[0],n.target)||(r.trigger(n=t.Event("hide.bs.dropdown",s)),n.isDefaultPrevented()||(i.attr("aria-expanded","false"),r.removeClass("open").trigger(t.Event("hidden.bs.dropdown",s)))))}))}function i(e){return this.each(function(){var n=t(this),i=n.data("bs.dropdown");i||n.data("bs.dropdown",i=new o(this)),"string"==typeof e&&i[e].call(n)})}var r=".dropdown-backdrop",s='[data-toggle="dropdown"]',o=function(e){t(e).on("click.bs.dropdown",this.toggle)};o.VERSION="3.3.7",o.prototype.toggle=function(i){var r=t(this);if(!r.is(".disabled, :disabled")){var s=e(r),o=s.hasClass("open");if(n(),!o){"ontouchstart"in document.documentElement&&!s.closest(".navbar-nav").length&&t(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(t(this)).on("click",n);var a={relatedTarget:this};if(s.trigger(i=t.Event("show.bs.dropdown",a)),i.isDefaultPrevented())return;r.trigger("focus").attr("aria-expanded","true"),s.toggleClass("open").trigger(t.Event("shown.bs.dropdown",a))}return!1}},o.prototype.keydown=function(n){if(/(38|40|27|32)/.test(n.which)&&!/input|textarea/i.test(n.target.tagName)){var i=t(this);if(n.preventDefault(),n.stopPropagation(),!i.is(".disabled, :disabled")){var r=e(i),o=r.hasClass("open");if(!o&&27!=n.which||o&&27==n.which)return 27==n.which&&r.find(s).trigger("focus"),i.trigger("click");var a=" li:not(.disabled):visible a",l=r.find(".dropdown-menu"+a);if(l.length){var c=l.index(n.target);38==n.which&&c>0&&c--,40==n.which&&cdocument.documentElement.clientHeight;this.$element.css({paddingLeft:!this.bodyIsOverflowing&&t?this.scrollbarWidth:"",paddingRight:this.bodyIsOverflowing&&!t?this.scrollbarWidth:""})},n.prototype.resetAdjustments=function(){this.$element.css({paddingLeft:"",paddingRight:""})},n.prototype.checkScrollbar=function(){var t=window.innerWidth;if(!t){var e=document.documentElement.getBoundingClientRect();t=e.right-Math.abs(e.left)}this.bodyIsOverflowing=document.body.clientWidth
',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},n.prototype.init=function(e,n,i){if(this.enabled=!0,this.type=e,this.$element=t(n),this.options=this.getOptions(i),this.$viewport=this.options.viewport&&t(t.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 r=this.options.trigger.split(" "),s=r.length;s--;){var o=r[s];if("click"==o)this.$element.on("click."+this.type,this.options.selector,t.proxy(this.toggle,this));else if("manual"!=o){var a="hover"==o?"mouseenter":"focusin",l="hover"==o?"mouseleave":"focusout";this.$element.on(a+"."+this.type,this.options.selector,t.proxy(this.enter,this)),this.$element.on(l+"."+this.type,this.options.selector,t.proxy(this.leave,this))}}this.options.selector?this._options=t.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},n.prototype.getDefaults=function(){return n.DEFAULTS},n.prototype.getOptions=function(e){return e=t.extend({},this.getDefaults(),this.$element.data(),e),e.delay&&"number"==typeof e.delay&&(e.delay={show:e.delay,hide:e.delay}),e},n.prototype.getDelegateOptions=function(){var e={},n=this.getDefaults();return this._options&&t.each(this._options,function(t,i){n[t]!=i&&(e[t]=i)}),e},n.prototype.enter=function(e){var n=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);return n||(n=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,n)),e instanceof t.Event&&(n.inState["focusin"==e.type?"focus":"hover"]=!0),n.tip().hasClass("in")||"in"==n.hoverState?void(n.hoverState="in"):(clearTimeout(n.timeout),n.hoverState="in",n.options.delay&&n.options.delay.show?void(n.timeout=setTimeout(function(){"in"==n.hoverState&&n.show()},n.options.delay.show)):n.show())},n.prototype.isInStateTrue=function(){for(var t in this.inState)if(this.inState[t])return!0;return!1},n.prototype.leave=function(e){var n=e instanceof this.constructor?e:t(e.currentTarget).data("bs."+this.type);if(n||(n=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,n)),e instanceof t.Event&&(n.inState["focusout"==e.type?"focus":"hover"]=!1),!n.isInStateTrue())return clearTimeout(n.timeout),n.hoverState="out",n.options.delay&&n.options.delay.hide?void(n.timeout=setTimeout(function(){"out"==n.hoverState&&n.hide()},n.options.delay.hide)):n.hide()},n.prototype.show=function(){var e=t.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(e);var i=t.contains(this.$element[0].ownerDocument.documentElement,this.$element[0]);if(e.isDefaultPrevented()||!i)return;var r=this,s=this.tip(),o=this.getUID(this.type);this.setContent(),s.attr("id",o),this.$element.attr("aria-describedby",o),this.options.animation&&s.addClass("fade");var a="function"==typeof this.options.placement?this.options.placement.call(this,s[0],this.$element[0]):this.options.placement,l=/\s?auto?\s?/i,c=l.test(a);c&&(a=a.replace(l,"")||"top"),s.detach().css({top:0,left:0,display:"block"}).addClass(a).data("bs."+this.type,this),this.options.container?s.appendTo(this.options.container):s.insertAfter(this.$element),this.$element.trigger("inserted.bs."+this.type);var u=this.getPosition(),h=s[0].offsetWidth,f=s[0].offsetHeight;if(c){var p=a,d=this.getPosition(this.$viewport);a="bottom"==a&&u.bottom+f>d.bottom?"top":"top"==a&&u.top-fd.width?"left":"left"==a&&u.left-ho.top+o.height&&(r.top=o.top+o.height-l)}else{var c=e.left-s,u=e.left+s+n;co.right&&(r.left=o.left+o.width-u)}return r},n.prototype.getTitle=function(){var t,e=this.$element,n=this.options;return t=e.attr("data-original-title")||("function"==typeof n.title?n.title.call(e[0]):n.title)},n.prototype.getUID=function(t){do t+=~~(1e6*Math.random());while(document.getElementById(t));return t},n.prototype.tip=function(){if(!this.$tip&&(this.$tip=t(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},n.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},n.prototype.enable=function(){this.enabled=!0},n.prototype.disable=function(){this.enabled=!1},n.prototype.toggleEnabled=function(){this.enabled=!this.enabled},n.prototype.toggle=function(e){var n=this;e&&(n=t(e.currentTarget).data("bs."+this.type),n||(n=new this.constructor(e.currentTarget,this.getDelegateOptions()),t(e.currentTarget).data("bs."+this.type,n))),e?(n.inState.click=!n.inState.click,n.isInStateTrue()?n.enter(n):n.leave(n)):n.tip().hasClass("in")?n.leave(n):n.enter(n)},n.prototype.destroy=function(){var t=this;clearTimeout(this.timeout),this.hide(function(){t.$element.off("."+t.type).removeData("bs."+t.type),t.$tip&&t.$tip.detach(),t.$tip=null,t.$arrow=null,t.$viewport=null,t.$element=null})};var i=t.fn.tooltip;t.fn.tooltip=e,t.fn.tooltip.Constructor=n,t.fn.tooltip.noConflict=function(){return t.fn.tooltip=i,this}}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),r=i.data("bs.popover"),s="object"==typeof e&&e;!r&&/destroy|hide/.test(e)||(r||i.data("bs.popover",r=new n(this,s)),"string"==typeof e&&r[e]())})}var n=function(t,e){this.init("popover",t,e)};if(!t.fn.tooltip)throw new Error("Popover requires tooltip.js");n.VERSION="3.3.7",n.DEFAULTS=t.extend({},t.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),n.prototype=t.extend({},t.fn.tooltip.Constructor.prototype),n.prototype.constructor=n,n.prototype.getDefaults=function(){return n.DEFAULTS},n.prototype.setContent=function(){var t=this.tip(),e=this.getTitle(),n=this.getContent();t.find(".popover-title")[this.options.html?"html":"text"](e),t.find(".popover-content").children().detach().end()[this.options.html?"string"==typeof n?"html":"append":"text"](n),t.removeClass("fade top bottom left right in"),t.find(".popover-title").html()||t.find(".popover-title").hide()},n.prototype.hasContent=function(){return this.getTitle()||this.getContent()},n.prototype.getContent=function(){var t=this.$element,e=this.options;return t.attr("data-content")||("function"==typeof e.content?e.content.call(t[0]):e.content)},n.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow"); -};var i=t.fn.popover;t.fn.popover=e,t.fn.popover.Constructor=n,t.fn.popover.noConflict=function(){return t.fn.popover=i,this}}(jQuery),+function(t){"use strict";function e(n,i){this.$body=t(document.body),this.$scrollElement=t(t(n).is(document.body)?window:n),this.options=t.extend({},e.DEFAULTS,i),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",t.proxy(this.process,this)),this.refresh(),this.process()}function n(n){return this.each(function(){var i=t(this),r=i.data("bs.scrollspy"),s="object"==typeof n&&n;r||i.data("bs.scrollspy",r=new e(this,s)),"string"==typeof n&&r[n]()})}e.VERSION="3.3.7",e.DEFAULTS={offset:10},e.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},e.prototype.refresh=function(){var e=this,n="offset",i=0;this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight(),t.isWindow(this.$scrollElement[0])||(n="position",i=this.$scrollElement.scrollTop()),this.$body.find(this.selector).map(function(){var e=t(this),r=e.data("target")||e.attr("href"),s=/^#./.test(r)&&t(r);return s&&s.length&&s.is(":visible")&&[[s[n]().top+i,r]]||null}).sort(function(t,e){return t[0]-e[0]}).each(function(){e.offsets.push(this[0]),e.targets.push(this[1])})},e.prototype.process=function(){var t,e=this.$scrollElement.scrollTop()+this.options.offset,n=this.getScrollHeight(),i=this.options.offset+n-this.$scrollElement.height(),r=this.offsets,s=this.targets,o=this.activeTarget;if(this.scrollHeight!=n&&this.refresh(),e>=i)return o!=(t=s[s.length-1])&&this.activate(t);if(o&&e=r[t]&&(void 0===r[t+1]||e .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),e.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),a?(e[0].offsetWidth,e.addClass("in")):e.removeClass("fade"),e.parent(".dropdown-menu").length&&e.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),r&&r()}var o=i.find("> .active"),a=r&&t.support.transition&&(o.length&&o.hasClass("fade")||!!i.find("> .fade").length);o.length&&a?o.one("bsTransitionEnd",s).emulateTransitionEnd(n.TRANSITION_DURATION):s(),o.removeClass("in")};var i=t.fn.tab;t.fn.tab=e,t.fn.tab.Constructor=n,t.fn.tab.noConflict=function(){return t.fn.tab=i,this};var r=function(n){n.preventDefault(),e.call(t(this),"show")};t(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',r).on("click.bs.tab.data-api",'[data-toggle="pill"]',r)}(jQuery),+function(t){"use strict";function e(e){return this.each(function(){var i=t(this),r=i.data("bs.affix"),s="object"==typeof e&&e;r||i.data("bs.affix",r=new n(this,s)),"string"==typeof e&&r[e]()})}var n=function(e,i){this.options=t.extend({},n.DEFAULTS,i),this.$target=t(this.options.target).on("scroll.bs.affix.data-api",t.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",t.proxy(this.checkPositionWithEventLoop,this)),this.$element=t(e),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};n.VERSION="3.3.7",n.RESET="affix affix-top affix-bottom",n.DEFAULTS={offset:0,target:window},n.prototype.getState=function(t,e,n,i){var r=this.$target.scrollTop(),s=this.$element.offset(),o=this.$target.height();if(null!=n&&"top"==this.affixed)return r=t-i&&"bottom"},n.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(n.RESET).addClass("affix");var t=this.$target.scrollTop(),e=this.$element.offset();return this.pinnedOffset=e.top-t},n.prototype.checkPositionWithEventLoop=function(){setTimeout(t.proxy(this.checkPosition,this),1)},n.prototype.checkPosition=function(){if(this.$element.is(":visible")){var e=this.$element.height(),i=this.options.offset,r=i.top,s=i.bottom,o=Math.max(t(document).height(),t(document.body).height());"object"!=typeof i&&(s=r=i),"function"==typeof r&&(r=i.top(this.$element)),"function"==typeof s&&(s=i.bottom(this.$element));var a=this.getState(o,e,r,s);if(this.affixed!=a){null!=this.unpin&&this.$element.css("top","");var l="affix"+(a?"-"+a:""),c=t.Event(l+".bs.affix");if(this.$element.trigger(c),c.isDefaultPrevented())return;this.affixed=a,this.unpin="bottom"==a?this.getPinnedOffset():null,this.$element.removeClass(n.RESET).addClass(l).trigger(l.replace("affix","affixed")+".bs.affix")}"bottom"==a&&this.$element.offset({top:o-e-s})}};var i=t.fn.affix;t.fn.affix=e,t.fn.affix.Constructor=n,t.fn.affix.noConflict=function(){return t.fn.affix=i,this},t(window).on("load",function(){t('[data-spy="affix"]').each(function(){var n=t(this),i=n.data();i.offset=i.offset||{},null!=i.offsetBottom&&(i.offset.bottom=i.offsetBottom),null!=i.offsetTop&&(i.offset.top=i.offsetTop),e.call(n,i)})})}(jQuery)}()}),require.register("jquery/dist/jquery.js",function(t,e,i){e=n(e,{},"jquery"),function(){!function(t,e){"use strict";"object"==typeof i&&"object"==typeof i.exports?i.exports=t.document?e(t,!0):function(t){if(!t.document)throw new Error("jQuery requires a window with a document");return e(t)}:e(t)}("undefined"!=typeof window?window:this,function(t,e){"use strict";function n(t,e){e=e||nt;var n=e.createElement("script");n.text=t,e.head.appendChild(n).parentNode.removeChild(n)}function i(t){var e=!!t&&"length"in t&&t.length,n=mt.type(t);return"function"!==n&&!mt.isWindow(t)&&("array"===n||0===e||"number"==typeof e&&e>0&&e-1 in t)}function r(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}function s(t,e,n){return mt.isFunction(e)?mt.grep(t,function(t,i){return!!e.call(t,i,t)!==n}):e.nodeType?mt.grep(t,function(t){return t===e!==n}):"string"!=typeof e?mt.grep(t,function(t){return at.call(e,t)>-1!==n}):kt.test(e)?mt.filter(e,t,n):(e=mt.filter(e,t),mt.grep(t,function(t){return at.call(e,t)>-1!==n&&1===t.nodeType}))}function o(t,e){for(;(t=t[e])&&1!==t.nodeType;);return t}function a(t){var e={};return mt.each(t.match(Rt)||[],function(t,n){e[n]=!0}),e}function l(t){return t}function c(t){throw t}function u(t,e,n,i){var r;try{t&&mt.isFunction(r=t.promise)?r.call(t).done(e).fail(n):t&&mt.isFunction(r=t.then)?r.call(t,e,n):e.apply(void 0,[t].slice(i))}catch(t){n.apply(void 0,[t])}}function h(){nt.removeEventListener("DOMContentLoaded",h),t.removeEventListener("load",h),mt.ready()}function f(){this.expando=mt.expando+f.uid++}function p(t){return"true"===t||"false"!==t&&("null"===t?null:t===+t+""?+t:Ht.test(t)?JSON.parse(t):t)}function d(t,e,n){var i;if(void 0===n&&1===t.nodeType)if(i="data-"+e.replace(Bt,"-$&").toLowerCase(),n=t.getAttribute(i),"string"==typeof n){try{n=p(n)}catch(r){}jt.set(t,e,n)}else n=void 0;return n}function m(t,e,n,i){var r,s=1,o=20,a=i?function(){return i.cur()}:function(){return mt.css(t,e,"")},l=a(),c=n&&n[3]||(mt.cssNumber[e]?"":"px"),u=(mt.cssNumber[e]||"px"!==c&&+l)&&qt.exec(mt.css(t,e));if(u&&u[3]!==c){c=c||u[3],n=n||[],u=+l||1;do s=s||".5",u/=s,mt.style(t,e,u+c);while(s!==(s=a()/l)&&1!==s&&--o)}return n&&(u=+u||+l||0,r=n[1]?u+(n[1]+1)*n[2]:+n[2],i&&(i.unit=c,i.start=u,i.end=r)),r}function g(t){var e,n=t.ownerDocument,i=t.nodeName,r=Vt[i];return r?r:(e=n.body.appendChild(n.createElement(i)),r=mt.css(e,"display"),e.parentNode.removeChild(e),"none"===r&&(r="block"),Vt[i]=r,r)}function y(t,e){for(var n,i,r=[],s=0,o=t.length;s-1)r&&r.push(s);else if(c=mt.contains(s.ownerDocument,s),o=v(h.appendChild(s),"script"),c&&b(o),n)for(u=0;s=o[u++];)Gt.test(s.type||"")&&n.push(s);return h}function C(){return!0}function w(){return!1}function x(){try{return nt.activeElement}catch(t){}}function E(t,e,n,i,r,s){var o,a;if("object"==typeof e){"string"!=typeof n&&(i=i||n,n=void 0);for(a in e)E(t,a,n,i,e[a],s);return t}if(null==i&&null==r?(r=n,i=n=void 0):null==r&&("string"==typeof n?(r=i,i=void 0):(r=i,i=n,n=void 0)),r===!1)r=w;else if(!r)return t;return 1===s&&(o=r,r=function(t){return mt().off(t),o.apply(this,arguments)},r.guid=o.guid||(o.guid=mt.guid++)),t.each(function(){mt.event.add(this,e,r,i,n)})}function k(t,e){return r(t,"table")&&r(11!==e.nodeType?e:e.firstChild,"tr")?mt(">tbody",t)[0]||t:t}function T(t){return t.type=(null!==t.getAttribute("type"))+"/"+t.type,t}function S(t){var e=re.exec(t.type);return e?t.type=e[1]:t.removeAttribute("type"),t}function A(t,e){var n,i,r,s,o,a,l,c;if(1===e.nodeType){if(Pt.hasData(t)&&(s=Pt.access(t),o=Pt.set(e,s),c=s.events)){delete o.handle,o.events={};for(r in c)for(n=0,i=c[r].length;n1&&"string"==typeof d&&!pt.checkClone&&ie.test(d))return t.each(function(n){var s=t.eq(n);m&&(e[0]=d.call(this,n,s.html())),N(s,e,i,r)});if(f&&(s=_(e,t[0].ownerDocument,!1,t,r),o=s.firstChild,1===s.childNodes.length&&(s=o),o||r)){for(a=mt.map(v(s,"script"),T),l=a.length;h=0&&nx.cacheLength&&delete t[e.shift()],t[n+" "]=i}var e=[];return t}function i(t){return t[$]=!0,t}function r(t){var e=I.createElement("fieldset");try{return!!t(e)}catch(n){return!1}finally{e.parentNode&&e.parentNode.removeChild(e),e=null}}function s(t,e){for(var n=t.split("|"),i=n.length;i--;)x.attrHandle[n[i]]=e}function o(t,e){var n=e&&t,i=n&&1===t.nodeType&&1===e.nodeType&&t.sourceIndex-e.sourceIndex;if(i)return i;if(n)for(;n=n.nextSibling;)if(n===e)return-1;return t?1:-1}function a(t){return function(e){var n=e.nodeName.toLowerCase();return"input"===n&&e.type===t}}function l(t){return function(e){var n=e.nodeName.toLowerCase();return("input"===n||"button"===n)&&e.type===t}}function c(t){return function(e){return"form"in e?e.parentNode&&e.disabled===!1?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&Et(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function u(t){return i(function(e){return e=+e,i(function(n,i){for(var r,s=t([],n.length,e),o=s.length;o--;)n[r=s[o]]&&(n[r]=!(i[r]=n[r]))})})}function h(t){return t&&"undefined"!=typeof t.getElementsByTagName&&t}function f(){}function p(t){for(var e=0,n=t.length,i="";e1?function(e,n,i){for(var r=t.length;r--;)if(!t[r](e,n,i))return!1;return!0}:t[0]}function g(t,n,i){for(var r=0,s=n.length;r-1&&(i[c]=!(o[c]=h))}}else b=y(b===o?b.splice(d,b.length):b),s?s(null,o,b,l):J.apply(o,b)})}function b(t){for(var e,n,i,r=t.length,s=x.relative[t[0].type],o=s||x.relative[" "],a=s?1:0,l=d(function(t){return t===e},o,!0),c=d(function(t){return tt(e,t)>-1},o,!0),u=[function(t,n,i){var r=!s&&(i||n!==L)||((e=n).nodeType?l(t,n,i):c(t,n,i));return e=null,r}];a1&&m(u),a>1&&p(t.slice(0,a-1).concat({value:" "===t[a-2].type?"*":""})).replace(at,"$1"),n,a0,s=t.length>0,o=function(i,o,a,l,c){var u,h,f,p=0,d="0",m=i&&[],g=[],v=L,b=i||s&&x.find.TAG("*",c),_=F+=null==v?1:Math.random()||.1,C=b.length;for(c&&(L=o===I||o||c);d!==C&&null!=(u=b[d]);d++){if(s&&u){for(h=0,o||u.ownerDocument===I||(O(u),a=!D);f=t[h++];)if(f(u,o||I,a)){l.push(u);break}c&&(F=_)}r&&((u=!f&&u)&&p--,i&&m.push(u))}if(p+=d,r&&d!==p){for(h=0;f=n[h++];)f(m,g,o,a);if(i){if(p>0)for(;d--;)m[d]||g[d]||(g[d]=X.call(l));g=y(g)}J.apply(l,g),c&&!i&&g.length>0&&p+n.length>1&&e.uniqueSort(l)}return c&&(F=_,L=v),m};return r?i(o):o}var C,w,x,E,k,T,S,A,L,N,R,O,I,M,D,P,j,H,B,$="sizzle"+1*new Date,q=t.document,F=0,U=0,W=n(),V=n(),K=n(),z=function(t,e){return t===e&&(R=!0),0},G={}.hasOwnProperty,Y=[],X=Y.pop,Q=Y.push,J=Y.push,Z=Y.slice,tt=function(t,e){for(var n=0,i=t.length;n+~]|"+nt+")"+nt+"*"),ut=new RegExp("="+nt+"*([^\\]'\"]*?)"+nt+"*\\]","g"),ht=new RegExp(st),ft=new RegExp("^"+it+"$"),pt={ID:new RegExp("^#("+it+")"),CLASS:new RegExp("^\\.("+it+")"),TAG:new RegExp("^("+it+"|[*])"),ATTR:new RegExp("^"+rt),PSEUDO:new RegExp("^"+st),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+nt+"*(even|odd|(([+-]|)(\\d*)n|)"+nt+"*(?:([+-]|)"+nt+"*(\\d+)|))"+nt+"*\\)|)","i"),bool:new RegExp("^(?:"+et+")$","i"),needsContext:new RegExp("^"+nt+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+nt+"*((?:-\\d)?\\d*)"+nt+"*\\)|)(?=[^-]|$)","i")},dt=/^(?:input|select|textarea|button)$/i,mt=/^h\d$/i,gt=/^[^{]+\{\s*\[native \w/,yt=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,vt=/[+~]/,bt=new RegExp("\\\\([\\da-f]{1,6}"+nt+"?|("+nt+")|.)","ig"),_t=function(t,e,n){var i="0x"+e-65536;return i!==i||n?e:i<0?String.fromCharCode(i+65536):String.fromCharCode(i>>10|55296,1023&i|56320)},Ct=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,wt=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},xt=function(){O()},Et=d(function(t){return t.disabled===!0&&("form"in t||"label"in t)},{dir:"parentNode",next:"legend"});try{J.apply(Y=Z.call(q.childNodes),q.childNodes),Y[q.childNodes.length].nodeType}catch(kt){J={apply:Y.length?function(t,e){Q.apply(t,Z.call(e))}:function(t,e){for(var n=t.length,i=0;t[n++]=e[i++];);t.length=n-1}}}w=e.support={},k=e.isXML=function(t){var e=t&&(t.ownerDocument||t).documentElement;return!!e&&"HTML"!==e.nodeName},O=e.setDocument=function(t){var e,n,i=t?t.ownerDocument||t:q;return i!==I&&9===i.nodeType&&i.documentElement?(I=i,M=I.documentElement,D=!k(I),q!==I&&(n=I.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",xt,!1):n.attachEvent&&n.attachEvent("onunload",xt)),w.attributes=r(function(t){return t.className="i",!t.getAttribute("className")}),w.getElementsByTagName=r(function(t){return t.appendChild(I.createComment("")),!t.getElementsByTagName("*").length}),w.getElementsByClassName=gt.test(I.getElementsByClassName),w.getById=r(function(t){return M.appendChild(t).id=$,!I.getElementsByName||!I.getElementsByName($).length}),w.getById?(x.filter.ID=function(t){var e=t.replace(bt,_t);return function(t){return t.getAttribute("id")===e}},x.find.ID=function(t,e){if("undefined"!=typeof e.getElementById&&D){var n=e.getElementById(t);return n?[n]:[]}}):(x.filter.ID=function(t){var e=t.replace(bt,_t);return function(t){var n="undefined"!=typeof t.getAttributeNode&&t.getAttributeNode("id");return n&&n.value===e}},x.find.ID=function(t,e){if("undefined"!=typeof e.getElementById&&D){var n,i,r,s=e.getElementById(t);if(s){if(n=s.getAttributeNode("id"),n&&n.value===t)return[s];for(r=e.getElementsByName(t),i=0;s=r[i++];)if(n=s.getAttributeNode("id"),n&&n.value===t)return[s]}return[]}}),x.find.TAG=w.getElementsByTagName?function(t,e){return"undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t):w.qsa?e.querySelectorAll(t):void 0}:function(t,e){var n,i=[],r=0,s=e.getElementsByTagName(t);if("*"===t){for(;n=s[r++];)1===n.nodeType&&i.push(n);return i}return s},x.find.CLASS=w.getElementsByClassName&&function(t,e){if("undefined"!=typeof e.getElementsByClassName&&D)return e.getElementsByClassName(t)},j=[],P=[],(w.qsa=gt.test(I.querySelectorAll))&&(r(function(t){M.appendChild(t).innerHTML="",t.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+nt+"*(?:''|\"\")"), -t.querySelectorAll("[selected]").length||P.push("\\["+nt+"*(?:value|"+et+")"),t.querySelectorAll("[id~="+$+"-]").length||P.push("~="),t.querySelectorAll(":checked").length||P.push(":checked"),t.querySelectorAll("a#"+$+"+*").length||P.push(".#.+[+~]")}),r(function(t){t.innerHTML="";var e=I.createElement("input");e.setAttribute("type","hidden"),t.appendChild(e).setAttribute("name","D"),t.querySelectorAll("[name=d]").length&&P.push("name"+nt+"*[*^$|!~]?="),2!==t.querySelectorAll(":enabled").length&&P.push(":enabled",":disabled"),M.appendChild(t).disabled=!0,2!==t.querySelectorAll(":disabled").length&&P.push(":enabled",":disabled"),t.querySelectorAll("*,:x"),P.push(",.*:")})),(w.matchesSelector=gt.test(H=M.matches||M.webkitMatchesSelector||M.mozMatchesSelector||M.oMatchesSelector||M.msMatchesSelector))&&r(function(t){w.disconnectedMatch=H.call(t,"*"),H.call(t,"[s!='']:x"),j.push("!=",st)}),P=P.length&&new RegExp(P.join("|")),j=j.length&&new RegExp(j.join("|")),e=gt.test(M.compareDocumentPosition),B=e||gt.test(M.contains)?function(t,e){var n=9===t.nodeType?t.documentElement:t,i=e&&e.parentNode;return t===i||!(!i||1!==i.nodeType||!(n.contains?n.contains(i):t.compareDocumentPosition&&16&t.compareDocumentPosition(i)))}:function(t,e){if(e)for(;e=e.parentNode;)if(e===t)return!0;return!1},z=e?function(t,e){if(t===e)return R=!0,0;var n=!t.compareDocumentPosition-!e.compareDocumentPosition;return n?n:(n=(t.ownerDocument||t)===(e.ownerDocument||e)?t.compareDocumentPosition(e):1,1&n||!w.sortDetached&&e.compareDocumentPosition(t)===n?t===I||t.ownerDocument===q&&B(q,t)?-1:e===I||e.ownerDocument===q&&B(q,e)?1:N?tt(N,t)-tt(N,e):0:4&n?-1:1)}:function(t,e){if(t===e)return R=!0,0;var n,i=0,r=t.parentNode,s=e.parentNode,a=[t],l=[e];if(!r||!s)return t===I?-1:e===I?1:r?-1:s?1:N?tt(N,t)-tt(N,e):0;if(r===s)return o(t,e);for(n=t;n=n.parentNode;)a.unshift(n);for(n=e;n=n.parentNode;)l.unshift(n);for(;a[i]===l[i];)i++;return i?o(a[i],l[i]):a[i]===q?-1:l[i]===q?1:0},I):I},e.matches=function(t,n){return e(t,null,null,n)},e.matchesSelector=function(t,n){if((t.ownerDocument||t)!==I&&O(t),n=n.replace(ut,"='$1']"),w.matchesSelector&&D&&!K[n+" "]&&(!j||!j.test(n))&&(!P||!P.test(n)))try{var i=H.call(t,n);if(i||w.disconnectedMatch||t.document&&11!==t.document.nodeType)return i}catch(r){}return e(n,I,null,[t]).length>0},e.contains=function(t,e){return(t.ownerDocument||t)!==I&&O(t),B(t,e)},e.attr=function(t,e){(t.ownerDocument||t)!==I&&O(t);var n=x.attrHandle[e.toLowerCase()],i=n&&G.call(x.attrHandle,e.toLowerCase())?n(t,e,!D):void 0;return void 0!==i?i:w.attributes||!D?t.getAttribute(e):(i=t.getAttributeNode(e))&&i.specified?i.value:null},e.escape=function(t){return(t+"").replace(Ct,wt)},e.error=function(t){throw new Error("Syntax error, unrecognized expression: "+t)},e.uniqueSort=function(t){var e,n=[],i=0,r=0;if(R=!w.detectDuplicates,N=!w.sortStable&&t.slice(0),t.sort(z),R){for(;e=t[r++];)e===t[r]&&(i=n.push(r));for(;i--;)t.splice(n[i],1)}return N=null,t},E=e.getText=function(t){var e,n="",i=0,r=t.nodeType;if(r){if(1===r||9===r||11===r){if("string"==typeof t.textContent)return t.textContent;for(t=t.firstChild;t;t=t.nextSibling)n+=E(t)}else if(3===r||4===r)return t.nodeValue}else for(;e=t[i++];)n+=E(e);return n},x=e.selectors={cacheLength:50,createPseudo:i,match:pt,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(t){return t[1]=t[1].replace(bt,_t),t[3]=(t[3]||t[4]||t[5]||"").replace(bt,_t),"~="===t[2]&&(t[3]=" "+t[3]+" "),t.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||e.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&e.error(t[0]),t},PSEUDO:function(t){var e,n=!t[6]&&t[2];return pt.CHILD.test(t[0])?null:(t[3]?t[2]=t[4]||t[5]||"":n&&ht.test(n)&&(e=T(n,!0))&&(e=n.indexOf(")",n.length-e)-n.length)&&(t[0]=t[0].slice(0,e),t[2]=n.slice(0,e)),t.slice(0,3))}},filter:{TAG:function(t){var e=t.replace(bt,_t).toLowerCase();return"*"===t?function(){return!0}:function(t){return t.nodeName&&t.nodeName.toLowerCase()===e}},CLASS:function(t){var e=W[t+" "];return e||(e=new RegExp("(^|"+nt+")"+t+"("+nt+"|$)"))&&W(t,function(t){return e.test("string"==typeof t.className&&t.className||"undefined"!=typeof t.getAttribute&&t.getAttribute("class")||"")})},ATTR:function(t,n,i){return function(r){var s=e.attr(r,t);return null==s?"!="===n:!n||(s+="","="===n?s===i:"!="===n?s!==i:"^="===n?i&&0===s.indexOf(i):"*="===n?i&&s.indexOf(i)>-1:"$="===n?i&&s.slice(-i.length)===i:"~="===n?(" "+s.replace(ot," ")+" ").indexOf(i)>-1:"|="===n&&(s===i||s.slice(0,i.length+1)===i+"-"))}},CHILD:function(t,e,n,i,r){var s="nth"!==t.slice(0,3),o="last"!==t.slice(-4),a="of-type"===e;return 1===i&&0===r?function(t){return!!t.parentNode}:function(e,n,l){var c,u,h,f,p,d,m=s!==o?"nextSibling":"previousSibling",g=e.parentNode,y=a&&e.nodeName.toLowerCase(),v=!l&&!a,b=!1;if(g){if(s){for(;m;){for(f=e;f=f[m];)if(a?f.nodeName.toLowerCase()===y:1===f.nodeType)return!1;d=m="only"===t&&!d&&"nextSibling"}return!0}if(d=[o?g.firstChild:g.lastChild],o&&v){for(f=g,h=f[$]||(f[$]={}),u=h[f.uniqueID]||(h[f.uniqueID]={}),c=u[t]||[],p=c[0]===F&&c[1],b=p&&c[2],f=p&&g.childNodes[p];f=++p&&f&&f[m]||(b=p=0)||d.pop();)if(1===f.nodeType&&++b&&f===e){u[t]=[F,p,b];break}}else if(v&&(f=e,h=f[$]||(f[$]={}),u=h[f.uniqueID]||(h[f.uniqueID]={}),c=u[t]||[],p=c[0]===F&&c[1],b=p),b===!1)for(;(f=++p&&f&&f[m]||(b=p=0)||d.pop())&&((a?f.nodeName.toLowerCase()!==y:1!==f.nodeType)||!++b||(v&&(h=f[$]||(f[$]={}),u=h[f.uniqueID]||(h[f.uniqueID]={}),u[t]=[F,b]),f!==e)););return b-=r,b===i||b%i===0&&b/i>=0}}},PSEUDO:function(t,n){var r,s=x.pseudos[t]||x.setFilters[t.toLowerCase()]||e.error("unsupported pseudo: "+t);return s[$]?s(n):s.length>1?(r=[t,t,"",n],x.setFilters.hasOwnProperty(t.toLowerCase())?i(function(t,e){for(var i,r=s(t,n),o=r.length;o--;)i=tt(t,r[o]),t[i]=!(e[i]=r[o])}):function(t){return s(t,0,r)}):s}},pseudos:{not:i(function(t){var e=[],n=[],r=S(t.replace(at,"$1"));return r[$]?i(function(t,e,n,i){for(var s,o=r(t,null,i,[]),a=t.length;a--;)(s=o[a])&&(t[a]=!(e[a]=s))}):function(t,i,s){return e[0]=t,r(e,null,s,n),e[0]=null,!n.pop()}}),has:i(function(t){return function(n){return e(t,n).length>0}}),contains:i(function(t){return t=t.replace(bt,_t),function(e){return(e.textContent||e.innerText||E(e)).indexOf(t)>-1}}),lang:i(function(t){return ft.test(t||"")||e.error("unsupported lang: "+t),t=t.replace(bt,_t).toLowerCase(),function(e){var n;do if(n=D?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return n=n.toLowerCase(),n===t||0===n.indexOf(t+"-");while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var n=t.location&&t.location.hash;return n&&n.slice(1)===e.id},root:function(t){return t===M},focus:function(t){return t===I.activeElement&&(!I.hasFocus||I.hasFocus())&&!!(t.type||t.href||~t.tabIndex)},enabled:c(!1),disabled:c(!0),checked:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&!!t.checked||"option"===e&&!!t.selected},selected:function(t){return t.parentNode&&t.parentNode.selectedIndex,t.selected===!0},empty:function(t){for(t=t.firstChild;t;t=t.nextSibling)if(t.nodeType<6)return!1;return!0},parent:function(t){return!x.pseudos.empty(t)},header:function(t){return mt.test(t.nodeName)},input:function(t){return dt.test(t.nodeName)},button:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&"button"===t.type||"button"===e},text:function(t){var e;return"input"===t.nodeName.toLowerCase()&&"text"===t.type&&(null==(e=t.getAttribute("type"))||"text"===e.toLowerCase())},first:u(function(){return[0]}),last:u(function(t,e){return[e-1]}),eq:u(function(t,e,n){return[n<0?n+e:n]}),even:u(function(t,e){for(var n=0;n=0;)t.push(i);return t}),gt:u(function(t,e,n){for(var i=n<0?n+e:n;++i2&&"ID"===(o=s[0]).type&&9===e.nodeType&&D&&x.relative[s[1].type]){if(e=(x.find.ID(o.matches[0].replace(bt,_t),e)||[])[0],!e)return n;c&&(e=e.parentNode),t=t.slice(s.shift().value.length)}for(r=pt.needsContext.test(t)?0:s.length;r--&&(o=s[r],!x.relative[a=o.type]);)if((l=x.find[a])&&(i=l(o.matches[0].replace(bt,_t),vt.test(s[0].type)&&h(e.parentNode)||e))){if(s.splice(r,1),t=i.length&&p(s),!t)return J.apply(n,i),n;break}}return(c||S(t,u))(i,e,!D,n,!e||vt.test(t)&&h(e.parentNode)||e),n},w.sortStable=$.split("").sort(z).join("")===$,w.detectDuplicates=!!R,O(),w.sortDetached=r(function(t){return 1&t.compareDocumentPosition(I.createElement("fieldset"))}),r(function(t){return t.innerHTML="","#"===t.firstChild.getAttribute("href")})||s("type|href|height|width",function(t,e,n){if(!n)return t.getAttribute(e,"type"===e.toLowerCase()?1:2)}),w.attributes&&r(function(t){return t.innerHTML="",t.firstChild.setAttribute("value",""),""===t.firstChild.getAttribute("value")})||s("value",function(t,e,n){if(!n&&"input"===t.nodeName.toLowerCase())return t.defaultValue}),r(function(t){return null==t.getAttribute("disabled")})||s(et,function(t,e,n){var i;if(!n)return t[e]===!0?e.toLowerCase():(i=t.getAttributeNode(e))&&i.specified?i.value:null}),e}(t);mt.find=_t,mt.expr=_t.selectors,mt.expr[":"]=mt.expr.pseudos,mt.uniqueSort=mt.unique=_t.uniqueSort,mt.text=_t.getText,mt.isXMLDoc=_t.isXML,mt.contains=_t.contains,mt.escapeSelector=_t.escape;var Ct=function(t,e,n){for(var i=[],r=void 0!==n;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(r&&mt(t).is(n))break;i.push(t)}return i},wt=function(t,e){for(var n=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&n.push(t);return n},xt=mt.expr.match.needsContext,Et=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,kt=/^.[^:#\[\.,]*$/;mt.filter=function(t,e,n){var i=e[0];return n&&(t=":not("+t+")"),1===e.length&&1===i.nodeType?mt.find.matchesSelector(i,t)?[i]:[]:mt.find.matches(t,mt.grep(e,function(t){return 1===t.nodeType}))},mt.fn.extend({find:function(t){var e,n,i=this.length,r=this;if("string"!=typeof t)return this.pushStack(mt(t).filter(function(){for(e=0;e1?mt.uniqueSort(n):n},filter:function(t){return this.pushStack(s(this,t||[],!1))},not:function(t){return this.pushStack(s(this,t||[],!0))},is:function(t){return!!s(this,"string"==typeof t&&xt.test(t)?mt(t):t||[],!1).length}});var Tt,St=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,At=mt.fn.init=function(t,e,n){var i,r;if(!t)return this;if(n=n||Tt,"string"==typeof t){if(i="<"===t[0]&&">"===t[t.length-1]&&t.length>=3?[null,t,null]:St.exec(t),!i||!i[1]&&e)return!e||e.jquery?(e||n).find(t):this.constructor(e).find(t);if(i[1]){if(e=e instanceof mt?e[0]:e,mt.merge(this,mt.parseHTML(i[1],e&&e.nodeType?e.ownerDocument||e:nt,!0)),Et.test(i[1])&&mt.isPlainObject(e))for(i in e)mt.isFunction(this[i])?this[i](e[i]):this.attr(i,e[i]);return this}return r=nt.getElementById(i[2]),r&&(this[0]=r,this.length=1),this}return t.nodeType?(this[0]=t,this.length=1,this):mt.isFunction(t)?void 0!==n.ready?n.ready(t):t(mt):mt.makeArray(t,this)};At.prototype=mt.fn,Tt=mt(nt);var Lt=/^(?:parents|prev(?:Until|All))/,Nt={children:!0,contents:!0,next:!0,prev:!0};mt.fn.extend({has:function(t){var e=mt(t,this),n=e.length;return this.filter(function(){for(var t=0;t-1:1===n.nodeType&&mt.find.matchesSelector(n,t))){s.push(n);break}return this.pushStack(s.length>1?mt.uniqueSort(s):s)},index:function(t){return t?"string"==typeof t?at.call(mt(t),this[0]):at.call(this,t.jquery?t[0]:t):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(t,e){return this.pushStack(mt.uniqueSort(mt.merge(this.get(),mt(t,e))))},addBack:function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}}),mt.each({parent:function(t){var e=t.parentNode;return e&&11!==e.nodeType?e:null},parents:function(t){return Ct(t,"parentNode")},parentsUntil:function(t,e,n){return Ct(t,"parentNode",n)},next:function(t){return o(t,"nextSibling")},prev:function(t){return o(t,"previousSibling")},nextAll:function(t){return Ct(t,"nextSibling")},prevAll:function(t){return Ct(t,"previousSibling")},nextUntil:function(t,e,n){return Ct(t,"nextSibling",n)},prevUntil:function(t,e,n){return Ct(t,"previousSibling",n)},siblings:function(t){return wt((t.parentNode||{}).firstChild,t)},children:function(t){return wt(t.firstChild)},contents:function(t){return r(t,"iframe")?t.contentDocument:(r(t,"template")&&(t=t.content||t),mt.merge([],t.childNodes))}},function(t,e){mt.fn[t]=function(n,i){var r=mt.map(this,e,n);return"Until"!==t.slice(-5)&&(i=n),i&&"string"==typeof i&&(r=mt.filter(i,r)),this.length>1&&(Nt[t]||mt.uniqueSort(r),Lt.test(t)&&r.reverse()),this.pushStack(r)}});var Rt=/[^\x20\t\r\n\f]+/g;mt.Callbacks=function(t){t="string"==typeof t?a(t):mt.extend({},t);var e,n,i,r,s=[],o=[],l=-1,c=function(){for(r=r||t.once,i=e=!0;o.length;l=-1)for(n=o.shift();++l-1;)s.splice(n,1),n<=l&&l--}),this},has:function(t){return t?mt.inArray(t,s)>-1:s.length>0},empty:function(){return s&&(s=[]),this},disable:function(){return r=o=[],s=n="",this},disabled:function(){return!s},lock:function(){return r=o=[],n||e||(s=n=""),this},locked:function(){return!!r},fireWith:function(t,n){return r||(n=n||[],n=[t,n.slice?n.slice():n],o.push(n),e||c()),this},fire:function(){return u.fireWith(this,arguments),this},fired:function(){return!!i}};return u},mt.extend({Deferred:function(e){var n=[["notify","progress",mt.Callbacks("memory"),mt.Callbacks("memory"),2],["resolve","done",mt.Callbacks("once memory"),mt.Callbacks("once memory"),0,"resolved"],["reject","fail",mt.Callbacks("once memory"),mt.Callbacks("once memory"),1,"rejected"]],i="pending",r={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(t){return r.then(null,t)},pipe:function(){var t=arguments;return mt.Deferred(function(e){mt.each(n,function(n,i){var r=mt.isFunction(t[i[4]])&&t[i[4]];s[i[1]](function(){var t=r&&r.apply(this,arguments);t&&mt.isFunction(t.promise)?t.promise().progress(e.notify).done(e.resolve).fail(e.reject):e[i[0]+"With"](this,r?[t]:arguments)})}),t=null}).promise()},then:function(e,i,r){function s(e,n,i,r){return function(){var a=this,u=arguments,h=function(){var t,h;if(!(e=o&&(i!==c&&(a=void 0,u=[t]),n.rejectWith(a,u))}};e?f():(mt.Deferred.getStackHook&&(f.stackTrace=mt.Deferred.getStackHook()),t.setTimeout(f))}}var o=0;return mt.Deferred(function(t){n[0][3].add(s(0,t,mt.isFunction(r)?r:l,t.notifyWith)),n[1][3].add(s(0,t,mt.isFunction(e)?e:l)),n[2][3].add(s(0,t,mt.isFunction(i)?i:c))}).promise()},promise:function(t){return null!=t?mt.extend(t,r):r}},s={};return mt.each(n,function(t,e){var o=e[2],a=e[5];r[e[1]]=o.add,a&&o.add(function(){i=a},n[3-t][2].disable,n[0][2].lock),o.add(e[3].fire),s[e[0]]=function(){return s[e[0]+"With"](this===s?void 0:this,arguments),this},s[e[0]+"With"]=o.fireWith}),r.promise(s),e&&e.call(s,s),s},when:function(t){var e=arguments.length,n=e,i=Array(n),r=rt.call(arguments),s=mt.Deferred(),o=function(t){return function(n){i[t]=this,r[t]=arguments.length>1?rt.call(arguments):n,--e||s.resolveWith(i,r)}};if(e<=1&&(u(t,s.done(o(n)).resolve,s.reject,!e),"pending"===s.state()||mt.isFunction(r[n]&&r[n].then)))return s.then();for(;n--;)u(r[n],o(n),s.reject);return s.promise()}});var Ot=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;mt.Deferred.exceptionHook=function(e,n){t.console&&t.console.warn&&e&&Ot.test(e.name)&&t.console.warn("jQuery.Deferred exception: "+e.message,e.stack,n)},mt.readyException=function(e){t.setTimeout(function(){throw e})};var It=mt.Deferred();mt.fn.ready=function(t){return It.then(t)["catch"](function(t){mt.readyException(t)}),this},mt.extend({isReady:!1,readyWait:1,ready:function(t){(t===!0?--mt.readyWait:mt.isReady)||(mt.isReady=!0,t!==!0&&--mt.readyWait>0||It.resolveWith(nt,[mt]))}}),mt.ready.then=It.then,"complete"===nt.readyState||"loading"!==nt.readyState&&!nt.documentElement.doScroll?t.setTimeout(mt.ready):(nt.addEventListener("DOMContentLoaded",h),t.addEventListener("load",h));var Mt=function(t,e,n,i,r,s,o){var a=0,l=t.length,c=null==n;if("object"===mt.type(n)){r=!0;for(a in n)Mt(t,e,a,n[a],!0,s,o)}else if(void 0!==i&&(r=!0,mt.isFunction(i)||(o=!0),c&&(o?(e.call(t,i),e=null):(c=e,e=function(t,e,n){return c.call(mt(t),n)})),e))for(;a1,null,!0)},removeData:function(t){return this.each(function(){jt.remove(this,t)})}}),mt.extend({queue:function(t,e,n){var i;if(t)return e=(e||"fx")+"queue",i=Pt.get(t,e),n&&(!i||Array.isArray(n)?i=Pt.access(t,e,mt.makeArray(n)):i.push(n)),i||[]},dequeue:function(t,e){e=e||"fx";var n=mt.queue(t,e),i=n.length,r=n.shift(),s=mt._queueHooks(t,e),o=function(){mt.dequeue(t,e)};"inprogress"===r&&(r=n.shift(),i--),r&&("fx"===e&&n.unshift("inprogress"),delete s.stop,r.call(t,o,s)),!i&&s&&s.empty.fire()},_queueHooks:function(t,e){var n=e+"queueHooks";return Pt.get(t,n)||Pt.access(t,n,{empty:mt.Callbacks("once memory").add(function(){Pt.remove(t,[e+"queue",n])})})}}),mt.fn.extend({queue:function(t,e){var n=2;return"string"!=typeof t&&(e=t,t="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Gt=/^$|\/(?:java|ecma)script/i,Yt={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Yt.optgroup=Yt.option,Yt.tbody=Yt.tfoot=Yt.colgroup=Yt.caption=Yt.thead,Yt.th=Yt.td;var Xt=/<|&#?\w+;/;!function(){var t=nt.createDocumentFragment(),e=t.appendChild(nt.createElement("div")),n=nt.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),e.appendChild(n),pt.checkClone=e.cloneNode(!0).cloneNode(!0).lastChild.checked,e.innerHTML="",pt.noCloneChecked=!!e.cloneNode(!0).lastChild.defaultValue}();var Qt=nt.documentElement,Jt=/^key/,Zt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,te=/^([^.]*)(?:\.(.+)|)/;mt.event={global:{},add:function(t,e,n,i,r){var s,o,a,l,c,u,h,f,p,d,m,g=Pt.get(t);if(g)for(n.handler&&(s=n,n=s.handler,r=s.selector),r&&mt.find.matchesSelector(Qt,r),n.guid||(n.guid=mt.guid++),(l=g.events)||(l=g.events={}),(o=g.handle)||(o=g.handle=function(e){return"undefined"!=typeof mt&&mt.event.triggered!==e.type?mt.event.dispatch.apply(t,arguments):void 0}),e=(e||"").match(Rt)||[""],c=e.length;c--;)a=te.exec(e[c])||[],p=m=a[1],d=(a[2]||"").split(".").sort(),p&&(h=mt.event.special[p]||{},p=(r?h.delegateType:h.bindType)||p,h=mt.event.special[p]||{},u=mt.extend({type:p,origType:m,data:i,handler:n,guid:n.guid,selector:r,needsContext:r&&mt.expr.match.needsContext.test(r),namespace:d.join(".")},s),(f=l[p])||(f=l[p]=[],f.delegateCount=0,h.setup&&h.setup.call(t,i,d,o)!==!1||t.addEventListener&&t.addEventListener(p,o)),h.add&&(h.add.call(t,u),u.handler.guid||(u.handler.guid=n.guid)),r?f.splice(f.delegateCount++,0,u):f.push(u),mt.event.global[p]=!0)},remove:function(t,e,n,i,r){var s,o,a,l,c,u,h,f,p,d,m,g=Pt.hasData(t)&&Pt.get(t);if(g&&(l=g.events)){for(e=(e||"").match(Rt)||[""],c=e.length;c--;)if(a=te.exec(e[c])||[],p=m=a[1],d=(a[2]||"").split(".").sort(),p){for(h=mt.event.special[p]||{},p=(i?h.delegateType:h.bindType)||p,f=l[p]||[],a=a[2]&&new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),o=s=f.length;s--;)u=f[s],!r&&m!==u.origType||n&&n.guid!==u.guid||a&&!a.test(u.namespace)||i&&i!==u.selector&&("**"!==i||!u.selector)||(f.splice(s,1),u.selector&&f.delegateCount--,h.remove&&h.remove.call(t,u));o&&!f.length&&(h.teardown&&h.teardown.call(t,d,g.handle)!==!1||mt.removeEvent(t,p,g.handle),delete l[p])}else for(p in l)mt.event.remove(t,p+e[c],n,i,!0);mt.isEmptyObject(l)&&Pt.remove(t,"handle events")}},dispatch:function(t){var e,n,i,r,s,o,a=mt.event.fix(t),l=new Array(arguments.length),c=(Pt.get(this,"events")||{})[a.type]||[],u=mt.event.special[a.type]||{};for(l[0]=a,e=1;e=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==t.type||c.disabled!==!0)){for(s=[],o={},n=0;n-1:mt.find(r,this,null,[c]).length),o[r]&&s.push(i);s.length&&a.push({elem:c,handlers:s})}return c=this,l\x20\t\r\n\f]*)[^>]*)\/>/gi,ne=/\s*$/g;mt.extend({htmlPrefilter:function(t){return t.replace(ee,"<$1>")},clone:function(t,e,n){var i,r,s,o,a=t.cloneNode(!0),l=mt.contains(t.ownerDocument,t);if(!(pt.noCloneChecked||1!==t.nodeType&&11!==t.nodeType||mt.isXMLDoc(t)))for(o=v(a),s=v(t),i=0,r=s.length;i0&&b(o,!l&&v(t,"script")),a},cleanData:function(t){for(var e,n,i,r=mt.event.special,s=0;void 0!==(n=t[s]);s++)if(Dt(n)){if(e=n[Pt.expando]){if(e.events)for(i in e.events)r[i]?mt.event.remove(n,i):mt.removeEvent(n,i,e.handle);n[Pt.expando]=void 0}n[jt.expando]&&(n[jt.expando]=void 0)}}}),mt.fn.extend({detach:function(t){return R(this,t,!0)},remove:function(t){return R(this,t)},text:function(t){return Mt(this,function(t){return void 0===t?mt.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=t)})},null,t,arguments.length)},append:function(){return N(this,arguments,function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=k(this,t);e.appendChild(t)}})},prepend:function(){return N(this,arguments,function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=k(this,t);e.insertBefore(t,e.firstChild)}})},before:function(){return N(this,arguments,function(t){this.parentNode&&this.parentNode.insertBefore(t,this)})},after:function(){return N(this,arguments,function(t){this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling)})},empty:function(){for(var t,e=0;null!=(t=this[e]);e++)1===t.nodeType&&(mt.cleanData(v(t,!1)),t.textContent="");return this},clone:function(t,e){return t=null!=t&&t,e=null==e?t:e,this.map(function(){return mt.clone(this,t,e)})},html:function(t){return Mt(this,function(t){var e=this[0]||{},n=0,i=this.length;if(void 0===t&&1===e.nodeType)return e.innerHTML;if("string"==typeof t&&!ne.test(t)&&!Yt[(zt.exec(t)||["",""])[1].toLowerCase()]){t=mt.htmlPrefilter(t);try{for(;n1)}}),mt.Tween=B,B.prototype={constructor:B,init:function(t,e,n,i,r,s){this.elem=t,this.prop=n,this.easing=r||mt.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=i,this.unit=s||(mt.cssNumber[n]?"":"px")},cur:function(){var t=B.propHooks[this.prop];return t&&t.get?t.get(this):B.propHooks._default.get(this)},run:function(t){var e,n=B.propHooks[this.prop];return this.options.duration?this.pos=e=mt.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):B.propHooks._default.set(this),this}},B.prototype.init.prototype=B.prototype,B.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=mt.css(t.elem,t.prop,""),e&&"auto"!==e?e:0)},set:function(t){mt.fx.step[t.prop]?mt.fx.step[t.prop](t):1!==t.elem.nodeType||null==t.elem.style[mt.cssProps[t.prop]]&&!mt.cssHooks[t.prop]?t.elem[t.prop]=t.now:mt.style(t.elem,t.prop,t.now+t.unit)}}},B.propHooks.scrollTop=B.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},mt.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},mt.fx=B.prototype.init,mt.fx.step={};var me,ge,ye=/^(?:toggle|show|hide)$/,ve=/queueHooks$/;mt.Animation=mt.extend(K,{tweeners:{"*":[function(t,e){var n=this.createTween(t,e);return m(n.elem,t,qt.exec(e),n),n}]},tweener:function(t,e){mt.isFunction(t)?(e=t,t=["*"]):t=t.match(Rt);for(var n,i=0,r=t.length;i1)},removeAttr:function(t){return this.each(function(){mt.removeAttr(this,t)})}}),mt.extend({attr:function(t,e,n){var i,r,s=t.nodeType;if(3!==s&&8!==s&&2!==s)return"undefined"==typeof t.getAttribute?mt.prop(t,e,n):(1===s&&mt.isXMLDoc(t)||(r=mt.attrHooks[e.toLowerCase()]||(mt.expr.match.bool.test(e)?be:void 0)),void 0!==n?null===n?void mt.removeAttr(t,e):r&&"set"in r&&void 0!==(i=r.set(t,n,e))?i:(t.setAttribute(e,n+""),n):r&&"get"in r&&null!==(i=r.get(t,e))?i:(i=mt.find.attr(t,e),null==i?void 0:i))},attrHooks:{type:{set:function(t,e){if(!pt.radioValue&&"radio"===e&&r(t,"input")){var n=t.value;return t.setAttribute("type",e),n&&(t.value=n),e}}}},removeAttr:function(t,e){var n,i=0,r=e&&e.match(Rt);if(r&&1===t.nodeType)for(;n=r[i++];)t.removeAttribute(n)}}),be={set:function(t,e,n){return e===!1?mt.removeAttr(t,n):t.setAttribute(n,n),n}},mt.each(mt.expr.match.bool.source.match(/\w+/g),function(t,e){var n=_e[e]||mt.find.attr;_e[e]=function(t,e,i){var r,s,o=e.toLowerCase();return i||(s=_e[o],_e[o]=r,r=null!=n(t,e,i)?o:null,_e[o]=s),r}});var Ce=/^(?:input|select|textarea|button)$/i,we=/^(?:a|area)$/i;mt.fn.extend({prop:function(t,e){return Mt(this,mt.prop,t,e,arguments.length>1)},removeProp:function(t){return this.each(function(){delete this[mt.propFix[t]||t]})}}),mt.extend({prop:function(t,e,n){var i,r,s=t.nodeType;if(3!==s&&8!==s&&2!==s)return 1===s&&mt.isXMLDoc(t)||(e=mt.propFix[e]||e,r=mt.propHooks[e]),void 0!==n?r&&"set"in r&&void 0!==(i=r.set(t,n,e))?i:t[e]=n:r&&"get"in r&&null!==(i=r.get(t,e))?i:t[e]},propHooks:{tabIndex:{get:function(t){var e=mt.find.attr(t,"tabindex");return e?parseInt(e,10):Ce.test(t.nodeName)||we.test(t.nodeName)&&t.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),pt.optSelected||(mt.propHooks.selected={get:function(t){var e=t.parentNode;return e&&e.parentNode&&e.parentNode.selectedIndex,null},set:function(t){var e=t.parentNode;e&&(e.selectedIndex,e.parentNode&&e.parentNode.selectedIndex)}}),mt.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){mt.propFix[this.toLowerCase()]=this}),mt.fn.extend({addClass:function(t){var e,n,i,r,s,o,a,l=0;if(mt.isFunction(t))return this.each(function(e){mt(this).addClass(t.call(this,e,G(this)))});if("string"==typeof t&&t)for(e=t.match(Rt)||[];n=this[l++];)if(r=G(n),i=1===n.nodeType&&" "+z(r)+" "){for(o=0;s=e[o++];)i.indexOf(" "+s+" ")<0&&(i+=s+" ");a=z(i),r!==a&&n.setAttribute("class",a)}return this},removeClass:function(t){var e,n,i,r,s,o,a,l=0;if(mt.isFunction(t))return this.each(function(e){mt(this).removeClass(t.call(this,e,G(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof t&&t)for(e=t.match(Rt)||[];n=this[l++];)if(r=G(n),i=1===n.nodeType&&" "+z(r)+" "){for(o=0;s=e[o++];)for(;i.indexOf(" "+s+" ")>-1;)i=i.replace(" "+s+" "," ");a=z(i),r!==a&&n.setAttribute("class",a)}return this},toggleClass:function(t,e){var n=typeof t;return"boolean"==typeof e&&"string"===n?e?this.addClass(t):this.removeClass(t):mt.isFunction(t)?this.each(function(n){mt(this).toggleClass(t.call(this,n,G(this),e),e)}):this.each(function(){var e,i,r,s;if("string"===n)for(i=0,r=mt(this),s=t.match(Rt)||[];e=s[i++];)r.hasClass(e)?r.removeClass(e):r.addClass(e);else void 0!==t&&"boolean"!==n||(e=G(this),e&&Pt.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||t===!1?"":Pt.get(this,"__className__")||""))})},hasClass:function(t){var e,n,i=0;for(e=" "+t+" ";n=this[i++];)if(1===n.nodeType&&(" "+z(G(n))+" ").indexOf(e)>-1)return!0;return!1}});var xe=/\r/g;mt.fn.extend({val:function(t){var e,n,i,r=this[0];{if(arguments.length)return i=mt.isFunction(t),this.each(function(n){var r;1===this.nodeType&&(r=i?t.call(this,n,mt(this).val()):t,null==r?r="":"number"==typeof r?r+="":Array.isArray(r)&&(r=mt.map(r,function(t){return null==t?"":t+""})),e=mt.valHooks[this.type]||mt.valHooks[this.nodeName.toLowerCase()],e&&"set"in e&&void 0!==e.set(this,r,"value")||(this.value=r))});if(r)return e=mt.valHooks[r.type]||mt.valHooks[r.nodeName.toLowerCase()],e&&"get"in e&&void 0!==(n=e.get(r,"value"))?n:(n=r.value,"string"==typeof n?n.replace(xe,""):null==n?"":n)}}}),mt.extend({valHooks:{option:{get:function(t){var e=mt.find.attr(t,"value");return null!=e?e:z(mt.text(t))}},select:{get:function(t){var e,n,i,s=t.options,o=t.selectedIndex,a="select-one"===t.type,l=a?null:[],c=a?o+1:s.length;for(i=o<0?c:a?o:0;i-1)&&(n=!0);return n||(t.selectedIndex=-1),s}}}}),mt.each(["radio","checkbox"],function(){mt.valHooks[this]={set:function(t,e){if(Array.isArray(e))return t.checked=mt.inArray(mt(t).val(),e)>-1}},pt.checkOn||(mt.valHooks[this].get=function(t){return null===t.getAttribute("value")?"on":t.value})});var Ee=/^(?:focusinfocus|focusoutblur)$/;mt.extend(mt.event,{trigger:function(e,n,i,r){var s,o,a,l,c,u,h,f=[i||nt],p=ut.call(e,"type")?e.type:e,d=ut.call(e,"namespace")?e.namespace.split("."):[];if(o=a=i=i||nt,3!==i.nodeType&&8!==i.nodeType&&!Ee.test(p+mt.event.triggered)&&(p.indexOf(".")>-1&&(d=p.split("."),p=d.shift(),d.sort()),c=p.indexOf(":")<0&&"on"+p,e=e[mt.expando]?e:new mt.Event(p,"object"==typeof e&&e),e.isTrigger=r?2:3,e.namespace=d.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=i),n=null==n?[e]:mt.makeArray(n,[e]),h=mt.event.special[p]||{},r||!h.trigger||h.trigger.apply(i,n)!==!1)){if(!r&&!h.noBubble&&!mt.isWindow(i)){for(l=h.delegateType||p,Ee.test(l+p)||(o=o.parentNode);o;o=o.parentNode)f.push(o),a=o;a===(i.ownerDocument||nt)&&f.push(a.defaultView||a.parentWindow||t)}for(s=0;(o=f[s++])&&!e.isPropagationStopped();)e.type=s>1?l:h.bindType||p,u=(Pt.get(o,"events")||{})[e.type]&&Pt.get(o,"handle"),u&&u.apply(o,n),u=c&&o[c],u&&u.apply&&Dt(o)&&(e.result=u.apply(o,n),e.result===!1&&e.preventDefault());return e.type=p,r||e.isDefaultPrevented()||h._default&&h._default.apply(f.pop(),n)!==!1||!Dt(i)||c&&mt.isFunction(i[p])&&!mt.isWindow(i)&&(a=i[c],a&&(i[c]=null),mt.event.triggered=p,i[p](),mt.event.triggered=void 0,a&&(i[c]=a)),e.result}},simulate:function(t,e,n){var i=mt.extend(new mt.Event,n,{type:t,isSimulated:!0});mt.event.trigger(i,null,e)}}),mt.fn.extend({trigger:function(t,e){return this.each(function(){mt.event.trigger(t,e,this)})},triggerHandler:function(t,e){var n=this[0];if(n)return mt.event.trigger(t,e,n,!0)}}),mt.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(t,e){mt.fn[e]=function(t,n){return arguments.length>0?this.on(e,null,t,n):this.trigger(e)}}),mt.fn.extend({hover:function(t,e){return this.mouseenter(t).mouseleave(e||t)}}),pt.focusin="onfocusin"in t,pt.focusin||mt.each({focus:"focusin",blur:"focusout"},function(t,e){var n=function(t){mt.event.simulate(e,t.target,mt.event.fix(t))};mt.event.special[e]={setup:function(){var i=this.ownerDocument||this,r=Pt.access(i,e);r||i.addEventListener(t,n,!0),Pt.access(i,e,(r||0)+1)},teardown:function(){var i=this.ownerDocument||this,r=Pt.access(i,e)-1;r?Pt.access(i,e,r):(i.removeEventListener(t,n,!0),Pt.remove(i,e))}}});var ke=t.location,Te=mt.now(),Se=/\?/;mt.parseXML=function(e){var n;if(!e||"string"!=typeof e)return null;try{n=(new t.DOMParser).parseFromString(e,"text/xml")}catch(i){n=void 0}return n&&!n.getElementsByTagName("parsererror").length||mt.error("Invalid XML: "+e),n};var Ae=/\[\]$/,Le=/\r?\n/g,Ne=/^(?:submit|button|image|reset|file)$/i,Re=/^(?:input|select|textarea|keygen)/i;mt.param=function(t,e){var n,i=[],r=function(t,e){var n=mt.isFunction(e)?e():e;i[i.length]=encodeURIComponent(t)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(t)||t.jquery&&!mt.isPlainObject(t))mt.each(t,function(){r(this.name,this.value)});else for(n in t)Y(n,t[n],e,r);return i.join("&")},mt.fn.extend({serialize:function(){return mt.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var t=mt.prop(this,"elements");return t?mt.makeArray(t):this}).filter(function(){var t=this.type;return this.name&&!mt(this).is(":disabled")&&Re.test(this.nodeName)&&!Ne.test(t)&&(this.checked||!Kt.test(t))}).map(function(t,e){var n=mt(this).val();return null==n?null:Array.isArray(n)?mt.map(n,function(t){return{name:e.name,value:t.replace(Le,"\r\n")}}):{name:e.name,value:n.replace(Le,"\r\n")}}).get()}});var Oe=/%20/g,Ie=/#.*$/,Me=/([?&])_=[^&]*/,De=/^(.*?):[ \t]*([^\r\n]*)$/gm,Pe=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,je=/^(?:GET|HEAD)$/,He=/^\/\//,Be={},$e={},qe="*/".concat("*"),Fe=nt.createElement("a");Fe.href=ke.href,mt.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:ke.href,type:"GET",isLocal:Pe.test(ke.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":qe,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":JSON.parse,"text xml":mt.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(t,e){return e?J(J(t,mt.ajaxSettings),e):J(mt.ajaxSettings,t)},ajaxPrefilter:X(Be),ajaxTransport:X($e),ajax:function(e,n){function i(e,n,i,a){var c,f,p,_,C,w=n;u||(u=!0,l&&t.clearTimeout(l),r=void 0,o=a||"",x.readyState=e>0?4:0,c=e>=200&&e<300||304===e,i&&(_=Z(d,x,i)),_=tt(d,_,x,c),c?(d.ifModified&&(C=x.getResponseHeader("Last-Modified"),C&&(mt.lastModified[s]=C),C=x.getResponseHeader("etag"),C&&(mt.etag[s]=C)),204===e||"HEAD"===d.type?w="nocontent":304===e?w="notmodified":(w=_.state,f=_.data,p=_.error,c=!p)):(p=w,!e&&w||(w="error",e<0&&(e=0))),x.status=e,x.statusText=(n||w)+"",c?y.resolveWith(m,[f,w,x]):y.rejectWith(m,[x,w,p]),x.statusCode(b),b=void 0,h&&g.trigger(c?"ajaxSuccess":"ajaxError",[x,d,c?f:p]),v.fireWith(m,[x,w]),h&&(g.trigger("ajaxComplete",[x,d]),--mt.active||mt.event.trigger("ajaxStop")))}"object"==typeof e&&(n=e,e=void 0),n=n||{};var r,s,o,a,l,c,u,h,f,p,d=mt.ajaxSetup({},n),m=d.context||d,g=d.context&&(m.nodeType||m.jquery)?mt(m):mt.event,y=mt.Deferred(),v=mt.Callbacks("once memory"),b=d.statusCode||{},_={},C={},w="canceled",x={readyState:0,getResponseHeader:function(t){var e;if(u){if(!a)for(a={};e=De.exec(o);)a[e[1].toLowerCase()]=e[2];e=a[t.toLowerCase()]}return null==e?null:e},getAllResponseHeaders:function(){return u?o:null},setRequestHeader:function(t,e){return null==u&&(t=C[t.toLowerCase()]=C[t.toLowerCase()]||t,_[t]=e),this},overrideMimeType:function(t){return null==u&&(d.mimeType=t),this},statusCode:function(t){var e;if(t)if(u)x.always(t[x.status]);else for(e in t)b[e]=[b[e],t[e]];return this},abort:function(t){var e=t||w;return r&&r.abort(e),i(0,e),this}};if(y.promise(x),d.url=((e||d.url||ke.href)+"").replace(He,ke.protocol+"//"),d.type=n.method||n.type||d.method||d.type,d.dataTypes=(d.dataType||"*").toLowerCase().match(Rt)||[""],null==d.crossDomain){c=nt.createElement("a");try{c.href=d.url,c.href=c.href,d.crossDomain=Fe.protocol+"//"+Fe.host!=c.protocol+"//"+c.host}catch(E){d.crossDomain=!0}}if(d.data&&d.processData&&"string"!=typeof d.data&&(d.data=mt.param(d.data,d.traditional)),Q(Be,d,n,x),u)return x;h=mt.event&&d.global,h&&0===mt.active++&&mt.event.trigger("ajaxStart"),d.type=d.type.toUpperCase(),d.hasContent=!je.test(d.type),s=d.url.replace(Ie,""),d.hasContent?d.data&&d.processData&&0===(d.contentType||"").indexOf("application/x-www-form-urlencoded")&&(d.data=d.data.replace(Oe,"+")):(p=d.url.slice(s.length),d.data&&(s+=(Se.test(s)?"&":"?")+d.data,delete d.data),d.cache===!1&&(s=s.replace(Me,"$1"),p=(Se.test(s)?"&":"?")+"_="+Te++ +p),d.url=s+p),d.ifModified&&(mt.lastModified[s]&&x.setRequestHeader("If-Modified-Since",mt.lastModified[s]),mt.etag[s]&&x.setRequestHeader("If-None-Match",mt.etag[s])),(d.data&&d.hasContent&&d.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",d.contentType),x.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+("*"!==d.dataTypes[0]?", "+qe+"; q=0.01":""):d.accepts["*"]);for(f in d.headers)x.setRequestHeader(f,d.headers[f]);if(d.beforeSend&&(d.beforeSend.call(m,x,d)===!1||u))return x.abort();if(w="abort",v.add(d.complete),x.done(d.success),x.fail(d.error),r=Q($e,d,n,x)){if(x.readyState=1,h&&g.trigger("ajaxSend",[x,d]),u)return x;d.async&&d.timeout>0&&(l=t.setTimeout(function(){x.abort("timeout")},d.timeout));try{u=!1,r.send(_,i)}catch(E){if(u)throw E;i(-1,E)}}else i(-1,"No Transport");return x},getJSON:function(t,e,n){return mt.get(t,e,n,"json")},getScript:function(t,e){return mt.get(t,void 0,e,"script")}}),mt.each(["get","post"],function(t,e){mt[e]=function(t,n,i,r){return mt.isFunction(n)&&(r=r||i,i=n,n=void 0),mt.ajax(mt.extend({url:t,type:e,dataType:r,data:n,success:i},mt.isPlainObject(t)&&t))}}),mt._evalUrl=function(t){return mt.ajax({url:t,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},mt.fn.extend({wrapAll:function(t){var e;return this[0]&&(mt.isFunction(t)&&(t=t.call(this[0])),e=mt(t,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&e.insertBefore(this[0]),e.map(function(){for(var t=this;t.firstElementChild;)t=t.firstElementChild;return t}).append(this)),this},wrapInner:function(t){return mt.isFunction(t)?this.each(function(e){mt(this).wrapInner(t.call(this,e))}):this.each(function(){var e=mt(this),n=e.contents();n.length?n.wrapAll(t):e.append(t)})},wrap:function(t){var e=mt.isFunction(t);return this.each(function(n){mt(this).wrapAll(e?t.call(this,n):t)})},unwrap:function(t){return this.parent(t).not("body").each(function(){mt(this).replaceWith(this.childNodes)}),this}}),mt.expr.pseudos.hidden=function(t){return!mt.expr.pseudos.visible(t)},mt.expr.pseudos.visible=function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)},mt.ajaxSettings.xhr=function(){try{return new t.XMLHttpRequest}catch(e){}};var Ue={0:200,1223:204},We=mt.ajaxSettings.xhr();pt.cors=!!We&&"withCredentials"in We,pt.ajax=We=!!We,mt.ajaxTransport(function(e){var n,i;if(pt.cors||We&&!e.crossDomain)return{send:function(r,s){var o,a=e.xhr();if(a.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(o in e.xhrFields)a[o]=e.xhrFields[o];e.mimeType&&a.overrideMimeType&&a.overrideMimeType(e.mimeType),e.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest");for(o in r)a.setRequestHeader(o,r[o]);n=function(t){return function(){n&&(n=i=a.onload=a.onerror=a.onabort=a.onreadystatechange=null,"abort"===t?a.abort():"error"===t?"number"!=typeof a.status?s(0,"error"):s(a.status,a.statusText):s(Ue[a.status]||a.status,a.statusText,"text"!==(a.responseType||"text")||"string"!=typeof a.responseText?{binary:a.response}:{text:a.responseText},a.getAllResponseHeaders()))}},a.onload=n(),i=a.onerror=n("error"),void 0!==a.onabort?a.onabort=i:a.onreadystatechange=function(){4===a.readyState&&t.setTimeout(function(){n&&i()})},n=n("abort");try{a.send(e.hasContent&&e.data||null)}catch(l){if(n)throw l}},abort:function(){n&&n()}}}),mt.ajaxPrefilter(function(t){t.crossDomain&&(t.contents.script=!1)}),mt.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(t){return mt.globalEval(t),t}}}),mt.ajaxPrefilter("script",function(t){void 0===t.cache&&(t.cache=!1),t.crossDomain&&(t.type="GET")}),mt.ajaxTransport("script",function(t){if(t.crossDomain){var e,n;return{send:function(i,r){e=mt(" From 1573bc817246006e988332288f23d6ccdfe32881 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sun, 8 Oct 2017 22:22:08 +0200 Subject: [PATCH 08/55] added offline google fonts --- package-lock.json | 11 +- package.json | 1 + priv/static/css/dashboard.css | 63 ++++ .../fonts/Source+Sans+Pro_300_italic.ttf | Bin 0 -> 24812 bytes .../fonts/Source+Sans+Pro_300_italic.woff | Bin 0 -> 17524 bytes .../fonts/Source+Sans+Pro_300_normal.ttf | Bin 0 -> 26884 bytes .../fonts/Source+Sans+Pro_300_normal.woff | Bin 0 -> 18364 bytes .../fonts/Source+Sans+Pro_400_italic.ttf | Bin 0 -> 24548 bytes .../fonts/Source+Sans+Pro_400_italic.woff | Bin 0 -> 17496 bytes .../fonts/Source+Sans+Pro_400_normal.svg | 344 ++++++++++++++++++ .../fonts/Source+Sans+Pro_400_normal.ttf | Bin 0 -> 26744 bytes .../fonts/Source+Sans+Pro_400_normal.woff | Bin 0 -> 18364 bytes .../fonts/Source+Sans+Pro_600_italic.ttf | Bin 0 -> 24500 bytes .../fonts/Source+Sans+Pro_600_italic.woff | Bin 0 -> 17368 bytes .../fonts/Source+Sans+Pro_600_normal.ttf | Bin 0 -> 26472 bytes .../fonts/Source+Sans+Pro_600_normal.woff | Bin 0 -> 18284 bytes .../fonts/Source+Sans+Pro_700_normal.ttf | Bin 0 -> 26472 bytes .../fonts/Source+Sans+Pro_700_normal.woff | Bin 0 -> 18056 bytes priv/static/js/dashboard.js | 4 +- priv/static/js/toolbar.js | 4 +- web/static/css/dashboard.scss | 2 + web/static/css/dashboard/_fonts.scss | 77 ++++ web/templates/dashboard_layout/app.html.eex | 39 +- yarn.lock | 4 + 24 files changed, 507 insertions(+), 42 deletions(-) create mode 100644 priv/static/fonts/Source+Sans+Pro_300_italic.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_300_italic.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_300_normal.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_300_normal.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_400_italic.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_400_italic.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_400_normal.svg create mode 100644 priv/static/fonts/Source+Sans+Pro_400_normal.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_400_normal.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_600_italic.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_600_italic.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_600_normal.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_600_normal.woff create mode 100644 priv/static/fonts/Source+Sans+Pro_700_normal.ttf create mode 100644 priv/static/fonts/Source+Sans+Pro_700_normal.woff create mode 100644 web/static/css/dashboard/_fonts.scss diff --git a/package-lock.json b/package-lock.json index 83d32e5..68607f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3029,6 +3029,11 @@ "delegate": "3.1.3" } }, + "google-fonts-offline": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/google-fonts-offline/-/google-fonts-offline-0.1.2.tgz", + "integrity": "sha1-69MEPKNjsJUTZx3hHZ1ipW/odtg=" + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -4069,12 +4074,6 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" }, - "phoenix": { - "version": "file:deps/phoenix" - }, - "phoenix_html": { - "version": "file:deps/phoenix_html" - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", diff --git a/package.json b/package.json index dbb2abf..3c9fe01 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "bootstrap-sass": "^3.3.7", "copycat-brunch": "^1.1.0", "css-reset-and-normalize-sass": "^0.1.2", + "google-fonts-offline": "^0.1.2", "jquery": "^3.2.1", "phoenix": "file:deps/phoenix", "prismjs": "^1.6.0", diff --git a/priv/static/css/dashboard.css b/priv/static/css/dashboard.css index cb73d15..3ea71f9 100644 --- a/priv/static/css/dashboard.css +++ b/priv/static/css/dashboard.css @@ -8143,6 +8143,69 @@ button.close { overflow: visible; clip: auto; } +@font-face { + font-family: 'Source Sans Pro'; + font-style: italic; + font-weight: 300; + src: url(../fonts/Source+Sans+Pro_300_italic.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_300_italic.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_300_italic.woff) format("woff"), url(../fonts/Source+Sans+Pro_300_italic.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_300_italic.svg#Source+Sans+Pro_300_italic) format("svg"); + /* {{svg-gf-url}} */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: italic; + font-weight: 400; + src: url(../fonts/Source+Sans+Pro_400_italic.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_400_italic.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_400_italic.woff) format("woff"), url(../fonts/Source+Sans+Pro_400_italic.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_400_italic.svg#Source+Sans+Pro_400_italic) format("svg"); + /* {{svg-gf-url}} */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: italic; + font-weight: 600; + src: url(../fonts/Source+Sans+Pro_600_italic.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_600_italic.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_600_italic.woff) format("woff"), url(../fonts/Source+Sans+Pro_600_italic.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_600_italic.svg#Source+Sans+Pro_600_italic) format("svg"); + /* {{svg-gf-url}} */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 300; + src: url(../fonts/Source+Sans+Pro_300_normal.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_300_normal.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_300_normal.woff) format("woff"), url(../fonts/Source+Sans+Pro_300_normal.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_300_normal.svg#Source+Sans+Pro_300_normal) format("svg"); + /* {{svg-gf-url}} */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 400; + src: url(../fonts/Source+Sans+Pro_400_normal.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_400_normal.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_400_normal.woff) format("woff"), url(../fonts/Source+Sans+Pro_400_normal.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_400_normal.svg#Source+Sans+Pro_400_normal) format("svg"); + /* http://fonts.gstatic.com/l/font?kit=ODelI1aHBYDBqgeIAH2zlADX0QHsyBtvFGhCuXSMYhM&skey=1e026b1c27170b9b&v=v10#SourceSansPro */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 600; + src: url(../fonts/Source+Sans+Pro_600_normal.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_600_normal.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_600_normal.woff) format("woff"), url(../fonts/Source+Sans+Pro_600_normal.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_600_normal.svg#Source+Sans+Pro_600_normal) format("svg"); + /* {{svg-gf-url}} */ } + +@font-face { + font-family: 'Source Sans Pro'; + font-style: normal; + font-weight: 700; + src: url(../fonts/Source+Sans+Pro_700_normal.eot); + /* {{embedded-opentype-gf-url}} */ + src: local("☺"), url(../fonts/Source+Sans+Pro_700_normal.eot?#iefix) format("embedded-opentype"), url(../fonts/Source+Sans+Pro_700_normal.woff) format("woff"), url(../fonts/Source+Sans+Pro_700_normal.ttf) format("truetype"), url(../fonts/Source+Sans+Pro_700_normal.svg#Source+Sans+Pro_700_normal) format("svg"); + /* {{svg-gf-url}} */ } + /*! * AdminLTE v2.4.0 * Author: Almsaeed Studio diff --git a/priv/static/fonts/Source+Sans+Pro_300_italic.ttf b/priv/static/fonts/Source+Sans+Pro_300_italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2a3162ac55579d4b102147785b74440db9e31a9d GIT binary patch literal 24812 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 aML$qblHHlVQ3?N=fci2|GuHobdj22$&7BGW literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_300_italic.woff b/priv/static/fonts/Source+Sans+Pro_300_italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..d5bcffeafd453c214712e80b868000ee3ca80a35 GIT binary patch literal 17524 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
P$Zj&q7)U4o|i*QK= zmn_1i6kMtZ*P_s9RpMHU;(8Ta?>H`*m2t`J7_O-o+m-a;&<^k#G~D6bfcQw@APKXA zV=mCIA&L7rxSTv8YjJUK>1KSNii?9cPeCaA%4dd%2*VA_G{Lfm-z0NX9x`R>aifTaQZz*=Yb58*!0NW`evk;sdxUu&-=zxLz-*L02Ui(Zp(QANDI~K6+`0xOuE)%@h;`D5)ng~9(fl++ zUZ00vxDXeIeEk-B;!>Wrq2OhBJKSN2Mitqzgi8z`q z&*q=c!%zJ0eyFaZ)<@(SBDm=bne(5>sQgEw4k)#N`9e|!ffPrOc8teyk6HL7ADBk? zRN$(`&fBN?52%#mr_H}JPLom;W(A$rmTOg1jt-c2<&yDDk^pu361wu39YGFdo{3+; z949d-l!49>@TvyU8c|*)aGw$<9Q&DA+hb#o_e}KiZ;S6Q?=i~Q46Upm@*E#X1FBK+ zhvc6Fv0-S3i$z4e9E~xQN3WUs0_C(Z{dis~7jwNzN&5);?JxP4C|#c3Q3<{)lBACO z$-rV{QM%}9#2*1Cejw+@)9nSyh2DfL|I!a=yqtd+v@n*UM7;A<)aOfch;%fr)RGs( z(Xk zV*R5T`*-y6JG9mi2NiP3{a$!N2w%te2VC+oxKMC={^)ovIR)gy$0Qd)Tg+qn7Ed1{ zg!C%V$^Q*^I(icPtH?7*9!0htOSh2k|2mw|7L@*B{`~yC`Jd;1mES39a|gc56>0UU zG82v<_SgA4u-dcyd-*qoK0$iKC;3Mp?cpjt-bbuKG&9HahU2CB-{R1_kLBM-sYhg~ zfLcH*9Q#2mbhmLVywvgsUdS)|i2Bl89;B`jLnL%wBr~*=#W*fd_eaQT8loOSQCoI zh>%`#1T#kHwS_#zVg6|G(}erV2~R~2a!b&wNAvFydTgYN(u~~_Ur*>GWu5s7t^mb* z$MPTdrnv8pn*hlCPYN;Uf$0o;?$D6g{;T+B;53 zl!m^PQ;m&;oPfAcXffzhXd|MOPa*AJrPTTN$Eak`pP!-@pJSEz94o@#Ah9sY`8Nu) z1^LIM2}bC18dXtW(s0J-7YG)5NYKuVX%b^a(T&I{a!p7rr;+PRmY_U8#-vn{ylTwf zGyX*FK<%kT;#-t3W^YOvRvLp46T_50g%Yx>euBoG*=6$Dc`u3iat}) z04v&BNQcm0bdU9?&>O|r!o8^5XXEWc4cQ`w!(1X8 zhCHJN*u+-kC*PwFR(eSMUR4kK7n|)^jVfhb3HF&5cjQmiqf`@YYrC-az37V|YzRjz83NEekhewCs;`3eC$(SuZivP+b!&|s%hGL=pj`F5Sk6-4=hGldU=T78#T zU8;> z$_Rx-raSrwDf-U;SsVY|T(Zo8tP)a5$Y99f!Uy#m*I^3Cq7bqJ(hW6*h9N>)`^ID! zV#y~W)`6l-|JJRrn*L?V{DYWFiajn8(;6t&L3%3G9sb>?;m!I4wfq#;&7<_62joxw zmlTfcYzq3A0Qv99{{iyxvHWlH=ZhTg%QBz-KLPT8iKjuxTBSFXemauBYK*u94&Q^l z947pNrSJ=W4>RX_Tqe9B{YJ>in{m-w9QWXxe5fSzWDh;rb~KaAA(sd!wgmJDRLX^4 zI10Q;NDN8HF|Ck^Wtd+^*9tnOlMxTkx=2gm0C8 z&(MH4^01Z&>ERT9))MUT#et`HV$*+MXheO;+gc&KtyRL?S}(k<)kWS`{67y|2H|Hd z7k*Zi@UR+%hqVN&%sS8{4{M3=tyUNLR&Bz!YJ*SuV$_(t&<^2YtrH&B8sTBB6&}_a z;bE;69#$LP5r3PIid^*MIoK!szuPx4GF9*50XK8@&z_6_{V{j;4BFF`cU!QwiM<}$ z36bwe7Rq;Ya;I|BiR(vM_rLYMb@e7T8UOKT>>KqbzL0lhh^MT|Q#nH7DvI?hZ6zH2 gZlxTfT#j|Yh?QG~v28?;;@l?IZwdF5!^7DB2LV(2`~Uy| literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_300_normal.woff b/priv/static/fonts/Source+Sans+Pro_300_normal.woff new file mode 100644 index 0000000000000000000000000000000000000000..5e8ea9a6b05e4df1b6836496576f1a7d57417eb8 GIT binary patch literal 18364 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 XkPsBHfl+z`L*xd=J^({`6%+sf2Sxeh literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_400_italic.ttf b/priv/static/fonts/Source+Sans+Pro_400_italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..05dd53b84b23ac47099fac52811f63fdf1309c65 GIT binary patch literal 24548 zcmb_^2Vh*qwf4;2l~!f7(rU}y-tHD{Uv1H{v@>VUoH^&r+$EF{ zq9Lac1z9nze_&8pBAiXga5JE-(`L^ayZNbmuf+QfLX2eE*u36dckOzFkmYzM+h&c$ zlZ#*Z;c0}>4R~L%`lyxLk{7=)PDt4qfbCtsa{IP?9wn3E1mY{!Z$5tAmXCJKB&4#R zkTzk%+Ldc6-`Z1wxc3m6HULmzD}NYyy?FO-IBLgnS8jJN!#nC!+_QP>>Xj`!hJcT1 z4Pg6@T6x?yMWwJ9&qGM>+OqPfwVvbKY=rdVo!+}`>-HV}J?(fOL>-C%VQr<5HAQ)LEDggn=^7*jx*ZgtL_wdU7b1oT=L!q+ACVdCPWtIGlB5!#)ny8W z60K39KotVRl^;F*y|eJ<@)(2<^5qN@s&x^135%p}3YX&MA_`##@sj%i$>kpxrV&Z- zlNMn%k?6k>{(<)qyl){A`4aDsQNC@@hVmLLIy^<`WSLVM&+$r=5atiKS5VqoZ3&K|9`7^Mc#nKXp(Lw?FG&n>i9+Zp zd7gy73|j32PDm$cK>srGwopcEaQ`jBjR=n;Jc)1sVJ=3X7NHIygD^@+{zZfj5S~PM z2I1cb|3df@@ghPP&nNJ3Ki-&_z`#b(b6LUeO8OYyTQRnk#6sevg>;j}WCb~ae2?5m zo+K}m10+uy>6q|m;RWGEm)>P@Ib0r>-_`2sckOW9>Z$h_Abpv1NT8e^as*jPzDs^e z?k7)?edI&rompAhawIV689!cK%VAvs-6aWJ>AuVpAlX~kdGIE#a9nX&LJ0&-N5oM=kCX3{E6Ew;=j2Rs7Vv+PJWb9czb4m_o5=O#zsOI>-^mT+M)EWAEct+(OCBPB z0+k*hHnY%&KuJ&v~QBf50`(UimKMB z&QSeTm8%F>3{{*~@vDlx6`xkp%9=`ZrLVHFvZHci<<81eD|c01S^2Zd-IaG&{<-q$ z%9kqNuKcu$R@GFQtJYRsR&{OFFRSjVdbsN8YEs=$ov!Y#9;sefy{39w^&8b6RUcGW zstszlI-<_1d)1@r#p-qHW7OYMpR2xHeVzKPnvt68YJOGohnhdvJX5o`<{eF|W{2j^ zT1D;p+8@{cuJ+YBU)_wl@7Fz1_m*~s_Hym5+DEm|XzAFO{( zC+IXfi%!xdbiKN9-3r}i-SN6pbrNcmq<>WZy#5XSzYHpa z&v2IEMq`C>iSbF1h?Qc!XcfKULUFTrnfQ$Oq4>Fpn6jqzrXQMKHHXY=%$Jz|X|Y;D zmZYW6GHzLGIo5Kn<%gEtmKQB=Sq@t3tr2Ulb(8f3>y6gk*1N0^SRc1OYkkT3ruBgJ zpsm_wwgqghwo%&-+ZDE-*&eeUuv_c{_SN=N?WbZ^hrS|g!Cb6>)=&%SYak@0b63+; z7nMXsDo&+ZnhjW~%6l4p*brxp|q8z27}Yrw6-o=wzz-B5l0@gY|H5I4&lP#A$K-pD_5#}nzOS~ zW_s*kb2NGIo&M2e2aqN$`A>wXa1C)oAN0h8OuAD*ouVp6C67ih=pA@%%8D9FJQ;tSGJ8_wsR;O3c3QFtB!Av&S-MFtVve{ za+9^I3GJ$qX86_8YoU)c2U66p5iaa`uJ^OvlJu1&=@o_4(T{3A zY)8`9dvkv;(xDA>0M);q4&ak)N #+K%XSHZDGOPTL%FR+nw)Ts7d;g?i)OX1(w1 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%0AW=qnfXt)J%g#lp0r<64W(lkT!dvCTms zY+%0&J=n^;p{Xn+EDvxJpgoYwJYWM6oG4kz-!rRbZfv$@ye-vw62dIa+}Iq=yzX?* z_qykt96NbW_VVmqIB?suXAf0g&St}#>3MXfLW`N~cldVYJV0gwa=gM0$nOh~QF=1{ z4u{-XfXqjllX$MX7=(}hPoQmG0=|JU^^KOd@mzb%sWoA{kbLj=+aiuSmyci7VleBD zEgOlmdwki9IQAV(_r^N>9k{kbLM;JBC_R%|n{38m9tp*9or^01aZ`MhHV4YJb-5Fe zjv`%zUd(rC9Aay88xEACs*Z)t7MIHq)Je8Be^aNqaX4{(l|MYtnz7p5R=wBiZEke7 zwsv__tUPG2A(RN8vuu;XTg0}ePTJVADUagI3$C>@8~e3EP1r3ZlP#5=m`&}n2SZkS zo4c_i9`SfYe_EYz*)1NQWDf;3Mw`a$a0d;#WYpKHQ70|-s0(6Tf-Xmda+s`8#SY%DzqR|MO9J(`6%@$I+Yf=;`za!n4qJ?&11U z8{XIO_di1W5sLBhPCi{>r#rZ7Vn2X5WjoqDM`O1~45*cwXji;kX=-tX(np(`M2p6u z6~k_WlYSAK-R2QZf!uv@i@ja#wx4O%Tcho+1|MoG)GqIFDQLQdId;OR=GN$Mn!26I zZg*3UGudMkLoS`$Wx~}%Pw(rDk2X2vYup@ebp<2xm9=Iq-HmU9e);X?KNW8`NC|5U z*SM+Pj_*Vq^$tU|o9^yN+EW2hzDDY-QoTK>W!DB)elCZ& zU5A(|dGBMsWYQ-v;eFw4ib>N{6)symlCZQook`uWG+gJjWWr6B4p+B#vnAPJioztu zb$h6@&L>7^J34$_^?JRwE7au)Vb1IK_UnxSojKetrLyKoyC;TSRh&KCuoiUrRYJFwI9jr!`!vyYe=RAFbW7&LAkeg5pKt81>Qy2f>FXdq1ccDwt$zCPFP+#kaOp=(jP z9{$k^w5YJ&jrK5;9#{CKCN^5L;-SIf>R_UQe;`u3U@h&eY7&&nRAolnJZ&tR?K8C2 zh9qZ8B2e?6$}g2l;hCz(XkV+;X7>BW)u)`;pwvm)21U!VK3{W#&l#|#21608R3BZk z!flF6FrNi7GygH&EBqKz(8qKwqo~s;betPIOZq#Y0G6;LYw1C}iP)@YAA>`d{?*bPitUTMv$7PASGh<~+=0P6w#>p>Qp9qC4;nqXzef z=^}2e-9dNr6yHILJ5gQ$vyiorVuYu-i=NF>tVW6_3n|1xiYA`o_w;(6B8C)?@f3GX z)Uu^e22^MCVuGxvj|m~>zsY8#Oe&KyqzsZ_@2`H{{_EZA|I+f{gDrpI>Ar&R$i(11+FYe5ZTU0J$sCHyRjs&diU6k2D{y0w9_LU@{q7<5LErmp;kLA|TYaT!8q{q+tdFzcmvlGfj_FZ-YX`hhOW;0zh z6Q`LnL*j`OPke%2b5`%HMrC4l&yB5&+Y)HHOgCoTmQYTG*2vU*hhBBsU9ETA(R$Zu zt;mBN>DZlc2RIa%V4H$Y;vbTYUEFzbcTZFi??&wDxsz`D{`Z-WAWD_=LCmboB!;%h zeY~=Jw>XSOtkIxPZ@s#=vC<9 zJmUlGh3uj4V`bTb{#8sY=(F!+n46j@k8FSBV-q{wW~^ZQuZR5hXmyQ!LnN`6vU1dsR+0C}sh8ht>B(1(Th0ePnYnTs6&Rp2zX_Rm(PF*69Q zG)U4CZs3BnyGC(mbb8DI@_yBN1nx+yO7 zMXzjUaihY0R8%Z4#vSSSnNPScvV+CtUqsvLdE4->1=$pahE(P}cWhB$nNn!>oV&}p zgQfaFxEnjA27xETil?e|pSWN=uvjVFZQFXZc_~Zvq|ifKK^1TXvq8Sf6%SZkW~)xL zRbtDEXchaEZQY{P*r#moLOK5y7Lh#q0Tfk02d}KkRSJvXEfVto zLZ4Nj&#GmNC&zWFWQ<$2qQg)xI)BFRMu#wJ(1|Xi9?-%aC4DJ8PU{p*PVu%Mz9cUz z0fCpKHQI&84LYOSpf|XScZ^(7h>-WeBeLw7;+Mh~8nO=-Gx4#(Cao)M31;h^5rf%h z5zSt+5D7IHgO2)8gV^Ax_lE5TTi9;IRz`S~;S+pcvE|!JJzdIZZ2=>{>O~2@N=X#% z@du$-*9963UTdw_V>VbMvjH3QX#Rw}1FNEZuRHgcr{ObTnhSg`X9(>rg45sL6qGE2 za>c6w!DiCwl}r08?dC+{f0Y-*1bny{^-^UexSQ>rk)H+ZaCa1*6{Hh;DrC44JJ2^2 zp3CsnH2Zdzq_udE$wg8vXnrEX% z7y5wV!p=6db1Sf1&C?z`kvc}2Ii^Pe|07WzOS2BSSX)-{{29D8!GDlODNXf z{h|T(TL`-VBKWR7hEfusK$2sc0j62BtOfPAVK-q1`e6WdOny;6f-mGJzo;LB=V2cH zD_{ZsA7T+W=m^-ROYz12qxk;+SD?dc_{-Pe`~S80KL0U%_x}XhgB@Ax@Xh~I*w^uE zwBaKBTfpD&-T!l-^Sk72{QJfxwD(ASg})hn^Ha3+XtbX7)=tpiSn?hGSHN-jABE%b zZwM!m6Y>87zrlYFoQ(ffIE9=Fng0jO1RuZ)&A#Q#-KF3$xch@LviqV5jh2s-t>p zphhZE6E#x{GzS~CV^fHey5PO^DAp}shpz1{#?K`(^uh{XOt^A>C z$A)9p%CO3HTX!DAft4q$J!Wfc&6cf4@eKTdWnd454D3YLeK1|YQqW`QRlpZMvHYuKP5zqv^ZEDk4?&xI9`+gR zi2vDe!*jBpwVe77MEB@kBw@b1;(6!+(hU2y1-o z+p}^&&Oyw%I0eL9N;h)XBB3rF|>0YBzQe! z_z{qjOSqg{5B{&`vyBJ|yaVO1QJ{lVXaBZvG0tkZ99}>2J?-@#c( zck_R@HpXYjaouEkRtkHYyz@7i2S583&gaFTyjzfeZ~pgqt>U>$xt*u^f4T6M?mukK za_}cR_?6?RV{f3#N1)6%9z`j@60v_$!u35)$&W!@o|jP>&>In@E4CjrewU^F`U8A* z*Eht1o>OZ67A#pw;MXUC*&F%W`5Po1$5qDhW4XV${QHc{nSZhJ@gH!6)Z`COHC6z@ zh-IU2QXgvor1VHa4`at{{I`??|5bzo6ylta{}0LJA0Up>mausF$bXUlqVObh)Q7A; zkQ;f~e^lYhFl2Gz{0@})DyK7-cU)%fhMfGUwCp_FPf&8?f1Q66CA`l-p!X;89nY-X zck_S4dmV#)+mZii{v}q@;SW$2?I^Z|rQ!dub@;?3(ERlnuY9H{0x=g(9IU5gOl1&S z&mj{DzUHAorN_S}dMdbV>g(6NVP@Ws-q`#9TM~X|=F(x0v zmGc#gV>~sPMtfA#Uk}N>h~xZU`C|ZiBmWL+`g{IH>DdB=cMhPUrL=Lmu`^fS9B))R|L>i8oth*d;Y!&B{;+-ciUJe=g zMR4)X`WvqI&xy=o30S4?y0ozd%?jzfB5N>cXy@}b9}{42+Q6(^o9%3?v= zPa!Skam;#K?nyag$uld1eW5I;%-@E5(7k28#PjnE8#Y@&%Qy{hyK!Cv2?{He=@VQ& zKO~Q8zzg#=dbETCkZMByv+56d`<;wZ@yhXeerg(?i*eg~`8N;EU(7eY5vYdSoxvbN6Z`AX>%kO1$+_joC?jtdOYe|+{Y)FZcnz=?F(&>D zedK;#_Q(0B_#OIqsZ?Vyq&)n*D$|w8*D09Ed8S^Gra*bQET;Kl)@FSOEfh7#S2kir z-iD9zZvi*XmvTvm;2^*cAg~og_!25$<5#1V<07V->_e$^< z<$jgeS(4Y!tAA?Q{Ph`hPcXT)z@tVtz$lmY?~583nM*9Kpix U%-^Vne@y_s%+nkPloI#<1^*L~DF6Tf literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_400_italic.woff b/priv/static/fonts/Source+Sans+Pro_400_italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..7c224fa86aff18d57f0cce3fdf3b0ec641aeefe8 GIT binary patch literal 17496 zcmYg%V{m5A6Yd+^wryu)+qP|O>||rxwrx8b+cq{fZ+`!KKisbK)XY4mduD3tOifpx zX*YQ>F#r(YM?^FLNdJ|86n@(OWBzOX{~|6TDh2=m`TuZ?Ki~q^0S*&akXQcU>Hq+6 zE&u=>P(Is}F0QO91OPx>{^5PC8CMYZ$BytnfItCj z*%{iJ{%}8ffVm&N9%2t}TnBq+7XU!$XD&c@KmAdN2=d@MIGO&~ih%y;{kJY^3A(QV z?(1;<`9S`Rh@f?wIItJHm_Q?a0mXQ|xsa{`Ye~Xcy!5T^o?U#m&zL1zn&+TL?(0M9 zAa%x?h`jx+(e<{KO)a(?g-+GB*D4nSgHff=D!tEzxgTBSbH9EswYPRI zV4U@V6C%+$vRrcPcs>tG_`LtQx-LMJLnMA{ua#fl@jM!Ii?>SFq0Q&|Awunzx4&)hY6O%K%BOR-1a4;=|Fov{CW)Yfea5*Y-Av2q%LvX zAz>|yqA_0Nm@s=%j6A(sMiBl?fc{JbA1l(E86V698+u$sg=j%Bc~a!}qKR(gq>wE$ z%A>?ODa%~aqzDW%2HiMM6S47ZMwBoPGn(xm@FOU&!tJ?9cYYAq6v3Z=7UZ>AwQ}qMfW;lurv_2`aZ? z8v1nqN@yx{2I<_&3g_Ucl*b0e9%O{()Z5@GlM6-Z(LcOHRuhTC9wc-ZTlwaG3jV=b zf!g1?NDQWmf&*OO4qj<5m|ZHQRS zvs#)lAxWSGY-FHUsVHSJoidf4$cMP=jE zx>IRQlO7=|q$)3$l#Mq22374;T$bnYQr?%WG5YB!$XD^6eJV^k`LdbJBVj4{F~7ww z-H-|5HAssylAZf1?`v**lt80B$SFM&AYN@$c5O~F^JsR7^Eo%djjm+9Z!B03{jEjr zEv4fF$X4zo)evrnWJ3M1YvvGdFabEcZ{tn+kq(I%iy5DEO&l4xQIguZ)?x(M#iZ^1 z&n4e3!{i=nDDyw_oko5kUiN)4peW$*X@I_s557%-Exn^FB36-{<1j3 zUrsg3_943AuXCi=46|r2b{8hY4q%Eph5n4KQ!8fCOmR3&LF@4w^wodXx@(SRV(3#( zjhPX9U}L}gdMAZ*!Pu%81`$%T(BVBY&h?J}Qo05djDkH*Z9Ph87IDrO@bht!K6u{l(YDZ1+W>{C7gQF+K}8y_W3K5m3yT91 zQ_ZPNF)*-j4f#9^sOk@1w0inF2->fqWo{F-(k%K^$m_)2{+bLxaiu$ZX}AUU)+BER z;^5M-{+vUD;iN@`=x1dypo=1ShlPBaXmE32OS927e>NOAv<~!mVq@IFwj41$3pjEH z%wM2q_PrkZr7;D3g9T08V2Ql?z`4O2Im`GV1c;RcXP3Wir`TLU6j4R`ky%(4!c4C> zy&hnE3D3DWu6lql)5WZBX`G!L?{8?#%YrL1vfxkiQ9_8!O^q2&PA|`|#J`|Sb8&cy zr18aEo#ZQ|Dxd`Dc_}KeoyK_?RT`gt5*1)k0F8BZsOh04DH3ErBT7zpUnXV16$apW z8CGM~G^b}Y*jmV7N08J8C@JNIFUxam91aP*`RC3{=IfG3w7IkepgB3Yb5h_yfA`*9 z_pn``rpf88^64pntvTXVnZa#}aT$f67(XE_Mwre30QYrc0}}&-T_Z*V2SbCOi9;Fg zPDs*@8^;+L7y<&nzXk6g*%6tKOiC!2Zv-Xs7)dZ20YqWP03#~KsiD4+zCi`}A~Y;& z{~|t(R$_pbEo|cd`ZVkM%NY=m91u_*Nwxni4sMS)wL5@0YA{p=i+W^cYG!75Y+__+ zU|;}YBnD3D;No}(afg~DlD_?EZfs!C(@$B}*T;!PI{Ff22_2_oU;qxNbcB=oZ@#7z zAXUjfXYi~u6H8|gr#Zsf&vEzj)KG1-TJS4H$DfMq^N=RP8`uSOY zF4j}W-k-7Ds13f8V<<4;xhn08+>NZJ%p%>8rtuYA#=m;+xX-J^8?-K~M$%n3o687%N>)+h7D;&hzv;SSpcv=#{gJh@E`E~!1o7nKNti2cvtT0x^e+#LjtJY z8%4JF5T?nxG{bA00O&y3GJ$o}_dMJ7!ZZFP0mC_a53m*i-zrar@vXhxsmVzea^O{R zq2)IMq8_G*?^?*KV+>{qy_`tM0czF9m?4@-mWdH57U`-As__ePdj&AGD-OY>^G{o0 zOFj~a4S#FV+1H%w#1)kSo_V@`T_mDx&-r!=LJn_QIF#w-x7gfi+d|5A+s~lVeo1OP zscKbG;|og{C6c?9VMnS1bHDB#Z_8g=Ozm1)T=K=FeTe9$tZ+nQ1~+*mQ4}Hm%7vRa zNXH|jwFQ{#zp$fH5)GT?DA_uQh0HRi)w@)T>p@7*tq*@z2k6I#1a@C<_J%OP8LdCP z!jn)b014fO@5^r$CK5orlqFs2T+$)cY}nMkT#ff?J!mU_*87T_|7yHU`c~4@K_O${ zy;9Rz@T%|Q@8rY@wcqhxx70IK`UuqYTj+ z&0;Nj2CYCXT6n`8<6+ukxHjUpdS-7t-@}e)%8{0D>Zg3aqK}AjYkuDM3*KDQD{ema|#pre-{sG|0YSPZR$fzysYt zl!Lf56pLAaw^U5R0AvPwF{Mde-$gxkB)Z;iGQ)CD@tGnGDt-McD4+HFCf7X;#0?sT zjslND^_6{%@fDwAf1*6`E(1aqJire9P!Oruw2TxQ@pmNv) z!H9I)D_`t|68)0BGKa~4fShb5;*V1~rmRu>fd2RER%lju0ZwG%t*ZHwRi~>hK`!sV ztVq{v4t{4S=jTb6x`dktY8R5vWVQknefG6n`Yd-_?;b|T7Zr@J$)fbHyI;p7^D_DTgQv6+Sp%m{=JN-SBB_1%FjIf{55#vp zP^4<|4myssC5yvgME^t}B(i~jo~{InL5_!VDv{y97NrnY@*QwCE)HYTeZ{ZPMfuDOW59&OeU$3n7 z?9*`b)ZfAJx08M)g$hc2RfjIJ^I~pNXDv00o6#kYv%za8p#7|Sa?30~r^>#%BhznG z*?L7~7=6Z7F(+LCeX8a5Hes(D?`0LTZ+Rc9fae|2G@6o6yGJI#}1^r}X$`+qOJ(t^RU4yypfwy0ZgTs%nbJ}SopS`p6y30V- zo;u$Eq8T|AtRh>-VuQ+Yjo5h&SS<#=2j`Td;qSvJ!0Pg_+ZpOQe0rCA?fYobX6=Md zj+}nm;k4lIOM2&YM)vmLrftOH{+ViWUBxSL3y1z-=CXWBBVz-6lO>87QD++lC!|vh z$6SfY5hrODo_}KQ0I0=2KqIuK7$trftII~d@tq9h-_h;8vFde6L@j20DT#A9ke>%T zTiqx_2RU<2(oPz}%+Zj7PhkyLoXpWwKomvR33JWa*O*1Wc9f~NV2s7vVe05ELEdSq0?CiwaKbsTGYd0BPE%@DWw7Ude-Emn_Jp6&xAC4uX|oi85O z_Ffk?PabvwJ$WA1T&!&7GgB$Iyi?94)7W=8-8*7tw!8|Qz-bTpf2qbb>{r-}$W$5% zhC|7+L$7f)4z3jIq0Pr1lcT5PgEBg6y~}jCYJ(B_OCsm&f>%+aFhsP!Vn;xFB;G?n zSnH555A(2BVGt~i=n$LiUZ#b&G!mCPk2C#v zl*6(9@L9Ye6Mjz5_dC5BKoMBlIV1CEn0_Q%DGGybE^B?W44C|WbTM3iO=!;qZ<%lR>qAN?tn9l`bo)?V{F zQ<`I06&%ePF0-Z|$MJKgt!N_tfN$f&^F9)ROEk4||AX1V0c7_aL>Wl!+V<2ed8NET7+~A1M0W zX~dHS^?W;Yxx7>%{FTIVM-jo}T8ar)o*e+rDzJoFGH5`lC}RPX4PsaZf{o%&`RR6~ zc8j65V7P(Fy~sAGk<-Nbx%8lOxoW3~;cQVIs~mw6)l2p9X@XTRbcGNQ*u~=zsTkWtQ8>=WGU=>etvE)_Qd;d(oDJ z?q+U4kY;|!TBGJwVD|1h59aCOJw2nDHp-CP5S(w&I)Pnf-9U9x2*?>u(#z`Ly z{{)NMNYDmdr4W9zsOcTqVj2=CovDw()AKM|^OwfXUf%)&(keC(p`Wc%T1FHy-N#`7 z&O;fn++6;TsOiB4@q`$l9?8kO>4>CsD&+(;fF99-Z^frsRge@GVI%fP9n{@00Zdup zuag{s6%vO$K6yDgTxnQXQ~GLK%%lYGUYRx1$=-T&DGLKzSs$uv$29C`yg%@p%FUH@ zpYFWTn5uGtbo~PYfBx44d%t-Lg_TG_f5Lq}RY=cT z?F|x3g(@Rf5DGCyh&Hc;R#*mPVgNicAm@#aWF4u{uxC#yZA&Ya3R69OdN#Y=(hlWI zrP+L|0?ubWLP=S|&VsddUmj>@PX)Wr547i95nMN><3@x2U8;gZTgNxTz2#v{4x<@H z>*7pj6-aZ2>BU5w1u3t(S>Zr3dRjSc`BDJ|@rvsJevh6BrTijKdzCMFXEK!c;5J`X z%-qGer5@ablE5}iV`7%?f(*@}tqE|aK|<&d(GH?FBs2rk$zp9H-hy9n}jZL_-5%#7VjTAITM zCuf#r4h8jlU^tEp6Adx#VR@9IFp?zmCywhPM7LUMcDT#s^BXa%Og-5R(zohJ)11D7 z<+_{(#HZt+gL35njp3a>nRb;=S{SMvFunAZxnioW{oClv#ytGBeYmI*os)O`@p}Jg ztl!`+3?G^L-7cp4PxV+y=4EIhF>|dhDwQ?1H^5^tznjJ)?kb%3H-|*)JBV8cKkd*b z5hkO|CjK#jcCW|Tc{WB{ns|m@6oLKMIR{2}vO$X03(FgYftlbqT9e?jWwE`ZI8oJE z^LkanUoH;BOP`C6rKs?KVDCdUFmF-x$5|-X3gsFsX5gq1=mcpi2C}8IdruZp^X&~m z2vool&0}iV8#ruz`S?6ylPmvoOq)s`C&F8*-#J9Z#2rlM(d`d5uF@`bRSK-f5NHup8!lFXRl$<)E>6I`tSHks zSzTy_ATyF%J(hk;GGvtIS0o#zzdH!`cR=KZfIYNZ-6TdN`3k60Ge{FaJlg*O zu@lxyr)U#3z_o2cmt!&_Y+kVgciQ$vPJOj+gm|uvmB>s$MlI8QFIj>tPk#~K7aRJ$ zHOVf5-yXD*7SxJ>B%n#02n_k@OW70Tmmrjo;{Ur;0l@1o#=@AIN1& zYZ0jfb&Ij~?nB3u)mZ;&dH_jy47w^`uHYanan^N^@?f(-+kS0YIA-q{aQ+hfn4fmh z<*l(=%#=@P+`u9HvM6Lo`MOl@=a zEKi*pMYen^Bgu_9b=q`TM8CyeQrp&~>s$!Re@NmsodWxlu)W6tmS|Va&0n&>Eu3N@ zaN6i4>*JcKdtFNbd{jnvDXYb6+1qc(RyoygFou1O5ysFC-(+hFPqag9%OwvU4x-cL~e3W^K>YtAL(5KqglIrr*g|1d2 zRUwN9*!1qAv2*iDNhbEx%A{GY{DQLLSvb!FNJ;M?!#K8bi<60rDNueIb`*f8MTH)A zf|Z=cT4vKRA&%V#${ywm?^o^!dlPK#t6&8)#RAIEhsJOu$!8v`WBV(Kq~(4!=mAh0 z4+7?M{vO&t{53`ome3ic(fQxX&W573LWa=V+k87bKoVV(Gk1IGjIQjuCME@hy)YyU z&$Q*=wY<{qzl5Bk%K~8SJl+s)oW-K*2X@)@Sgei0_{U9ocs?KOc>j39r2=g;+!*K2 zV#fO5v0*IVEbQH|?tIW_`tS!%AOxWQ${{9@l@p6RERL_^n4gV<$08e^mUu!2FN?Lq79OH+$&~A7wQ%L1D^tM&4VJ*gX0?+SGh3pL#F=84#Sk>Wuv>4so-+8g zjpZD-k-9PMeoXzL^+j@UEiC8IS4{wu+Aj>A;j%=JBE1mQGi_kADh-XJSDbC^*6Q81 zWEU69I)-yr+_z^HophUI)2}1FYbJQ8s5tK!J4ns!g_*u5BwKaaN7(Ccf~h0D{N(6! zYL}Pl4wQ#>do8*tkdNSW3$VmS!}sbyK&Z&jw?0>TsSxY%Fg7;KPZsXKGA;-sA}u_b zU4WFl;cx6TeSyKd;crM}{&*qIx@}}({wR)l>NP}R{!j%@9p#k|>6P0x;O2=$gb6U; z?ZngV8OmYG7RlrRov9?9>PO@y_EVlqC%%Fr+maA0*v%2;dL4|K@Z1s6W>RQuZi-fF zn$3zG7Vt(aaBu6lRX(tBDe-{w#oZ~i|DwOG>^UHIePr9A`#5=gsi?du`3joyppy8W zvJW(`@7N_-LlGzrRC>j^BwcJRcuuk`l>(rPA*AlMU`%tp#RL^1B@#eNb4s2i3|uvzV5)UM^>)@;XRM`4|XuQa)DXBvwPJk0ifYC-H|#?Q!^SB9gw}*JKUbw z(Y>Os_vW!SBuMg?RphrG0f?Yy8NC#@9Yz%%u^bX4(R~?M8p39Wq8ll-`9~R=dNkE+ zfhko;q_s#!F;=AA7)e!=!=lJYbhbFopFbfH*UdU0Ke3$;?K{oS1>%j&0 zXJddS(Z)l^y@^2|u z{or;nPhkZ34?*<>QFc+jkhR8-=)in2fQW&@@c4cr1Vv;!xI8rTzplqyV$!s%a8?zx z8v22o#I!*3L^C|&B_p#wOaKO-0PEp+ag*5VkqcNcbJ|U3QG@ID_h!y#frqm((Plb}`MTkyqCpIg zY1`Yb*0FViLEfzK(1@Dhv@a4vpvRNqCzmUyUM}?I1i60|1QPPUllJ&c{#zONmzlH! z=8s|cm*=#Z@f&qg&R>mImfv1yzE77XI2}2v6SF6#r)tM-us(_*HRQa~v+CrX z%_p0_gBQPz-cKOekU!9X#c4Oak`?zk5JLkg!)y5dBvNP?D9nvJuHvsMJ~nh$L4=)A z`3s!|CV0CEmnZ6=&n9|$U!2GIqwJE#vrS9{U`c%$p%3k+l&BeQc=MFEm zvUQ#17zt=S2O=}$O&-(e_hMuw_w>r7*z6d{GiT)%(oriWnh_~savUF-Br$|oCPhZs zh$Sa)F$IY^-YEzp+ca#>6GScxDVgbYv5zKF1;*Bz!|M-yRu&#i>fLo5xAyWL)!>tM*=sg;x?PSO*WPqVK3FbsfL z0tlfbwJLX0-H+4*%E19kg55?;f4a{)4Gq$!#BLC78nA|gsxcYM-{f!;z@wKX_Z9^z zz$B_&!bb#lHSef#<`RwMCHNielOwQr6cGySJ&7mv3*|Gw3}FEymmVUjUuZTr`ppNZ za_Qvu&eE?g!y(~O%!ky4_oV3Y1EdL3ed6YXdvDSa>&pn^!05tw)BGmlGBBO|idByNU2xRno6wzW!qD`&Z0?76kg~vqOqd^kforSwxz-VLRTSE zuEuLvNW;Xu-_7RG1FIRn$RjzL6zY;9IGlnjgP;xt{`8u22gLPe@hHGRkdaveYs)T1 z9uaW!sDppjO1gN zNyL7w))Cv0%*cZVE5Z+)cEBap$2-kyRg#j6UK^0FQx@A6vlxvxS{2&UmB_$ZQ<3iK ziz}BXupS);E<5ySK5!8I_Rc7i5Oc0(L5gOEU11efe^HYDQ_{?4S zrVNovwDa;}Q5lX#W-FS=b(;EWo%7bQYGW}_PrW8bLd>5CHNKPIm1p2WL87k0~27F3G*Oq#-7T#0b z$PYOt)TsG&6G?CF;@@hO*IOC z4{A$vghlvg_yQI`UmM51mi(&O&C(aAfJT@INc0%%x$;D!4;D zb`v09dV%jy1U#DFQJ32uMo^21={HnvY3s}Jfh)4`N(1w zUXC7+V3~XVYabkDvYtzN5dYcVvJO5DR)xKO?8no8stZmvrVcXb6?8LsKaEpkk3k$` z<0Q zI9JN<;K45r>xMB8;vpRGsMzwH|77G2b=+&GF(kR1MT0o@s24L4GCwqPDf-`Gb5uWb zie|zvO~CnlFkV1?OGRI$5lcu-=*Mjeb)ft4A|G7wH^IyAK}bc2d_8)Q6INhyk{jn~ zhg29axH0R?wyB+%g}i(|MKNH-r`pInoV!$`T80=Av92MQbTHD$jnX1w&2R||+lm@q zeo>o>9KMBS?!*P(R*41MLy^SKv+#MoQVxU#>6B~F67|glq`=_8g*xJe8zs7$FIu~a zxZrov95r_)h+OmZ)`4un`C#V9nrdQKV?ZSVE1KisX*Rd}k`4AF%^$6O)kn4CyE@4c zU26a4%j%_6i`^~70^0Hqx&2dyA?3di-?7Kh;=Q=*u?mYRG6(lNc$XfWv#JOu?Yep9 z=Q73DFO%AiPRvY~K&H}v{7(X0>?fOEGe@yA_;A`k5 zv-Ypp@d{SDmTWHl&K@8!KiE)uYYpUYmP1ue4Aaa5F`mXyia_k zXmLWFfcsd+TtT}$>W~!Miy^XTLqqBWx>CLH&fzmh%!Iuo9eyA(v6Fz&WWyfN^*jV#8PH&4kZuWfRzf@Ly${7{bGQ?p z5t*LRV<2%`PDJdnKfe|2CI{Er5FdW?`C`(f)k^tT<}-*^GNk1q?@*zIMz49tZXGx$ z@ZG=cL2_IjU+Pfe?pn7q?n>Xjq3)uI+Ecs?pxuCRVjZwBilJ`F?m86T{OM)Lf?>@b z1(@tDqv+cRIsj#d2BQbJObLV=;*ZW=yhxX&-bIUs-BlCA8p@4#`}98f6I(!liXM((-p?(1Z z2GMpO{!N+Jfpa5CdxRjRyvQeDxo6lOX4^ayvl{UENRzejBF z>tI*_wzTCg?cpUIwQBBr)7^lZex46TC&{N63mm66K~D7F8Kc)Vy;n^#-uo~cJ?Aek z1_hrd=WD4(nYZZJ{!ai;CqxciJ}D0kaFIyvqrjB3wP)F*Ae?uh_4CwWM21Q<>fS9j7XC8_u6dJKZ(xhraaP*- z>)?!_Wzdcm-I z5II@u72-+Tl@50~X-H)t!)>=><=4X}oBZg@&7#302^hzjpNg)rB}z*pWmpfN&|naZ zmjT0@d>X^3B(IM=(16C!!b{}m)GI>$`?fnm{J|DX_o?1-YgqAo=*GM`vTSGMw~4+- zP*r*LEQ{}b&M&nl9$&{>rE>j}LjB^!#)9IbeDjniJ=%Rj-v+9j7ql;57I}wuY(L=M zTo2U4;SL@aT>Rn+m?Vr3N2xst1Eb1U8FQ&-{dRtAn*E=z^w_vRD8l(c^80L44H-u7 zh5d{C{?{xRib_p5L7#*<3skd^^r*HaSBuG^R?5pJ(Q+HDypmv)DOa!hAL$@?z5xt~ ztbP%??mw}eBZG=eaka-Fk6H1Ns)1)7_VddGHz$;Jy|X70aJ$ufH;o%_2~76PxDDsd zQ{$NWHzG=1G}t##!xA3L=T8vQNZLGcuE7E|gZ&0wxaHAK^!9nk2atZ|=rN31Z!oYU zXnsM0Uz(Tz0iJ$ht9p}n1OxQatMpzsVNcuanaOO;zqXnaJZ{APqV#MTxZ4Xi92|tF z++8;q$G*pMCW62>bun_tzAJtHe18{-8bmDUAex~UwMOA-255S4a}C$=bN*&_F^8Zu zFHjT=Z*f!yDN$avTRt8ZRZXS~63m5z2d}vd1CU^YO@rKV1&!XM z3S5P&ON)S5l)Nu)?6J}z3m{oS3H$2=liI3-r0YL833A_19~!o6Y;SImsgTA(jly&# zb;k|WLO>|d>syjT6>q5Lgo8mOOow}xrMRR8{vzT#him7QpTuWgz09IH9WtI)A<59- z#dIvei66@7cNohgfLl@bx+gKzC$g&KKfZS$TFMw7Z@e@kh_84U&-uEhc^|Owz}3Q2XX=xi1omlM0$3p)xG=)!T`NfX`jkG zZ?ib{zim#UUGH%I-qwjC@RyexcLEWl-)nu5R=%x@JVSxeqCZA7rnfgpa;>kSK)CSri3kiWaN0RdF5BX z?b2P1qv6Ydn?243KU$1Qf(F}*VJevl?p=xHbOZ>|2bVJrV?To9(v^zX;Jgmb;9p18 z7(m-{gVL;S7^5nfDT1yHHI;Ts5;&z-k&Xpe68boteWFw;=(EH>??wA@bu9u#Dv$lM z(Apa*n9Z=5sx$3e&B`54!sVKf8SKxuNv_Y5z5TI`kQKaXT;GN}fg{R~p#5=*+@T1F zKHzuO9=uvJ*(l^sH`Z8th%qaFoqkWCyK6c~9fX4kszX7j2CQ`**<3CuLKXFIEQA9u z!|GegmV}&Jmy0A0H|&j{(9{PxgovH?k^5re9To_Z=aS>C6l0?`z4YJ9nl+n%)7VJ^ z7sQ(1m{t%%m&Lf@!6xFLbc}nkfyH8Sb)->@C$~+b6mdx@?8_Et6FK@$3sBU>s?{S*x047sh9AcX^(j@B z@}tBtZbne-t_2wR(`5e$=`@v1fOY-+&3q=`_v{qEegHdQmnOn1Kl=@q%7Mq2kX#7v zd*nZXZ4m9RrDUIHaZdVb?_uIaR<71u8`eYF5liY&E!c)ZW~8=%JvN_|6B=lPlWm7wt(<^#1Vq_=b!SUhJd9uB;-V zl_=%OV17IN8%@_NZ!xvU4<0(^!c*2Xk%1p~A2eGi7ys`QHLj{(fqQ=8WcvdjN-FI7 z#|uGvGYHW%5o>S!Z;y+Pyl3*#rR*9ABc!1wrqXNC;n{gW4yk@wF}2BSL)Unvf<7g} zJIrAJU05&U{vI-rG~=$nHKacO^4N5$Pqp=OdKK7y`Es&@4Fg}`3d?u&em{|=hNk+j zyr<(q{E1~-@9FFS>t(~Ibr-?hHS-1V+xY%Kb=0%eQMh0OhwQVD4YleElaagEi`bFlCBqg*P6Xjp(Q`Za{ zW-nNUJE~GCx`0#}X8$kNYBnn0xcqK0)zBjZ0S8Qm}uJ4X&a?N2^`?_hptn z>i1=qgpI(EGHv$oy`x_7c6*?HS9&c-8ll=U9TdTWDs{xfE8Qhe5UJB@qT-0iG7Q?23QNUxCrZ}?pEr{Sg**vH|wV9>Dku0a}81El3jXv}Ps(!V(O zY&tOMNI{={SrowcfgzNN8Wf;=_s z-?Q--vwAJ1w?Qt(O{!{=>@1RWakHD%1Nc}+WYN!?8e zruG&a`dO^#N1%9?Op#32uWn=c+4v){p}Zv+zo8jM0s-p0sveUVsyRJEHW^9Pgi0SXu?IFXqGbGo|a4ve%u-~e2t@#i5Flpd*p^w#KFIT;%{&HH7E@eH=x zm~eq~X9#i@_NM2E0i-{TpTc z*EBDXwvNA=+!05R`eK}=>5eTT3t!OJ_hl?@eagWonkg61zhn5Nv`zAcjhlvp?kGFT^4_nK%`i$C7&@>-<5C27Oi=SDViUR!5Y`29@2-70t9)E+yF z5VHDX_dX|hTvC)~QwFd5)2+}9NKVZ@5DQCR!?)TQ>eOAhF#xkqku5wh5Jt~i5PrAs z*ReZp&L7>^(Q~~o?}$bLfeQhFz>8xz--3MtB(ISKVy5_+;`*HLa;p1MX#)RUu3svaWl!Km|Bv(XLG!3f0Yz6ZdPu*YPhxD|EgPw z*H-pxVA}TCeV}O!`=2@aL3~=$!^r!&xefA0dxeP4+qh!pwDovAV%T@ZyU#3W1oVQT zGmG1zC)zZgk``xApj=CcH;8IeO|>uFhAmBJCQK9giR0010<~g9{SoO*BF&O8M?j=V zMDP)p>Q|Z#zP9oO?S(M$0HO@M>_Ym$d5f`Z<38U=_cs(rKT8&r9>pn$L@yE82KSTk z6?Jh%c>R}tR>o2N?|ynKO8?wlI;o2%qtT0lr_USr@JzKNWM>8&{l3nTfJN-Cj+?oz zck&?-_A+MkLY|p~^tprN;?2=4$3z$85Dn_i#|%fLX$L+om2B)f4fPBD9>>3nTyUA; zr7px1!cUga1U()54cpNsFGHreIPM`3L`M2(sQm=3+x z3Opl;T`xD9*@d%0iHE2yKI03~Js!{BX~GR=SXxjJV+?R9C=j|o8K$u4NQ4J|D`g;&}&7d&wFwG_9 zW-WrJp_(r!64}s2axgsiQWP$vnR;9Tbt{zl%lVGOF&!I2uQq1W-;P@AK9gNj17MeG zFXYK#LyGC6_3^SF`cWw4pM#+>#tmNSqqgW?vu4d;8)S1uxQRl&hQ7jX$w%hY?~*er z4^eV(`xE=7%7kYT>XTndQ&^6U({+iGWJXVIGg)DdOu4_Z9@cq&c9`t`Kg7@vIIr#R zJ&l!nvPAK^h05fEUpU@rwPFXmag5MR+N-vZp;_!0*G<0+?P_&yh&r_C!)eQl`r4Ab z6+l}-m`aj7!;Y6KqxiKLMm;bJSMLM++;Pz>jZWIuFD8#>zhn8nDfrb&vj5BC_zx(* z?E|De^bvR-0Z<^PKMY_V8cXiKa*1E3{+sUW2viAV8~_Y}`oaI?|K&#Y++Op7fJhJf zZTbD96`W+igl8fQdIt2|LjEs*%61+kN>>mQZ1;XbN2$Me*Na2_FUARjuYe#0drszFOL<`1iycv9p{R zL2p?HW3*47qFD7t{@BrScUZbhZm?d9j}Do916)El8o9swuG3Fbn*)_r(+^wTmT9yE$kI+VF)rTp=k9()y``Z)G-% z{I(}hBNFqmHs(#)GdME#dgd^B-#D)_IWw7`-oo*v(D5ex#*BW5_S_sZmmoZi{Lkqi z{bOck^||KHX8hdc%wr8Zs$7l!S_NG^V&tNKjXx88>vaMxndw+#63UQ!h+*{~QPi}cyIfWvZlQyUxIH(V(a^_0lGF_?3fT!YmkXlfBXK=~ z9k60-nL+VP5xK?`9+HqKXIj2&P+9_P$;v|?#ChG8`yq2$SyhV=BTA?jk+y!rk3kB9 zJmNP-A;Kz?JFTT&FAh~+TKWasP2&DlKXU)hcP|twrgdhp&3ASQ=TlS%pp^qJ<-z;+ z$P=6)>lW)jM9TmSlZNkfItK-i99y4KfAXb_3=AY72CAbHqSB)#Fmsv58C6;S8FdWP z_Ti4}%y@@_DIoFy7~w$x0Pm?Nvm!j4uK%U4{of?EmVccV88wzq=d4?REt+m^eQkct z??HuW#`(IPwDGphm$}6OmwsFphDJ=J#k>dokL(q01{5X!oQ0Wukn(?cGE8Z)V zE1D~aD~>Ay{A}~8l~cTfpq?P#Lx!VVTnVHy+*RDe{_{FeONe7t;;e3*O)LoZHy zca;~h7u^>ORSPDq@a4iOOAM|I`hts7de0QSVumyQ;XKkL9Vs8vx(0={+KO|7-#HzE zyv2OstHj;J)`iR+tZIZU46Zz`M6N7Pl+y>I2SNL8DAU0df+)Jk+{n3!$qC}D71752 z&Bi2aA}wLIX5y==Pube;?Az(j|0jI|g8bw2_+I{5U{Ore5wpb-u~uvo`^5=yQQQ)b z#W!h|L785bkPYP``9S_kn=Wmmv@_D4OZy{TBwge`us4xz000000RR91?*MQB2LN>d z1pom6000003IG5C00DCV0{{Vd+KtZxQbhq20ML`&4#F_owrz|uzVT`$?Kiy1zBW+g zP@bIp5;>}QwsV!MezxoSrS1dhdAJJq38yFR^!Oqe!l&CrMb=kDj;mJi*(@2UMzyX#y=*0rRB+7Fx8ZK>56 zMxJoUm88IFSbOWaTC4uBKJHl5d02CyHQaC#_V;Mjt4p_bz5o8>N+6Ijs7;%!QyJG% z0$Hu$%`vT#GA^}QGi&()l*B)@0001Z+HAwM5dr}K0Kpw-1$Q2|40m_Rq%I;-q<}vW z;rsso6bR#msF=8fq?ELbtem`pqLQ*eMO95*LsLszM^{hZz|hFp#MI2(!qUpx#@5c> z!O_Xt#nsK-<3|uYYzYBC0RX+P#Mm!3Okgpsxy z<+agXc;&q}-g;+@Pd@nQys@^q;H%HR7^lI1O(qy`qRA$i;()29n`VZYW}9V>xxSfa zf%z6%Y>|U5T4$*xmRYXRE%lnCSM-)DUx7kJij^o;rd)+w*(y~zEx}=R4oQ>fn(MB( z>WQcBx$mS?aw5Scmp!(|An7vnGr$nTeisgV}xkrA2p z+80@oZH2p%t+G3EtaK-GrRdVBTb35BZm3bM)(!&=cO>!*w#j!tZ1&S1eUx?Q3mgQ3APC|%f4Qs%;^;SUw{v|xtm{-~th?9U_5ZVB z{(T^{SdYT*B}nrq9c5)G#U#5Y7nK`d!#q){xg=q5{)QhhpoAC@LJtV3280?MX z=xy>O6qbZwuB?}e6d}+IPKQY6Flc%?0-9cqf~J>anlsS!Y75YGIWh%Jn?noq15SXv zJpcfB+S|aO&9I4)iAkGr6Ele1&g^8YDJRUpp}n2O3d&;G&Y0j~qb3FtWb&}lQ30}m mx>z~bwKp&*xYlM$xOneiNC=A9z$m?eA#wv_9{|0=5?=r>S$};1 literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_400_normal.svg b/priv/static/fonts/Source+Sans+Pro_400_normal.svg new file mode 100644 index 0000000..64f90f5 --- /dev/null +++ b/priv/static/fonts/Source+Sans+Pro_400_normal.svg @@ -0,0 +1,344 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/priv/static/fonts/Source+Sans+Pro_400_normal.ttf b/priv/static/fonts/Source+Sans+Pro_400_normal.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0ed7e78102e184d2bf0add908f272f3c56803788 GIT binary patch literal 26744 zcmdtLcVHaF**`wBck0qfr|VUFMb~sqSJiv7CE2oMxg%V$!42F95Xu`IAcPh|h!YZe zf(Z~xLQ8>=03m@ufDlT+I0PIMObwX8i*J9Qncb64HYxA>egFFH>e<->pWVtM5^e}elBh`(~p=2a)hU)c8tLW(XUr1;A9tG1skNuW$dZ^ir4^_xyR zVbv|Y3y@(AAuX3}Shs3zRm}t6z`H|$%myIJcNZgXiadyS!{!}d_~FO(K0H50i0ZLT zTi2{wdd2WsLMj8m9oW3;3n#0z!s)mlLVR({s?F;>Uux44GIT9)kDk1B`;KQH6W%6d zF3P9sCX831XyxN4eCPS&tJ^*zWvYX~kY~!xpR(||&J}m&T5>O!ZdE;o$1)-?EDoeo zy^wnsEbPJimeQ@9lKf7-e!wvwkV{D=*+q(!_vOfr(Cw%JN>oBQy$o-NaG|gSiH7Bn zPLTxl09#R{QmIvfpvF5tfR&XW-F-dtNf!~_2H_p4n3aTTMMAG(FX;i{3IrmkUrd$~ zlv-f-BV?J-N>ajlgwfzAQrvQOFoufpzq>d zBIBxdGA?)kP9A@pr&*5lHxN4=CuXD>rq7Z};Ynhq4-gHzr#GXVjGxZ|Rfd#u9>E{u zF%Psv`V2gdB77I{)--R7zuAyb%?FP0R{)&9vxrL=ME!ur&jXc~v@pIo&x~&c$YJRa z=ligHt4Ph3v8SE!Pl}Lh!*G=OjKtDvA#n7fP(2XIV7^wrec{oMN$@^plrsdALssG>C>$h>^d@3LdnAGLusWn$$znhN-~oh`a5io!si&JEbNO(X^UUfZ1xN!- z3bd0&(ozPhCgM?5kuFsLUKHv<%7QhC;4*uab9(L>uXZ@Tl;T@Uo~Et)f$Oi$1YM z>=Sp0x4LWH254pi3UScsCd?iLb?YNRwCz?e&PuqM{+7XobA;3>T zhe*2sI{_&|a>iV7j_$vZ;rE}lf9?LM{k!+~?zisy`Mw{6lNO*C0agMw5Yz(Uz3N)FUce17IGWeM{XxSC*LA3knfN?P;U>B=g8e? z#Xpf3$q&gj^C>9rT{B@9MBB-B7n7SE8qe^n*z@wY**kJgdGaNQh=6`;bMec3fzgX z8?X!@0G2CoBSKgn9GJ`;r@;3RPATw5gvTpz9m16gyo7KS;BLfo~)H8Gzv)2Rx|2 zB?x~3cnXjK{9XZQOY|Rt{tHVKz}kQTd(U`gFaluZdj&8L!0L{{LIC5L!4|-Nz`KA+ zzYLm9}m z2z@e;3lTO0S`h!62>WDUcA|)KGhpp0LXH?P9qg`^fwhO*AOrag-Z8BZhORpgE&U>S zhf>-~$LSP3gMNeFNS~u03ys1e;YQ&Jl~Lta%~x$yeNXj_>Rok_x=Ve!`Zo1niX259 zMfVlGRCKu5UEEr{xcDo@w-mooB9<&J*;VrMk~d0AN*rYO3m_s$ErIs=B1=+g0yqf|}KuYczkaj#YoB`Zv}4Ybt9N)_kGnu9}av zTJ3i2ecC6rhqV8wRoCikQ?-+|m)8EK_Ql#abZVVj7uB`sdUa#ERl04uvve2guGC$v z`+@Er-GjPUb#Lj5^mY2UzFU8;{xSXY`q%Y;HBF{!eCsx4Vc zU(Q`d>70~0lTkPJyw!8s*=N%wX9-sv+0?Ro{rX3yPCYeu@qvT61by-#^tcLi9l~Xx zswG5MlJrNZ-=m=_T~g=qdrBU!d!(*btWj5sFYTM!x3uHkPP%pN+U(}$=FPcf!evKJ zehgx(Vq=2f1r;5%cs(mwGT{^q`r;CUlN$6I!J|qhGU=4Bf#QvPv+P%iiB?x*tZlBh zXGQj`RSV~ij;`A_IkjT(HsP{bUwcF2{AzW@yuSEQ+)PhvNi@fgeAwC3-b^S-NgoO} z;X7<3E^dU&uda+PK6`BbSxaJ#V#e;S?_b^Cv1Y*M_oN~T)C}V(1)j>m73avvIq^?3aO0k< z1M{}cogChdV_3Ls?|0{&F&XK*@XRxJL&dQ4bRW`J@Rl;T3`v6r*Jbqd+>4)lLK}t4 z2A&*zXHbdx2i^v(P34$c9`Dmn5o_N-?j?n5AGr1xa_tn3W;^XkC$(UGMfc`;;mFw5 zZg+F6UK6$SBobpyb&l+Uw5L=5)#t?x)7)!Jj_Qono9Ew9drN=rkgGxAK}h6zVDgsK zdT?DfK^qq?%snMsmV2A(j+{)>xyNNb$Zd!XnSul$784NQ>!c6qSAee}#N_s8os?A} zB0wHBtLPfPx zzkB<*hfhHn?xk}+&7DLizl>o>uJESLsQexXt#;YkvnoxM>Pkc97uU@zRjE^7%ziPYR+S*X>)ris{Lv|Jeq#8f z@HcX|(uLo^P41gYnIp(SmKvQY8KsQbX}XKv9t4^Bi{2Sjs~NSm7bG^O=mcne_x!~A zRPJWT9+U8OXlvckt<6NxpXh+hM}@qw(~*w#bA!RT>pMEu4+n$8>pQ}ONxMBc7*@i{ z_|miI&p&f*-pW*|d7m#NtI$!e#o%+)QdDVaa_)hq?y_vy4(oS}ttorO&|pJ*u=O z^jLpXC3jk;Bs4+^mk8crM~*7`N0HI?h$ge7)1Bwf)xIcYT9`4qG&R+UX5Y}d&O9TX z>xO*$Ord6XNoL8ZLwSA&cP`GBg&Q#96*J!v>(wH-tR@)CXY>@L%2UAS?-G;k?yt_Jr3^*D_w2 zinP>6TH_XvMPCstw+FJ``mUHY;>|c*$%xry(Uk@&>w;OYzc1-PnP833&%k2|6hq_@`zNTy8f$+`pfiXYFH7=N0wKbE7fJS z<^5w9tX)%9U8*kCmaYQ*t1=rhnG@4=UGA#XN%9?f)>nOVeE7@lL|Lm*0UyY`Cv~c% zNmc=!G^xUfC+Ag7s~@~;#nLKMwOV7ST)gB*53X2QWvfwZtd+;p3EIBb)ZlP5nD*u# z%-wmXIq7sJ&36*Y=I-x2IweISLiyz6+%kTFN)YlJq@6T<*xSW4Zww~RD7ll2BoU8B2oQ0%O9ITFHSzg*&g%3t2p zvAWOGZ)+Ti1bSlD9?1^Dpd^YsZwIIUew?q3FKqYtx+Y`sK5NJjbGVuUCZoT}PL1~Fj>Bjkkwkh3rOv|30y~sx za3*wV3~c#8t};+l>^%sG29}?(l|mk&?^JvgK$ct!>g1;envZrkGB@q;xoRzLo!Re5 z^w#S=nw!^ZP4;+qeXUPhRqIVmO-{PImNy&f9W`wY4Q(}!dY7j;U`)gpYFsr|^YDJH zJ1*8WnbZ}2M_sf^t?vy7x+3P1qE2n9&fnQ!E-S6D=}pdTySqJVqj%Og8*G`@){L#e zS(Cd!YxC;dR#lNMWbj9s?6Dc+^IR&}C?U%^>seaXGQ}m@@o|-BBsn@b9*+B3>LJK$ zU9pu@xhH6_zui}#yOyK&9RN>xYf8tgDSwG!e1Ynzu@!zskMxx0BA{wIF>+UO);s)xOcl@SO25hQIM}EZa*D40vLV;ZQPPvBSA*S^Xl&w-EBs^SV{? zC~P67+gK+$U4-6#x@z`?!gQ^K7nHOiC`Tqb7R*YP7jyRiDRcoxG72=XI%DWXhCjxg>p&*A}!~Q97%^TnR&m z(r>enO*ULiYdLzJ+A$nbR9%-#DD8QwK+XN`HmGe`)j1r|BcrrkRTl^DTec zr5PG2??3lkSE$NaS)-3tnnP_~TGdf>!3Dj!4);ietP@liV9POy24no zV!^G@EQh>99?y`M>T_14gUu`4gLMCqy>-p`3x`TICF;_evf;6jGA(Q@P3hpgFRdLY zt1bh!ybtvM>cOzu>!ud@uE&ErD=qS1Zqe__eTF64Q*mrMc$o zOS>z~RjlBxi@tvK(!naLMqOpD?8zP6s1NG#xAFatPBDfJh6d9qtOleQuL0P)GcwXi zXBnRw)iSNUvZhpD7D`uF{AzMdg#|UEFJC-%Z9_{lv}pRm>CV5td5e`>4-#VX_%hc8_s>DS6)jO9I7>f5B-e5>i!GX z<;dsY-Ar*JumGKN|lAEyOdf<@kS{g=gH!_(L*Y`V3U>=k&{E`s7?re-u2G z7vSHJ@zT4%n^cUx9RIHh{w?5bDn?(%A5!SBnP5c4YMa$s33-zaaQb}i&FRBm!CQ0W zbMbG`LOjb?j{nzLct&5wzc~xf$|K_sF+6O9g!G!QQTQSHiI>EfjqNY-XPJq`bhIgJ z!YrB39Q8&Mg$<$+6f4S4jdcEo!LH~)9iJp`80v`ji*EPGeTex4=;HWbQ9P)YDIoOrA0CyL-7r^$DfB&phiZkP2}wA#l5$8LiX={;~TWQK}|*3%SXG9FhAeRXeimIU;xb;uH#@W z=BGpr)R4{-T{f{Rv#is@oF}_BEt*(3xkzRB%6X1|oUoXpS5tV3qV$Wu_vsO4E`Hpxxr-*havWKXHd=L`%vT<(>b z%s{ncK_b#0GpllsP)i_F=V`Jz#gRn&xIMAX>>hKKmeZC6NmJwdhg+MHbB>yR>r?2%p3NFCEUWn&qk>ekjg=h3-{J~jx#=nezi{VkasPrbR>?7C};bp7Uvo)J> zMzyK*CLPyoCO$v(tBkaIep_RG#^PXBw{OUi@XGf;H~q1`sV?m^URIa(8_du7D;wJ! z-Qr}1&GIdlcHA${FbkXty-}(P*c$uage@NIjpaV`^AdfiazUyCSPe%z%*@2)Ny_I4 zbMcIOLtbJ~#2JRb{5FrbZ7ke0WwkHOL zIF<14pLR4Q=T1);I@+4MkCNi9=F^UuKJ0@Wvvx%Bh{qidM@3)b=)7E|pqe_x6i7RL>2T0$7A;n9CLm^DDMRkKWy|F#uE>|%zmCSg zuJk*O=kg`TKQIf={Of2J0MRFU}+9aGZ*m2+T?F38AOQMUR>gs=o2d32S|RMrgNA z95W;2ej#B6{6YbY>5vwjvwTCva1I^gDxzmTKHk$aJYtU3YMmZ$;PF|Gqug=KdDJzs zq`b7FDjDyX1gjc~D?Z9FV(>Xc}{T#^_Iu1tWq#Xut%%V3L15NIB_+`^J zadFHUs~*)i`Q05hqh}=GJ8qp;V+_{SI$ZVPl)J+bU+VG1^qyFyE#4b&WuksZrZfc9&y#yx*~Ra)K%MGdFyr8?cICb zb+`7^b*~#3Slj7zcCH<`=xioa^KrRXIE#DJn5#I=>ITN&{L6QQyRDtO`{*CjrKXxA zkM^(@HVF(PJJQ8SY5A@k%fn}XbPw@92-)wEN+}}8~ zW6gv=I}j0L;q>~+$nsSuwhC&tc5DTI4}dP#pZLn!^k5)(($hXyIUhEvF^3XgfI8&s zOa*H~j?w0pxrX?>=45|EZEG^n>j>8`Z4M12?OiEH!e?+bk5pD$#M+EA+L^J(+_jyx zV%QSPcpWKE#29Szx6IY6OKic6E7TXWpuSP*^f}Z@IrDE|AtOy$op=oOOqpaMxFs~6 z`!m(9SiCs*x5re1y3(q-BSZJ(cJ$ow!Tr`jt0~OAE*9|h5a{>{`O1%OC4L0o`LWg%bp(epb>6no%4&0+HUqRTRZ4-cQn`zn~9uH$9s}vi66dDFUGCz|@kP3h1qH{;?Hh?z49apGHQrqQTW* z@?`As9)GAOX3<*esttiUoij5+MNdmQ(qay#HBJ5Yc&FQ!G}I?5t+6g&UAn)RU4mPlv4B^nSb)RlGqgy`*vTImKymnYuc6mtYcOYXNFiMp`Mrm^;iZDCg}Yk>fG z_yu^VVl5!+6L~N;!tE`)!J!Yi_A6XKeoGvzD;;V#1yR$^TY`fo^!d?<3pT?u|mNai+!Nv6wxc zN{`Lq@i=TA)><)X5qT7GA^RqO2lW?o*D70OL5J(rH^ix`#O(1}#QK3B#C4qk>ag4D zQjzYJu$g#1^iP5xd$-io*4t4bObAetG8d21)2F6#=RGscj6f!(A@T$)W1ilGjS)JN zsv!M(p`y7$2rB9Co5E(6^QMF_s|iMgwV@Afc$)A7d3`eL>ws0t#B4^_sZE6?y0%#B z^t(-saaXG;CQfEYmYY3(SFPG@al?}Lcpmk4rlXOlEzn$NYw*S&iX)eVZYe8K6;q|82_s#uTZz+0o?wk1x#r8z{c7AxAD;&%YIlZVjO zEHz{;JxkUWnSAxCB7^8OIow%#yU)_xK&@u0GZt=Jj1nPdx)C}1*#1S>&tGFD0vFx_I@b22xb5+Mx&hK1}7#YNPEgvK6&zcNNJ-c>!zS3jA`a906IzSyX=&6X|WBVdO z`MjEJ$7zJ}$ruPXdqh-Bd;HqyGiIS)Z&%%mBHRmeOw=eR#jwp5VfPW6Ei9s;n78^%^q_P>?52H?*U5S;8q+#kuJ9q9;t%w~F;KO2jv^J2Zl^EQb zNownM?6_-BOvuGPyOG6kD>NEGLtZ-Kn~)SM1EV|a7dG?MGp#3Y{9_NmzTVoRQmIOH z=+AClX<18a#1^y_+eOh{jGH}8qqfFq)KYCTYEl}5U6Wjr9c_w*8lwx7jma`~St_1f z7;Oy2a0OqkxdkF30lL>utQVk zO;}v|QWQ<&2s`)4ImT1S5&7~QtDH%Hc1h9^qbZHiR&9w!8*ToivkE0CmsZjR!lS%J zX_A)HiniQG*Q!qV?AxraR^T^bR|@a&x3J?^w0x>M_?el#(IDMIIb9LbVYTF=R$3t^ z6bjOzrF2NC;;CC&sE0nDOCR|Q{e6zD|FmFt?*_~mVIS!HtS@DgY$9ta@n0BdUR8ZU zS!3Dy>QzntL3*QODiF17+GvgjrW}iyevU}LfF*h>yx#EV>DU~C2@xOsrw3VP4M1-* zdp^HL$ahz=)qChvX7#X2-5F>ftaH=_+He(5%`B-)SXu&sNU(jVJs9^@Yjyr6UwqUN zFvC2o4|WW81Yq(mhS9sUOOBP53g-j!fszr!d{o`^@du_9(~Z7?d{Hpaii1T zQ4w2w#^}iDi=xp*r;m)Du{ahAjc)Ae-Z&Brj%@7i**F@SvL)xl8U_+pm)Wm347c`- zT67_^3#&0E+DR`He#1FPv)^*)j?zs>^MEZa+$LcwZyx5F=3VAlY#YNCrar&FpN0MY zx@^E?3S{fVjNfGPX96Q)RIiOjJwaUrU@HO;27@{BewYw!h>6!YC^d}EXBaO0lk zVpyu3R5r)a#p&1Qo^yP*cl$RNj+{0bt#2802b+roOP4FzZ%Yh@tpSZtk@Y(lnqz*m zXJA8L?^&x`BV(JpqT_Dk2A_rXYGZ4M z$t*VFa!8giexP+Zc(BP-hZoB%V~cAiSD4bKFPqcm1?=9EHt)8GyK8qp(R@YAy*OH~ zXnx{}Cuq?XY*g#TSccss7}aEN?qd2?atOb)En&a%pkGCd0R1ZMQaOP6iGuOavuP*C zz&hk{LWncQQ~iu#SgB#Jjnd0u>0;tlXzOAFnQXeDqVMZlu%NGZe7x5ekNf=bc;%+G zYc_6NvvyN*{=9jkqx0s?hgMpQ5+0)GvGvF4`S7iiuCP8uQ=wvAb?$Uz$$T5M3;AJP z=JRL5Nkb|!5H$xpmXOwG>J79G8vW_I@6`vpGcltt>@s`Yp{@>lD%~WqF_e|R6ZGJ7 zM(Oi=Wngor^W`s`{>qB$$MLzQhT24(80~7tqO@oXK&!L|EfKfg=X52FzGP*C%Vn$c zy4{{&z-f2e^lpboWAj@)F->Ws-_}qEl_Rh`=@>XJXBsGpt=F>e$ly<=(abO3b>mP= z%gtM{vtfhl$a~QZR}O4mfOe{ftr`;kfR=oa+c!=;&*RU(Kn)7{_gGDGvp&st_%V^s z+t3cG>`TM`K4vXk5Xl_Bfm%J*tlnhl_qSyeC2D=5%HJ^B4${enbhbha8mbzqZ3CST z*Voz_1CynGyA|V+fZu8IyrDxNv&ZU>840+jE*mnNL)p4~7>Y(ip;(Nbi+vV>Kxf!! z40i?s9Sx>rcPi7>l}U9o`ayad^$559d-~tEL_B)ECt}Hmu29GYptsdxHt&S%q1GL9 zI%2L`XrlUPwBCa$q5vsck9}GZtm~zj<;e%E3>y)dL7jK*7PFC2gBtW_xld$f@AN>p zORLjqyTX0(PDhKWFWjxw>$TnCK2wXME4J0#AnJ4?6dQJn=)~~)NVloQ<7qYZL(|*V(O0c>vTSo&fDm8HhOjWkV$(=x}4rE9D;2N%MaeMY5xo#USYM$t~72q z$wRAQUwoP96Gx*>*qg^Jz(%Dpucf@k;&p~b%sIs1sq3%5{^A=J&8v3QsI`vjc?)m6fH4~BfHbQ^`f&30f7GCxE^U$ncgK;bbi&6 z-1-eg^=%8&sqwb@;*-`3Zeyy}DCG7Ew%U}{ty+%?mX>1H|KIT6Vt!EqtMVp#Qd92A zN@4GjB^WvKZ=r7<Xp`(_!}HhDvGZfGeMp1UZX7C>S^e*$(DL@KpG!tHM`( zn_a(sR^*ziBiCFLx%!&OwV>c8E0JdscYJpxqgUvSDD)B_pFf&J(PXNtGbtg<_i-n7 zX<}EUlWxf0fm=6u2xa^O)~uewZ;Xp^y^?cyE^;%lJwy?jt~XRu>>#2~|X6YDB7a80v8oljYIo9A_Y=#insG!sv)>jK_t_0l3wf8Z- z?d&@{9(bVR&a>s3YNK}Op{rR*Y!tuk!q3L4Y1^JTdxp9j)roGr{Zj6%JHGtoJ5UlY zenBecGt4M=ZFf)GAsXqAMQap*tSr?Z?^~?N@|f zgTN!~($b4_-=Mdlg>w><6lK)|@(BY0&*up3bP(SIV7ni{Au!Jab2Z20*QR#}P4oxC z>xh$Im0m4$)1L`X1Cw8mK2sQ`*9o@+!&jm~=R#pAy+XJgn7=8MuMMZHCM?vzuk#~sIFO$goi zP1e(Vx65=}LPO@;QZ;1ri4LvFC}e4s8S^YW)f$y2p&QK@_NcJ#Zs2!nMlBSxFiEvlP)5ca5BU?EWH3}Gqx zGTH<+sDk`{nU)Jn;hw=h=q1MuXjc3&4PTVc20XI0^xj zHVBWCJ*vpRrnH_@u-Wc2+H8!X@Hhy{w@L^~mkS}X1@gknq%9~%p|zZBZA~&@Te1N{ zsHq{;)D&uHs&_f;E|;DC?m)T*?YByG^1r4O%4S0h^mTQ5qthw;v@sZJYzze(y>_eB z&Hy!do#ezXt@$o@3x-b@D|Mw}` zSg{N_Qgs>hg%iC*z8Bz;a4PpI(uH*l8Lx&vf0J@wgfA|9Te&aBH$*hby$0V0X~MT0 zw&HsY+sGR1iV^X&3cnTKj=M47wqj??I(*4tCupt0a{^T3xHe+dvYYh5zc?Rvg%tAX z<Z>2yb^FQEa11RmlS1npd4Ci*_ybUEi8My7B z$V$Bl;Z|VR>JdCUFk=FMR3h zC**JB9V$>2RnsDjk~*wk8lc}y*fVXxEW?KVcv{#D4#@W{@V(rCQTTey`-<=lhI{dS zhP(0ol1K0zg$MDCh#!y|T8wWv{0QIwI3H43fi>a|^oA+25_>3*$JaFu!sB}$xd2~I zxe#81Vl0Z5(lX{mq?NRaYT(tb!S@EPh8wFEyH$UV-u7j3CDoDL1ex=av)W$(~*w#=HB9PK@r@wy|{UmUYqXJ5SzTy5rQX z{HA=zhHdL)T-ga*cW&dzveVaX+ZtWFW$R|1fZwnL>_$nzZsi2*u6PwsS1i+1_wU@c zm1UerG^XVO^vGc{9Ma-0-0y$;t+kW>n} z+=c6@kV=8PjFZt|P>%kwgQ)ukMivt5n$xyzBEI$8)@>w-O{;cnfh?(6KFF2Dow=t4 z_d>zFil{fP+qQ*RkG&$joTnNkV6-%3rRsA16~NYV3TnuE0KK{o7&YY3g#Nx4ao3k_Ux0n=Ms8S5`M*4*zn~Y) zk#3RxA{~+*mk#5(O1k%dk%LQ4Bke~WzXy2se?fytzhJ4P19DpFQRyJgL(&21B^mP{ zTwA4^r58ZsQ2+~Xl71<@g7A-kS8)H9^oM^D?!{Szw?9B^0a{fE7`KlDB6*{j18nXtc z6>n;B)#KDbry3yLMx4xoGC^+4IIB@k3*K09YN2awcyGsPg7k@a1smB(t#TeC&+y>Dztr(dW zpgiL^wHR|JAiI<3t0s&}D?xb`y2nd(vmPeu(h5N<;oX2cY{K31dCN1JYyC^^72-!z6u*UUZm; z?@ON`-_M8|;XkCGBmN7JntyX3^+C}1jMF|Oy~gPtnwqG?$5QPZ{Xou# zmp7kZIq>M)cz@vY%gx`vhwA~<-eGAUqd3E@l2;Ka;`w5h%nnZP5K78&Dd(tTF02Rt zyMv{d{tU>Mb~?eanCVySt71KXR`d;~sfqL?N}{wJ|78wgYu31P@icCX5gqvU8jH!= zleZoZ8?oX!-IhE@rX{8i=|05YC;f?)4>>Sxi!17h$vKx7MAb{XfIY}toR>k7q@PZg z2Sp69ujC%69$od;)d>JWUWw9as)4B0y)+^WnPla+| zRhAvoeAnZS;o=<4FW?9AEWdIosb$5{Vo z+JVV0mt#D?gS`16eT=71q}P!4Gr)9@kl+3vU5}9ul;r~H$I$3Mmi9|`v2RW8A@FNPj~)Ka_qezdN>k=#7kLRu6~%S)5~2{W}b5_t(t7aQMk3_+p!Y7Y zik>6IN6VRg3(2x?;Oa2@n2#?cq?=GAGtP%nK6n0uuM08g{>!_R{Q zef$~e7C9HhXLT!EW{}bUyMs&6G%s8uex|gbGVUQ?SVM(5qLj?uJnCT9Oa4H4nI`3Q znI!P}5Tq{uzA&7o6j3y_V%M?$!QxH#b2(AIwqe)c-Gh*~zwx>`3|++Z_QyEi$D5Ct zhT=yW^~$Wt_ocUSWqJ!53)iP-D5G^)dFA|Ad7lTM$H@d{uKAYb7@yJ}N-V^ORzkXe z%)~FalgkU8rqu4Sx-XCMgR4)azw;7c3}Ydu3(HnMP})~HkFtgOCSoxCF2|bHF4J|( z68aF2>5F%np3C!I$Psi`UZ+mCIb`=R#-aDP#$`GS_8Ftf%O%T2DV~^gegeCk_vk{J zN{J8goTo#YZwW<@CXb^P2x`VP2w81Emz{D|4KPqQ*0-L$=;*pt&Wj<+A-o8-#D`OmldOo=U= z3Y&|~)*Ja`axHy|ww>kxbRR}pFygVAm)_*{ixC9(+&bY&^=NJAbI9(#!ZBi+ESvjd zhX|fUcqtud=am>~)?x0u0)DI0;KO3G|1a>X8nbsc-(tSbD(Jl$%=s&EG9Rh|vt%pM zGcTnF^L9V{$gt`$BgXPQ=Gy!Vi@2}G>|2MEc?z7EeOurGVDo=BX8bC~WctU=u26pCT-WGPs^GMbPGpC$4yEZ7NobwD`1VycKGXD%aH2mbZpK~ck z`<3BjEBx|on|X08s4E8StsAY*fO&D)S)ov2bt*#ucdUibW;UB6v zQi;Hh&1e!H=YM(uHH@hd<`U$gcpj{LVjJKGl=k1l5RR76c-cI`0abd$Sjm+obJSOXhd<%v1>M6aU}VSByl}y{um( z&ff8bA_*)UA7(4S@~R9*HohjrR!ro(BBt9ot{62_zUjpEt4POxbltjU6Y0Z$*_png z{7fq3l^Z5e?8{EQ2-F&Cy8|ckp9bKHh%d3l>gZOo5X}gL;(OGzaNeD2cjU!AiZMpa*97%3jhGA z008{f%hPZT7gJOg1OT96e{8aU$}n@BorvWW=@@^siXTn+2YQ;Y|Jn?#_3Z!v7*GHJ zcm@CfPo`hlS}=5R!Uq807Jh6f{{s*q+?a`-sWkuq|3d*EKlM3+t7ov8>O21U!vAmp zc0R0Kt`&bNl2}14S(zeBY(7`|4>DdJZr7*_S3Gg(~lqie*i%O z_OQ{nHvZ8PfB5W=-4KyKH;SFD7x_S~z|H0JO(5bAXeRi2kpJnAC;Euk3Ls(jL7Fb!xP7nF}8ALH0*(dGG{Gphp~ zIOJSXSW7yq?RwIPpZUJnAFq)Y0iqJ_y6u74g<&{78gSmpJ98J_$rihqU(7ztakjcW zIXgo@ofHqwG@}~91R!kWP?CSri+)Y=I+XUIV}m1_;)~eN$56i|R7kOCWA4$T;MJpH ze2Oo2B7vX{TlK=3RJR8H>*FW=ZoJTjo*lDkcD-csTsyLqYkGgVrvwE&CErPMjO!-y z0QB$xemo|4qfGBTI=imr(VG@@xxTyB+g1px=X!MH%Pf42$1moqUVYmewB8xG6wQ@g zwVseGrU1X*es1)dI2x;dfpm6iL^iC!LG;@i8Cdv6J7SP#;Tx&I*a7hb$lu5WQjDX? z_#DWDs_~-6Q0s?)g@!Zf6*?Gu?DWK#u`eTwQ(8$Gk#3jTMO3A2Y z;^@jGQ5Jtf&lU&*Jdkt2E+3kTQ3yDtIJF1F*gRsT9aslQp7P8 zQ$%r@Qo{73e;q~i3!?Ap*S4q;+9ZcZ81I>IP|;T;`d1*+l^5b$4vcHC-lSob`$Z8$ z_`^FoU>BJlVQ_y(WDi!Dg7-2pGY zo?6yznlG(c@em(Lo9{%=(#MX=aalZP#6Ti&U&QON^FB5wP+)Z(;X(55Y&lnk+f zfa5e7f|=(?vmH=%6?|#(O`rw+aGPYtn|T@}GTBP6{c_+(G>-daZ?zFrtR`Nf?Mq|H z(K!U98mzk;q6wS`gP0kP7CuYswAVDm`NX+ClfttfV6V(B#P|=~RW;h-x)bpf<%B>By>^QiWR>DqZ#oq`UMlcBEUX<~0H2YI1 z7b3stx&$#CPZI-aAI*uz3%FzYrY{8EOQ6dsqvTJXr)vH*XU~rX1g!-}hc>R3tXMq< zW|^B;X6||Ov4&v}A-2s-t5xQ}?&GK&s$FQv=##Xqu!eStAqV_2=!{{o2t!k=vYa5& zR14G9^(|g$Mid<}G)s^sJ2&*9;N{)fmGuhM9ZkRGol0uMP(SF+lk&127M&D}v^(qY zcNKtpAdr#s6(d~d4x7e?a9c%;fy1spo0HrwE+V`no+J~s-};Ne@Y%T^g37TaMT+xj{tr)mOZ|IfP zVT;cMiR&NWGYL-g_EqGgc2~QjEll+%ZnI7aD<<~hYt9JB-mIu%SS$R*sIB6|v`*y; zy{h?}(ZxQOAO=<{zIAs)-!(|4CiRK?LCirO2D;Rn|G~4tW@|D@_LBC2cexDNPo);k zrWG+;RLdO$s-9gnEZ!e;F>07f6{`ZyaGXf_*DdvS`T>2UxpN z#|lgOH@<^M(26Da(9Z%lQtp7c6%B-1J;LU(&ymn=pa%9*TL?byoF;zX zMIfC^b^#BS!@@xPQYQBEWdmdBLb7_OR>m<9&&1DVc#YV5A@Z+IDuG<1e}(C=wo?;? zzVo0cw?6_M=dqepDnxcyDUV0plTfCC_N(DZU=kTteScx5SHUg4gw(XgtQ) zNm(H!%ltU?SjJ%d3X5!u;TMtD(nu*zr=F(2k3ZuCfB(__4Y_D!?TsH)JoTbPH)xv z_Kl&tgC<2INoTV1y-QDq+CVeL#fSF4bwRK8WKW&xqxSM6xG-pF&`(D>Gt5*jht+Q* z+Eg*rkmqR)reNENDWrq6pfp95aG;+o*Y({u6V-Kb72Qec2flIKYi*I+<+(xFQUWBG zj3#m(CgSZVG-EK*(UJYg8rqYyWp*`UEBR8&v@6;CJXF*CQlUI(bB^GV>Ln$lMi?kY z`G4{P$ywUZpemwESVa1~#$VSJT9g&gkD{QqqKrEo{jFmi4v8cqK__3#|D}b zc2ipsyMt*z3{4~+CU!)$qV=hV6>n;wwsR1mcss+yZYxsbOI{mCXg|nWt$QYm;)S?O zkBM026m0{J1{&kP!3&q29$*uqW`ehcNo%z(u1$Y$B_1eQ#-$~Fe$LOmi8DIPZGMkP z&dgJ6^-z95M-T&d1o7F)l-xFDt=7dieS`D$4?}+hSQfgZA6*?Y2Mi+v>l5IRAv|;Z zZk*Y$x!Rrg7S46=;hto<<5sZNA-0$p7p7tAxukXs%ed+OAk?-Te8{G@bx+2aQanie zEa-asCcWqb2Lglw>DjwJvrmCmfXvqtIWWwj>BMxSPuBi5S2L_~=Gio=vOeORt0Xz% zWZf(>u{oU9!f0rW6^dSETn=BYC8Rvs1nvCyLd9@7aZhAS7?RI%NkM5pw_%;#L zIX`F|&?=s2j2FxLae%hI{4hTcZ>nl}NRzTnvCM9DNwtjmzn7}Jx1tXq?uQ(xp9zWE zT2wTNKQI7M1drBy9P=u+Cb}J!IL^+sc)s25hx~{MyyLm* zedtgBXa)(;`Q=eXX78_r@S)yxK{p|5m<5tx#gU!n8G&a}AusCe3!9JvR3>{~tYM;* zbEsWnw8H%`>3ue5+h2#Mn>W zrR}tECVRnlc*3?T$4;L6Q}a06)-v8U&I>HQIG#J`;EWhedMphU3PXsU4IBFj?l>r_ zFAr)Nc`CdlqUt1OcW96PY9GR{TJW35AS_9?eZN*+WyLxsKTA_D;uT)QERIdb(=t`@ ziPI|k+2z%$TL}JTr@9cg<-Ex=nw_*4YT4>;R)vhD?J(1E>U}R^-{s}1;+)lUuhca8 zyr9%1%`&%8MaQDD(q-*DCx2=v&7ed-7)!rELFc!1#w}@zS$rv}rD3G9il%8)-!Mq&BUblTzmb=Eg<^cxR%j*~< zehnPmi=aRbDUA;|zxy?RNMxc%YQ-S6!Jx^=Af{tb^)blp{`Yk+5=p`4i{?x0?Qs2ot^fHouG=H0-l{Dh@FO&ov4sKLhM(-@Lnj{o`3OPpy?k_ zOLM=dj(|$yUfDf;x>~zfQ1)=Fi~*3TKTsIA{^i0wGCuv<;kyLiI}}?t@sw^-uwDg# zt{Wl1Mc!W?<^kf3fCnAWTm0-eA(b@}s zD9Rd`BnN=91KeUszrez{HggWzzZp^vvwu`4{0LR~s#m#kS2s!+z(<6e5Gk2Xd_C!G z=wW^o#f5&QMTdU+a46u0koUfvz(lEh^9p{ivcr1R_o|%m^n548J!<>l&KPxo1HEr3yCIkGaUh4(c_YlTO+Ejz9>;PzgnG*gr)b||g*8EexM1K8Q zTX(P~exC{ty3x(uoymy_CQ{%PQo*G+Jc2HU@b7BKt0N3Xahx5;cJnlJ~J#8d{Opm!%GJG~K zYB-dsrMH;uDeHXlR_o7z;$8_#9LY*$5yNwHr$0n@%Y*h5`=-8~+g|1z8Vs!(8k};4 z#65`U#>{X8BYHPEM3H2{ev0`USV%`h#MODf);KUDlN0nCX31IF2n9{jr&K$X3~ND% z&nypqq674^ZUlB)tMr1FvLou)N<& ze+K85F@qwg8tFtbm#1PRWU9-Rnl(kj+Dl$SJASDjL=ov<9!x0<8bop0n~ z*ix8DmR!4-VG^S2ycO-Z2EU3jjegv4I2iFBSJl<_d_<93ba;s?_Jb_=i}AM|<%B+$ z#~E`CYV7jdj2_7kilr0)0`v>g58q1gGBI?DIaW4ohCz+ga`v#F0y`N_&2Uunpr*oe z#x;AI+QlMj55c$YBcX82w(Mmv1U^Z3Ve>O@jbkIzROhY-1oDOxf*uB7f_@+%(BOvt z(TM@JgCeW|RRHA*G6H@rOGt%Zc(W3~enM~pHAAE|aomwHxmHo{UOQ>AV~nH$8QF+W(J+8c(ewvV9)=EXLIJcjF}!QEFHuNOuF- zawf<9@R__X8?Y60x$nWo#(HdE+c|0jQs8=10e}~DLYgw#CfqQAZx9UzjW)afz6~|` z6P$l#9LU3X%kNg}@WhFm;l9se+lSy3GrX`^(qBGB+LUxa=|#}n;&y0No9#l%bTEDx z54*Fb+rf?+H5q0Un?A*%6`*AU!izC28S)rv*uh+m-Jm!Xq#WFNT-8p*^zTwDr33p* z#=$kq?R}yVW;9M!%lDH8GJ)e(PH)PE*&CgS($O4AOeLCf8(qH9B=C2(#&6PinYu%3 z#*VCj>eA00Ti<^5tEpPCAzz;8m5%MAHr|i!OxI55PXz6q$b%^WBln|w;tLxU~QGdsN-5vH(%iwKC%&C?u$L+r6blXfpb zcUOff4c%9s+mbRQa2@(&t-o!uD-(FXDtV{|(PZs8D06X48?V-sz8Zk4G@90UBhpkL zMS2?1%E(BeXn*TWrw*_3cv{3bxGwnw(U|J^M>ImD2F`@&>A*o}4R$z5|B6_Fy=$<2 zjCnb{aUu)P23r=0RYM|Vhr@um~Uk%hSua0^|#k^;)t{=h7yv%TiW2NEy zD0l33p}4tXavR>Zq#J-~uA;y6fxNL0ysg(5#>~l*01F=E-Pto8`t7~k&koG_TwzoV z(rs+Aa;^YzZ?Yqtasfy6OxS+boe`IL?XMwkk^u&!c$B&`NEc*SWd7we%z zr@Z;Jnu~irZx+3ZN>_Ep!ioQ}{UhJ!rGGq!4TD4{#ZB=tz->A`N6}MCn^)qD?a4NR zZ~yClL`)9g5!6R|LjH$=Rd4!OF@-!T{C-O}3M9P!>B~c_oFoOejmXs=Xc{ETwwuSb zK;9ECN7TAszXlE+Rdld^PLWDnvKC3_ghd0$z^%U(xccGE5qCpTyk0)ucAbDT9G(r{#v`+5CisE$1MCcqm&?v zm>Gyjn~33x(e&9d`*96a4xIPg*qdjrvvJ(7?>1F+8F|>)yrEo+Nf?r|dG*S8f~^}( zZ~i#z)$lK=!&Y3{@{_)@;O!E+wKUBd;5=H0x}E1iwgP^K_2rEWswgM$4MZ};Nn#c= z!`aI*#l<0bvIx_+I6joQ$@0?ivFjrfelTW3ad;h$8eJ1`oNmTZB4`f8K5EI)>fJw1 zoWhJ|>D96ACuS}^nWdBcfd_?{t1`+V7Jn@ea?sEq^w4dCr$pVo$k?)et z3`Wdf9WpcX!<2R|PkrNTB^NNdS^0c1eRkv;9-8vPuPn` zuQKdUq^(0`_7j4@Tv6#(d+B~8wAEqyo8}Czbw6oKt8L_>*MJk5xihqI2mfkUV1rruKRujc#x3kG}`n9TCu0-~ry z%Bw3gC0^xp1mrwBKDtPg1ZZ7m!%f)sAGsX)S03f>aZ+PT6M6w(`5Hmrb-| zr13O2OVx|+2g8Twf#`0dc6+L{o@nKINk?kD=un8J{*X)4{R{P;>JG5bIe)0AfF$U3 zZZ=oWaek-CNf_k38Iw|=c*t9ZiFS+s=+P)K%50DXqAg(EA$ zZ>w+>DKygL(m~`Zd-|T^b71DeKTPh$ILfpF8z*G8_YIZZKMfH?2}74%El}@!6ffAtYUtfY4LCp!Wvw6X`72y_EZQh4A-p$@X9s9`0I8ikv4R{Kd)li>2dLQ$y$MsP9+a^^Dbdx)5;m zxl|<8iDdMGDo9%dSBWnhUi`_k&w%5{$85HP=X;Wf{!FZ>LD4#!UJZ0&!YJmQXOP%n zv{B1BGXluQl3!(es~VV>B|*1cj$l>Hw~s&CT#bT*^o-+-4%b6Q!?K{#A7wsK{gxEn zVpnH}OJANF!d6pC^zzU(_Zd$8xzp?Wx3*3}UL(BuZ3mfacOjr^%ddshDjPW`rMqSB z4lXX_byos;iNc#~e6aZ1Rc~|$zlr3w@x}r)#tT$qn1_zCKN3-Q`neGW!6ulch=ebO zyzTOEpzo#zr8w#sM;6)E8rTV*oBr(g_)9A7+NZIKbO^N1kC|-55#FBAI8#fhpR9_b zXM?$!^GkLZvm|sKO0BjaLeF`@ped38l$_(Dx?sXcze^~J(eB`v`ojsqK=_kxa$rsT zC^7MA_2Na@ea+0AAn;gHH?!i1#BSQDWabk*HJz0|?;h+fwF(4Am67;hHfZwg8v<>_ zqIm64e4PWk%}?0LediGqrsoc{sQ67w`Jf0O_I)6EFaO-d%mkB90EK$0?D$WEF6P0N zl$-dMqQ*fh6ErF?!-g7gu+#v7pR9V;##7GCJmMK3Ws10C3_q@aWo)RU3dXOVHnaB$ z+OV4?!CiA1?eV1c=5QFD(L*?l!@zv~{oHKInOVh%d3J^tkhqFoaZKd_FP%S3`A8kj zM)KC~XyT!M`GcczZb!%%>vWPg7}52-T5w`zpKKD+BzIUme2knbFNY|-LqOsE<#0)WjdO_rW_gWoY4hvo1@&2C24TMlc5A5# zfhlOANZ+}3A~N`mByH3(D?NgpcoYc3C+}#_#lt-WpWTgaqUr5(kv?-Wbfcu1LARq2 z95^P0!N3IOsG(Y3sDbx#&PtuFdjx`0x-vT2&#-D*l75%u6oN(uO-7M+6w1`6%Q0J2 z#ol1f9k?Lh#ApF@LS5pxf{D@1TXaZ}kx@U>+NSwv_Vb$8eaiC55n-X@mv`gSzHZkI zX<*p5$TmbpB>C2_Wvehy=}JtqK19zh2$b=sE+?a@nX<*xHO-5+D&%K>Cff!V2ee9+ z-1K*xM|V0tm{z8;g^$Q+asvEML<{stojUvupnHKph7G5A3 zyZ1^_ui(Z@rI*-lX!eY=$}GV}2?<qS(+&>U{=HcD8YAR_I z&w0`@nDsSzK1ijP2vFA3Qexpf!k_n*!Qzy_AwFB(LaaL%7OOvU5$Ye)h##P;BIKezQ$ z#{E6IB-A%yOlxw=$M%}*eM-hDkx-{~GOPlnm9h93EFI5RjOylGcquPcW7W%1a*i{m z?}WR>=#rt59#TVO#kZ#sim8I>!Tmx6?Uh6%g)C*7Z*lhq9a0%(oUst(`obtL*l!@L zn;K#f$TM&jU>`OF-Y#v%^zN7a80b>^-8-J)a}pi0fPMNK{|Vb2&bs^|(`R1R%>aU;n{dkV}XVL)T^ z>}OSFI66w`e~XoO34@y5t95Q_xck#b=I0RR)w>t!E-f2TTR2H;{IMk%2vLU3zew&1 zrPlzXE!L5hKkICDX|2hnUI^_G9%WsmZch?iS1~A$h^k_rrIJ|Tg1*9wLMs^@R@yY1 zZkud?qvKu7Qt3MI2HcWA=QNDd-?&Xyzw^ua(r=Sk?-|kuxWUUOpxbcss#wrZGGu1<(oPgmakn^OBYv;j^1xp-wf&b2HSLERC) z&&5)gQ0X*Nx{`+-X+;iCIra-F^lQAdO0xVX6e^@G2|**7ScU_XHnAN7j?ts}*H*Pn zL*YYD)wI}FuKt*6>*%I@^8}=AU9$_!BP@@kATOh9cmwv`%mjPUOx*}d@xpXoeixQN z)03}7OV)QXZi-z{Y)9!vB-;o5C-&Tp;dWBMx;z;ronF5xt0>8+nIT#ccR3@U9Ib>k zdwpjCc#6AntUazJH^o>x5@=smARi=@AIqTdpXhl5r( ztH@sw;4dlAzI8xZO1smPH_B?!C&W0#GQaUQrLVJt-`AIVeRF$MeL?JWn2P$cjc!Z< zS4+goFZIw`rFwrPuu=<#$um^oPhT=4t4e8hyUqM!N^i)pcDR&Y=HYG%pna2j1Y#V@ zW9%^;@kC`&`OTfY4M7`aI8zi+f(GDOGQqE_e)bwLWP_78^qC)aJ~tqfhMiG_;$Nmp z6katjN}e%?#rL<_wPqRajCaUNFzA(M4l_dx)IsT64Yx-}BNPmIHE_E+<;7#7eagdW zgQ>4IUkAKFw14gZzhpT1dY`$J*-0XX;^rT1LrMMM}z6?2Yr(J!$|eo2!=e7 zZdPJA{7+Vg1B35Y#S1}`=-7l&Ro79*VRtRHIXg$nDA2O?@C{1`-a+|HR*COI+BSGb zF%sh6+UTPTQc z(e7JJ>4gdIX1nA@7l~bd5#-J%So9WTXFlee&5|U_IUdxk1CCd!W*WZ^I5ZR+R*;!b z>>9p`*@y;6N6C_Wvw=*|R(z5&s>(`RdG}mXY6Qhnja>#Mj(Hc(KKhR(#qlZW_j%H0 zb!&MLf;$n4{{dgO5+)OLyW{9=gOFl70v8cU_Qv5;xMJ%Uhul?7KOa?N!*155JMVit z-?Pi1s}=cZB2#MJO0)b;icnHu0GqRB=OI5M3o5)?I4)WF+=rEeOV$lv;~7aK%ue^e zyKlA@6dADW0mnY%@P!;UK>J9@Xq1*X*2q>|h-xj|&ZlXZlA2 z%b8&)r$s~o4-oe7NNDJ@BlAJA0v)8awaiKouV%XC^oRmi)f|a1GGzG8pkGuKv};(S@>P`W`4?pDWBL zE^Es7fFVU35!kwmx+J`@I$KOIiHIY+oCQPW^_njVe2ysKox_BYsl6C=DS~aW7&3!e zxBz8UjqKM1m*d{JC!gEN?Zw(MCttX36UJscky$GO|M#_umt%%4{Y1mXJy~+JHd0aX zozX>foVOJs`B}Qkb9MfcZcD4j0`8!r;L8fN~oN}VUU`%_yLN)=AE!%;Z`dKb;!FRYs^Kiyk~{#^`7TNQzUsH zw=4t2J5yNVuQA!_g@+82*FU^}9)iQeO2!E|wg3JRrWScwR3@PlST+r=T$c@O^85b> zO8<`2w!|<6`F_rJb?@jW>=*1`B6u|Y3|%`uVa78Ju3a-S;2K*++?sk}U9y2((!5MN zb-)oZy$X?#g@3|{jfWx+N6=_^;U9I)N`3UQs>L*WF{>gv{A4neT!w$S*dC4hLxQ^G z^rT%wx7FT?U02%XzEie+YM6IYL4Jd{Q>TMpgMWOwR8c>ZKyqKq%bxTsZL~ZG_iRB^Cy5lHGTPq#39jSV#ld$ov~M z$^5O`e3K!w`U!~>T@K7})o|l)g1KvsWOP$q!Op|K%fP}+%Wx=|B(25{=90XB(U(=w(d6h2AHIp_2e`kVb9-d_( zwltUFY8v;TSF!4Z4Be^mNbBhdEJY2yh%6&-;AYxqY;eH5+gexd7{~gP$vF9!HMy5> zi`8MA#wYpZK!Wz6AI|yqkwTt?rfjaF7169J$9C~>0!72kXf;d2#bdUPK@al?{qXDQCuSFIV! zF=iCxZC`Oa;Xt--bPyRDsf%B&aohCi3|9Tyi9?s9>7-mkoDM;{Uqw z;MvhO_YBt3S!Ffb`@X{0Y2`!&k8xRlUnpd&$NGo)cM}>V8*x}C&3m|-uoEWz(N}ch z7B=`iB{* zIuWq#h4%~{+vyjMH8q0S{KXpI#@0~Hr7PxMLjc|Ied%vFOw0bgQhU!MF=~|@k1Hq1 z7<0z=GUb}ZemmvrV>iO)=4N#vzj$7Wi|M%-1(~l6xjSvg)`Q(2wPhfsrKY3ijG)K4 zf@xAr9d5LV9Ou`*{`f|P98h&eL-f)YUYZ4l6*-5_%| zLMjanyVzm&W zG_vU_G3wKwELEDs=^eC$@5Uu*F)pIq^V$WFo%Mu;L4k0p-v)b%f=+n{Fb^{4QSjNN zpgZysm}};ZZgxH&_Z|U6T%`JEH*nr|D58aB;k zGRsbPSqwUUozK^IevOP66w#l`s*mfG(jE40t=@bH*y8^aqL%=eZlaqabwgQjyqnTu!4u~QJOnGDvyz;QNX%*0A57LlA^O< zkFV55ZsW=Kn-P>FeFZvyQ;Ei+k=LNdxs>EVJ;o@;6UUa3AC@-4JmO<01iXPPDBUhk zvP9MECZaxgIJD8N|784=%9@a8XH9fT%iztY*{gSxQdCRy3?Ic6YcM;(d^9TilHWp~ zIMqJ=8(aPB--E`n8}AB+D|^CX4ig&EdZULfI~h171qLrA>_}>FRRbbgX5)9offv-M zwOthH2GnRIJ1P*aH+bj7=EF0e?;n|_;0u`fgE*l@Fh&|Fa!MycTaZ_HwE0LKh-3 zbjL80n-gcE{6l$_8)$X!A|Ei^zrPqxIW&o-uTJ^t?OPP%vLV#x#?AQS{+gtQ1**?^ z@A|MPk+mWca&kj}eN3C=m{I`X zB4Zi$>iLr;eGd^Xw&_OCUx&~8mdXDto4pl{0lz(gc>;Z>hqm%?H(?DO17QkmrY)DE zyaO$-ZI1J-E~aVsEiIa99HAKLQ~mUCfxSH`o_*eM{MEdj5Poke(!uL3h%SzU(DvvS z6DiHwIE`ue@MvF~vAXyB@TSLkyf(DRXRTew_Q$KAyS@=nKqLm24=OPpMmxQ4-12+q z|DiOVYqfEYa zoLXRgNd60>T8WZfkU*wh`EC!P2-*9+L*LXDwmpLuNVE)?Rrg4?6021GHx#Inl^V9^ ztGxWY5lUyr4&8oCV8*8Xg+oinsqi*oFPdE+28b-d1E)V#2XGZ2y%1z)R?luy zud1$pS7g;bBxvSq9dPeIK^fi({zT8*LGrNR8HAf+1*XH);M)ppT0zRN?*$xJ(5g0z z6Su>bXKPoKtHhnF;f40bv(20AW|~n|ZIW)U5y$8Cj$tZLgkM;?aIPUUnvgy>&;fuB z(3^Df4_fH%h@MihFCk+3L_^|dn#8<=b6{ERWC2- zWoLvY_3g^YDCIkz%}pLWo`(cYo7Y?Y;a9%4k2}0fxh#arsXV;$>E?xOGECK+D)0vD zFy8bK1>UhNC+x3Vn&yu{?(Pl`)by6>ztV0!bz%DM(DpO)}s! ztu!CLFY>qGH*A$`OC8VX3x%CKZTrFDYe~n(2gmEb(;rq{)ZzV(=8qg04;u}pemW2j zS0V&vaMWeR(GK3i2p@kxL;m!t_&Nl10G;f2@?b_44Fa1?*_xYQp31c4Uzx;^d!*$$ zsxCKhrAu-|*|g{C)wsjHdLN!vIZ>ytB}^Y_HdY2n`^ZsZNf8CfZUDU;DRlgmg?O-P zAQPhFzg-lfqI#*bsC**2)F=ef;n7}?!y<;N)EJVL=Y{8m+$afdWbI^nRQiUT zMc|NIZX%iXBV7C$YzU*lL^I|W-3fHe{xjrwT;l!8V6>8v`ic~{y2GPX4bc}qW1f9p zy`BDo1WAgYj!x|Y@wj3yHEg3*iB~MU&AfmD%}7GwPIcr%%sZ%V0fNq8xzxKChp8NK zeB_hdgBTM*{wVSlv~f{TCGaZ|T@ zu4okipn&wnw7wJ}^U}tHN1n-r4GnumMQqZVorz>WrJiwqwVBzxe5AK=ahBaOZC71H zHZL{{xn_`msGN^h;NwW)pg|#ZB)jY=hxAh6p(3_edTMRdhAFp01zx?TN`BF9VRtiD zD5!rr)_WzC5H@g-YqJC&9PEIr>%)$C?mV(oQqIk-hRozrT|Aei)8XQAmeyIiuw_|P zRIM#NY%q_30H?!^7A33A&F*yTWVM>P9Ty#Qs1;9S)hP1>FT+K{5CWPuzE9be@XpDV zy)EY}R|3hkr-rG4KM!q0C}{$_<-V(pwaIe0d-ZFR>X0Brp{NG7!QGES?nq_lcXBd_ z^#@r66h@Mne@0`X^-VBls%?$-3bg=g!} z7XlFaG;k#@_R@{}j1NWT)o>mpWym&tI3xNub}~s1d+%8T=FTpUL3H5ZC;*+nJFw1N4w7olx9`o@O4&063O@l($t$Atc z9VW*!z52f7#DQd@MECs+Tfg0RB<1Wm*IkWFE4)rv-d(glh#F*O(sCB- zJcxsrhBU|mJXgGR;_a!&MGnW#PmB{zN&XpUg7LBsbF`c3u=ilRYT}3t+swJ5<217m zYECqBFMJMVP4{$XvAOU)%m}rdMwOR8+NKF8VaQJf?5gIOvXIJ#_|bky`U&4q-TH|F zMmk{$_p$7g1Z5e-VXsmP<-DW$A^G&#SfX?hbb>?T!p6-GQra-AiXb4^NZq9#odQ4W ziP~LbV5cYHLKsu!*%M~*xSVeGA`oynlebxzn0R=Y>S6TNULkoRY(aP$q?ZAT z`nW9m@4a9Y`ZPO&6{`jn+5u)0VK;!C3qdI1xrQhfV$SgWhqnQ0vys!wxjJ`E0*+({ zVI$KC)V&a*&iyC5+2?Qn+1@{ExRT=Vt9V!?ZqS3YwUP9Ps%S^ixx6XsovHqfe$u6b zr?U0Nuu0&*dCylKg2H390*e@q%ic!hOkD2l9jC~Oz}xN*Ys_N&K+a=06MQU3s17f4 zJ9ud&Y;=3B|K%f94_`OEfvxVqa~(G1l3=+EduJML4j}f`_q?($K(YE0t2T>kpGwes zpi?LZr2U!1IL!NVQx|kEGIKeP=Q}MdH~p?tv3L|MY3h^C`F2!`aS1*N(^thl+ zVqBz+sf9?L^P1dcw5l%2H9Gixj3aX??HqEr_#G(Qt3%BOBflxSWtKEJx*8=~MB)6439n9=a2ZrP zk3y6%r9Cg78aW(nB6I+;U@u-D<1+#4IR!E!5B~}s56K0 zp|lc|Mpwg?mJ(AKYuGu|KQ_1Y+5x{&0|q!^QAXw55IhOkv*xce1kj@ z@h2t=FEaM~L)S%f72YuKDuFVeaN?0xGXcX3y6N(7@F(kjPI%sZ(^mm)(4Oc+##_Jp zwIvRlr@|>Ve&Hr)w`15sMp^TXW)KAroGPhuXsjxPU16S$!?vSj889p7`Mrio!Ltqq z*~qm};ZOvBhFQ3{m0sTT7Nx{Gd%}eAOD50d7lwgYhaiDN5o#<-<$RjPb@B!|-AK1% zMh{_i`RW6OO7Xl?RFV&^$(>t{eWm^im}KaFvv$gn^*@kTFXv#kvSEr-)GU-x9g4sG z*A`Xz+>tdOs&g^nK6TF80tZ&PLN_GJSk;np)ENL)t9rrM5;e$>{Rd-z_b@~r0&!+= zeF!LuFMdv%M#8b!V1?acL_@u*3oQp-G!AFYgw!7HotIV&A(i!n*hhq<1w zt(K<6jkUSec(XGe*O~0ZIoi{{!HTJwITQ0q>I}SClrZYr&(Ctc!Dq*6@K;cU-;kdb|WkwIV$6GlBLg;$%swK?c?$`rlo`p%{~ZQPc$kB-09 z4NNNHus2ASb0p{$K>CD{QvL6oH&xNzjYMMU{@$M9L9JbS_b@SbKAyc+#};Jl&8<6k zmeKefZJ@39zCG@slS?eX$eky4xZN1tHRVqxJg$2ayfdV^aX{>@c2ysu6Uyc4xt`{^ctf_Uwr-o@Tq9?>t_I1@>+PmzxnxW0 zHwK1Y@Fx-8W)(ij|K&J;H>#=aHpn`^>FtyrQFVR2XMa8H6!UpMlqXg9;r#{~zRiEh zlWFCGIk@`R>EBC&?r}H){}7o9USm5JRaY_Ku>Ww|d+Cl__H8F{pWYnxypq`Rmb=5T zBinK3-AN6}LTZf*3`ICd$y&)>mhg;ntd_gBTzUj5zP`&Fx#z{3*6`mC(1Eyqyo0CX z)wo8&eVhIFx6Rg(;DLN4&BV={>2Q70F9wb}RAv$eg$jfwN-VzRSHthx$&lOpM)!|g z+fA4CW*c4xCj&3i;>pPz8KRRF$Ur(yPQg~S!9iwP*42*#{g2%AB-3FzSOWMgQE3~| zg&@{X%+05~!1fgcTsCNB)x;FNZ+||g{b5So7r{eAHWfcGJ zsC#sdC}X0lcFSRHlmK;W8^kP6^~>OxEst|Ci6sQX4|*SvJq7F&FzUZL&ZZ)k2ch0f zrC=H;aA{2Hu*nwMW?F2b^;=HNM)e`m6wk3ORWY?vPEdJ?VY5rwVT?FrZ>yk2<&i)* zQ0TevR(;h~olw4z4Xxng4L;$}OQ$SOV4DMv`}Q)!ZHm|1AS0WockBULz0SMOjxp6- zr#=L1p?t&MhMT{i&s!xvWUq(-?!f{&y)?UQ4%HANbiWTWwP1CpKf&?44Pxc0J#GaG za<`>x;vU;PD3)W|^qwY{iUWKe6G8Lz^=8*SbtWIX8$WdJCZsq@=q=%GZX=C9nTp!y zs&{2|bh^U0?*S9{YscAQLPuepZ6W6|UCq*2uW~8JPu9l@*$iO12}iO+HhI(7M{P6q zW9=)!9zG!kGHAsW+PT}JCQ?F*Qvt29&ck%+?b2P6o@mY2%GJnpor#gIuxC8B3z60g zS%=v%&qEPUI;bteo>0%3QgqIlp0vMhv#^BmfF;@#OsII(WUIeRwMD$)0QD%v1!Ywx zGR`b0SFz+NZd|HEIMF!~9Zc)1TsDXetOS;z;tF$FDkI=leuK1EyblbM@J3>(mF$*l zz%V>L)NpDwV8Tn&1!RO!CJ|Eeg%l*_d~?9sSG?`(R~U_(LNoB@p5RarRfowll{v-4 z(=tWI{-BQbR5ts`Im`or0+on4krO7xYvVOiocQa@$%Kf{6a7{XxAw)Y4&N4$2a>(-<^4}z0T0ao4pII0#{gh3z5H>mTwMh2 zM*tMa$&Uhe-e(; zF6e@9NWpjOj=bmCLKhu}F3O#p!1GMrk-ogY8=a&J+VM_~Tt_2y3GL(*nh3{o5YDDg z4Rko_nU3sN0sC2h*fEd!o?e%Bt3j|XV6tCDrr!d%stmrxjy2KE5iRV^&XwSs^#<(C zd_pfdF6&$qoxx1xKD$?Bx|4E6nE9(DIH@jh(i54%oDYVJe1tC*kc~P}b81h4C3{}v ziJwTKfYQ{*F+g0=-8cvb1#-QRS;&l{1dgL90cK21;YZ!>KHDOy>?1N@3KtL>zipy+Jw>?z%A&wI_9gJNMj51PikUv1B7R^Y>0z zM7L=g4Waq8hIZ0Pz?w|6=?tBt;WUoAQUT4S2{ekf(01Bs@brJp4bLP1003nGWdO1P z6#-=dp8?wf5CU)ltOCmd{sT$_ZUfE)9t3g(xCJZ)f(7vg8wOnlnFkIBX$PhU-Uw0% z$q5+=j0x`wI|}#K!^AnjQciHXg_y zFCS4Kdmo1%lOLlW(I5aIPavKkv>?DBpkRg~Mt0BH2 z$06(?{~{kEKO$QqcOuUtDkDWBS0i#Gj3cxpB_viP*(F*f|0a7TgC>k7l_s7hrzYMf z0Vh8vnsV#*3D+}B`Uy8s z=Jp9U(qGg0ggcq6ndO8W6^ew2&?^g&r6f9}sB^3u(@(1x8E2SL$1xUIW0Q3bL~mDk z?mxDNKJqPshPQjrIodft)0Dtqm#3XtDC!rrnuU||MJZuR8Kmh=~ug11L^%?m;vTgHZ zyH&Pr+dP@;G{$=Fb;>hOoHo=jn+*5D2v0rt#!IifHqv`rGWo1OK^2Oo|0&mRrO z8e^OZ#+zubNv4==s%d7JZl+m2n{BQ+=2>9Aea=~Jk%bmp;=k+uYK(5tJrW{Os(b|s z6)9GtRGD%Wa%HPj<%9$W)Y&ghqRXzh=#qyXx$TZ)j?0N8=Uwo?O8uqF&|6;v4VGt+ zK7Pxz!YXU6Q7oc~nGYR7G{vL~YbXee{T)T}_Sy5(GgI z1kdWXtQkIj<7}<@`BjgR6*=nR{cvw)JZ^Z1r^)}N8tY9*b+sM8*U8yx9e8A>-+S|aO&9I4)iAkGr z6Ele1&g^2Qr6|I{p}n2O0m@?7&Y0j~qb3FtWb&}lQ30}mx>z~bwKp&*xYlM$xOnei WNC=A9z$m?eA#wv_9{|I05_bSDy4(K% literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_600_italic.ttf b/priv/static/fonts/Source+Sans+Pro_600_italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..130b5f932f6d1857673e22ec1e98734c2d8d97bb GIT binary patch literal 24500 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 literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_600_italic.woff b/priv/static/fonts/Source+Sans+Pro_600_italic.woff new file mode 100644 index 0000000000000000000000000000000000000000..a9fa76c479cb9bea3f41105551ec06b4ec8000d5 GIT binary patch literal 17368 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 M8{b#tDcpqoKd?uStN;K2 literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_600_normal.woff b/priv/static/fonts/Source+Sans+Pro_600_normal.woff new file mode 100644 index 0000000000000000000000000000000000000000..ce91d12bf4fd81c24aa0efd15fe4be542410de61 GIT binary patch literal 18284 zcmZ6SV{j+k)AxU|Z5tcg=5B1;PByk}+qP|PY}>Y-+`0a*o_eP0TW9(+eFi=1nL6zv zD<%d20{l$kRsf{`+UUq1`+wv=>;Ij^MMT8_03hEV#`YsIkYtcPaXDGVAJz&0KuQ4s zSTb=CzL(;P%0d7DH0X~{&d)OJTqj3TSw(uLA6EFolz*hBxtuy{XsvJe!#)52;28h_ zJegr-Yr)Xjkq`iYoA~je`cFV=@E|63rq(~~<;VW<1#$pa&tx~%clhZG|M0^g|I_z3 z0L0YF&E$vu_%J*I06K-iVL{<$#`;D80RMk}|Lrpy99(y<*$)H&1ZaM2f*+AW`+?V+ zSv$J^u%BZ9x�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 literal 0 HcmV?d00001 diff --git a/priv/static/fonts/Source+Sans+Pro_700_normal.ttf b/priv/static/fonts/Source+Sans+Pro_700_normal.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8585df0085a308f6107652fceaeb716852e59ef1 GIT binary patch literal 26472 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 Developer Dashboard - <%# %> - <%# %> + + + - - - - - - - "> + "> -

diff --git a/yarn.lock b/yarn.lock index c9054f0..8cd2c92 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1863,6 +1863,10 @@ good-listener@^1.2.2: dependencies: delegate "^3.1.2" +google-fonts-offline@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/google-fonts-offline/-/google-fonts-offline-0.1.2.tgz#ebd3043ca363b09513671de11d9d62a56fe876d8" + graceful-fs@^4.1.2, graceful-fs@^4.1.3: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" From 1962e535d6a7d043ee9067db2048abd7a4dd301e Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Mon, 9 Oct 2017 22:18:28 +0200 Subject: [PATCH 09/55] removed unused elements from layout --- web/templates/dashboard_layout/app.html.eex | 261 +------------------- web/views/dashboard_layout_view.ex | 5 + web/views/dashboard_view.ex | 4 + 3 files changed, 21 insertions(+), 249 deletions(-) diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index 86d8136..7ec5657 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -11,21 +11,20 @@ - "> - +
- @@ -37,41 +36,6 @@ @@ -192,47 +70,10 @@ @@ -244,12 +85,12 @@

- Page Header - Optional description + <%= @view_module.header(@conn) %> + <%= @view_module.description(@conn) %>

@@ -265,92 +106,14 @@
- Copyright © 2016 Company. All rights reserved. + Found an issue? Submit it!
- - - - - -
- diff --git a/web/views/dashboard_layout_view.ex b/web/views/dashboard_layout_view.ex index a9241c9..0efefe4 100644 --- a/web/views/dashboard_layout_view.ex +++ b/web/views/dashboard_layout_view.ex @@ -2,4 +2,9 @@ defmodule ExDebugToolbar.DashboardLayoutView do @moduledoc false use ExDebugToolbar.Web, :view + + def version do + {:ok, version} = :application.get_key(:ex_debug_toolbar, :vsn) + "v#{version}" + end end diff --git a/web/views/dashboard_view.ex b/web/views/dashboard_view.ex index 1ffcf2a..93c99aa 100644 --- a/web/views/dashboard_view.ex +++ b/web/views/dashboard_view.ex @@ -2,4 +2,8 @@ defmodule ExDebugToolbar.DashboardView do @moduledoc false use ExDebugToolbar.Web, :view + + def header(_), do: "Requests" + + def description(_), do: "Overview of all recorded requests" end From a58b1a5e33e6dc93df6038e993c69c8439563888 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Mon, 9 Oct 2017 22:18:50 +0200 Subject: [PATCH 10/55] added .DS_Store to .gitignore --- .gitignore | 1 + web/templates/dashboard_layout/app.html.eex | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 54e5b7d..f85d136 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ erl_crash.dump /config/prod.secret.exs /tmp /doc +.DS_Store diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index 7ec5657..b543bbc 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -106,10 +106,12 @@
- Found an issue? Submit it! + Found an issue? Submit it!
From 23a001befb77e87d406995b7e3b1c84dd0f66a90 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Tue, 10 Oct 2017 13:09:56 +0200 Subject: [PATCH 11/55] don't track favicon by default --- lib/ex_debug_toolbar/plug/pipeline.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/ex_debug_toolbar/plug/pipeline.ex b/lib/ex_debug_toolbar/plug/pipeline.ex index 28e73a0..64b1c99 100644 --- a/lib/ex_debug_toolbar/plug/pipeline.ex +++ b/lib/ex_debug_toolbar/plug/pipeline.ex @@ -12,6 +12,7 @@ defmodule ExDebugToolbar.Plug.Pipeline do ~r{^/images/}, ~r{^/css/}, ~r{^/js/}, - ~r{^/phoenix/live_reload/} + ~r{^/phoenix/live_reload/}, + ~r{^/favicon.ico$} ] end From f5505ff8b45600395a3e32cf9604aa9a22d4f21e Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Tue, 10 Oct 2017 13:33:48 +0200 Subject: [PATCH 12/55] added counts to info boxes --- priv/static/js/dashboard.js | 3573 ++++++++++++++++++- web/controllers/dashboard_controller.ex | 4 +- web/static/js/dashboard.js | 72 + web/templates/dashboard/show.html.eex | 116 +- web/templates/dashboard_layout/app.html.eex | 4 +- web/views/dashboard_view.ex | 21 + 6 files changed, 3786 insertions(+), 4 deletions(-) diff --git a/priv/static/js/dashboard.js b/priv/static/js/dashboard.js index b500e69..a698b15 100644 --- a/priv/static/js/dashboard.js +++ b/priv/static/js/dashboard.js @@ -2553,6 +2553,3489 @@ if (typeof jQuery === 'undefined') { })(); }); +require.register("chart.js/Chart.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /*! + * Chart.js + * http://chartjs.org/ + * Version: 1.0.2 + * + * Copyright 2015 Nick Downie + * Released under the MIT license + * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md + */ + + +(function(){ + + "use strict"; + + //Declare root variable - window in the browser, global on the server + var root = this, + previous = root.Chart; + + //Occupy the global variable of Chart, and create a simple base class + var Chart = function(context){ + var chart = this; + this.canvas = context.canvas; + + this.ctx = context; + + //Variables global to the chart + var computeDimension = function(element,dimension) + { + if (element['offset'+dimension]) + { + return element['offset'+dimension]; + } + else + { + return document.defaultView.getComputedStyle(element).getPropertyValue(dimension); + } + } + + var width = this.width = computeDimension(context.canvas,'Width'); + var height = this.height = computeDimension(context.canvas,'Height'); + + // Firefox requires this to work correctly + context.canvas.width = width; + context.canvas.height = height; + + var width = this.width = context.canvas.width; + var height = this.height = context.canvas.height; + this.aspectRatio = this.width / this.height; + //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. + helpers.retinaScale(this); + + return this; + }; + //Globally expose the defaults to allow for user updating/changing + Chart.defaults = { + global: { + // Boolean - Whether to animate the chart + animation: true, + + // Number - Number of animation steps + animationSteps: 60, + + // String - Animation easing effect + animationEasing: "easeOutQuart", + + // Boolean - If we should show the scale at all + showScale: true, + + // Boolean - If we want to override with a hard coded scale + scaleOverride: false, + + // ** Required if scaleOverride is true ** + // Number - The number of steps in a hard coded scale + scaleSteps: null, + // Number - The value jump in the hard coded scale + scaleStepWidth: null, + // Number - The scale starting value + scaleStartValue: null, + + // String - Colour of the scale line + scaleLineColor: "rgba(0,0,0,.1)", + + // Number - Pixel width of the scale line + scaleLineWidth: 1, + + // Boolean - Whether to show labels on the scale + scaleShowLabels: true, + + // Interpolated JS string - can access value + scaleLabel: "<%=value%>", + + // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there + scaleIntegersOnly: true, + + // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value + scaleBeginAtZero: false, + + // String - Scale label font declaration for the scale label + scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Scale label font size in pixels + scaleFontSize: 12, + + // String - Scale label font weight style + scaleFontStyle: "normal", + + // String - Scale label font colour + scaleFontColor: "#666", + + // Boolean - whether or not the chart should be responsive and resize when the browser does. + responsive: false, + + // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container + maintainAspectRatio: true, + + // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove + showTooltips: true, + + // Boolean - Determines whether to draw built-in tooltip or call custom tooltip function + customTooltips: false, + + // Array - Array of string names to attach tooltip events + tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"], + + // String - Tooltip background colour + tooltipFillColor: "rgba(0,0,0,0.8)", + + // String - Tooltip label font declaration for the scale label + tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Tooltip label font size in pixels + tooltipFontSize: 14, + + // String - Tooltip font weight style + tooltipFontStyle: "normal", + + // String - Tooltip label font colour + tooltipFontColor: "#fff", + + // String - Tooltip title font declaration for the scale label + tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + + // Number - Tooltip title font size in pixels + tooltipTitleFontSize: 14, + + // String - Tooltip title font weight style + tooltipTitleFontStyle: "bold", + + // String - Tooltip title font colour + tooltipTitleFontColor: "#fff", + + // Number - pixel width of padding around tooltip text + tooltipYPadding: 6, + + // Number - pixel width of padding around tooltip text + tooltipXPadding: 6, + + // Number - Size of the caret on the tooltip + tooltipCaretSize: 8, + + // Number - Pixel radius of the tooltip border + tooltipCornerRadius: 6, + + // Number - Pixel offset from point x to tooltip edge + tooltipXOffset: 10, + + // String - Template string for single tooltips + tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>", + + // String - Template string for single tooltips + multiTooltipTemplate: "<%= value %>", + + // String - Colour behind the legend colour block + multiTooltipKeyBackground: '#fff', + + // Function - Will fire on animation progression. + onAnimationProgress: function(){}, + + // Function - Will fire on animation completion. + onAnimationComplete: function(){} + + } + }; + + //Create a dictionary of chart types, to allow for extension of existing types + Chart.types = {}; + + //Global Chart helpers object for utility methods and classes + var helpers = Chart.helpers = {}; + + //-- Basic js utility methods + var each = helpers.each = function(loopable,callback,self){ + var additionalArgs = Array.prototype.slice.call(arguments, 3); + // Check to see if null or undefined firstly. + if (loopable){ + if (loopable.length === +loopable.length){ + var i; + for (i=0; i= 0; i--) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)){ + return currentItem; + } + } + }, + inherits = helpers.inherits = function(extensions){ + //Basic javascript inheritance based on the model created in Backbone.js + var parent = this; + var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); }; + + var Surrogate = function(){ this.constructor = ChartElement;}; + Surrogate.prototype = parent.prototype; + ChartElement.prototype = new Surrogate(); + + ChartElement.extend = inherits; + + if (extensions) extend(ChartElement.prototype, extensions); + + ChartElement.__super__ = parent.prototype; + + return ChartElement; + }, + noop = helpers.noop = function(){}, + uid = helpers.uid = (function(){ + var id=0; + return function(){ + return "chart-" + id++; + }; + })(), + warn = helpers.warn = function(str){ + //Method for warning of errors + if (window.console && typeof window.console.warn == "function") console.warn(str); + }, + amd = helpers.amd = (typeof define == 'function' && define.amd), + //-- Math methods + isNumber = helpers.isNumber = function(n){ + return !isNaN(parseFloat(n)) && isFinite(n); + }, + max = helpers.max = function(array){ + return Math.max.apply( Math, array ); + }, + min = helpers.min = function(array){ + return Math.min.apply( Math, array ); + }, + cap = helpers.cap = function(valueToCap,maxValue,minValue){ + if(isNumber(maxValue)) { + if( valueToCap > maxValue ) { + return maxValue; + } + } + else if(isNumber(minValue)){ + if ( valueToCap < minValue ){ + return minValue; + } + } + return valueToCap; + }, + getDecimalPlaces = helpers.getDecimalPlaces = function(num){ + if (num%1!==0 && isNumber(num)){ + return num.toString().split(".")[1].length; + } + else { + return 0; + } + }, + toRadians = helpers.radians = function(degrees){ + return degrees * (Math.PI/180); + }, + // Gets the angle from vertical upright to the point about a centre. + getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){ + var distanceFromXCenter = anglePoint.x - centrePoint.x, + distanceFromYCenter = anglePoint.y - centrePoint.y, + radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); + + + var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter); + + //If the segment is in the top left quadrant, we need to add another rotation to the angle + if (distanceFromXCenter < 0 && distanceFromYCenter < 0){ + angle += Math.PI*2; + } + + return { + angle: angle, + distance: radialDistanceFromCenter + }; + }, + aliasPixel = helpers.aliasPixel = function(pixelWidth){ + return (pixelWidth % 2 === 0) ? 0 : 0.5; + }, + splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){ + //Props to Rob Spencer at scaled innovation for his post on splining between points + //http://scaledinnovation.com/analytics/splines/aboutSplines.html + var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)), + d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)), + fa=t*d01/(d01+d12),// scaling factor for triangle Ta + fb=t*d12/(d01+d12); + return { + inner : { + x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x), + y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y) + }, + outer : { + x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x), + y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y) + } + }; + }, + calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){ + return Math.floor(Math.log(val) / Math.LN10); + }, + calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){ + + //Set a minimum step of two - a point at the top of the graph, and a point at the base + var minSteps = 2, + maxSteps = Math.floor(drawingSize/(textSize * 1.5)), + skipFitting = (minSteps >= maxSteps); + + var maxValue = max(valuesArray), + minValue = min(valuesArray); + + // We need some degree of seperation here to calculate the scales if all the values are the same + // Adding/minusing 0.5 will give us a range of 1. + if (maxValue === minValue){ + maxValue += 0.5; + // So we don't end up with a graph with a negative start value if we've said always start from zero + if (minValue >= 0.5 && !startFromZero){ + minValue -= 0.5; + } + else{ + // Make up a whole number above the values + maxValue += 0.5; + } + } + + var valueRange = Math.abs(maxValue - minValue), + rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange), + graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude), + graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude), + graphRange = graphMax - graphMin, + stepValue = Math.pow(10, rangeOrderOfMagnitude), + numberOfSteps = Math.round(graphRange / stepValue); + + //If we have more space on the graph we'll use it to give more definition to the data + while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) { + if(numberOfSteps > maxSteps){ + stepValue *=2; + numberOfSteps = Math.round(graphRange/stepValue); + // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps. + if (numberOfSteps % 1 !== 0){ + skipFitting = true; + } + } + //We can fit in double the amount of scale points on the scale + else{ + //If user has declared ints only, and the step value isn't a decimal + if (integersOnly && rangeOrderOfMagnitude >= 0){ + //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float + if(stepValue/2 % 1 === 0){ + stepValue /=2; + numberOfSteps = Math.round(graphRange/stepValue); + } + //If it would make it a float break out of the loop + else{ + break; + } + } + //If the scale doesn't have to be an int, make the scale more granular anyway. + else{ + stepValue /=2; + numberOfSteps = Math.round(graphRange/stepValue); + } + + } + } + + if (skipFitting){ + numberOfSteps = minSteps; + stepValue = graphRange / numberOfSteps; + } + + return { + steps : numberOfSteps, + stepValue : stepValue, + min : graphMin, + max : graphMin + (numberOfSteps * stepValue) + }; + + }, + /* jshint ignore:start */ + // Blows up jshint errors based on the new Function constructor + //Templating methods + //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ + template = helpers.template = function(templateString, valuesObject){ + + // If templateString is function rather than string-template - call the function for valuesObject + + if(templateString instanceof Function){ + return templateString(valuesObject); + } + + var cache = {}; + function tmpl(str, data){ + // Figure out if we're getting a template, or if we need to + // load the template - and be sure to cache the result. + var fn = !/\W/.test(str) ? + cache[str] = cache[str] : + + // Generate a reusable function that will serve as a template + // generator (and which will be cached). + new Function("obj", + "var p=[],print=function(){p.push.apply(p,arguments);};" + + + // Introduce the data as local variables using with(){} + "with(obj){p.push('" + + + // Convert the template into pure JavaScript + str + .replace(/[\r\t\n]/g, " ") + .split("<%").join("\t") + .replace(/((^|%>)[^\t]*)'/g, "$1\r") + .replace(/\t=(.*?)%>/g, "',$1,'") + .split("\t").join("');") + .split("%>").join("p.push('") + .split("\r").join("\\'") + + "');}return p.join('');" + ); + + // Provide some basic currying to the user + return data ? fn( data ) : fn; + } + return tmpl(templateString,valuesObject); + }, + /* jshint ignore:end */ + generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){ + var labelsArray = new Array(numberOfSteps); + if (labelTemplateString){ + each(labelsArray,function(val,index){ + labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))}); + }); + } + return labelsArray; + }, + //--Animation methods + //Easing functions adapted from Robert Penner's easing equations + //http://www.robertpenner.com/easing/ + easingEffects = helpers.easingEffects = { + linear: function (t) { + return t; + }, + easeInQuad: function (t) { + return t * t; + }, + easeOutQuad: function (t) { + return -1 * t * (t - 2); + }, + easeInOutQuad: function (t) { + if ((t /= 1 / 2) < 1) return 1 / 2 * t * t; + return -1 / 2 * ((--t) * (t - 2) - 1); + }, + easeInCubic: function (t) { + return t * t * t; + }, + easeOutCubic: function (t) { + return 1 * ((t = t / 1 - 1) * t * t + 1); + }, + easeInOutCubic: function (t) { + if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t; + return 1 / 2 * ((t -= 2) * t * t + 2); + }, + easeInQuart: function (t) { + return t * t * t * t; + }, + easeOutQuart: function (t) { + return -1 * ((t = t / 1 - 1) * t * t * t - 1); + }, + easeInOutQuart: function (t) { + if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t; + return -1 / 2 * ((t -= 2) * t * t * t - 2); + }, + easeInQuint: function (t) { + return 1 * (t /= 1) * t * t * t * t; + }, + easeOutQuint: function (t) { + return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); + }, + easeInOutQuint: function (t) { + if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t; + return 1 / 2 * ((t -= 2) * t * t * t * t + 2); + }, + easeInSine: function (t) { + return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; + }, + easeOutSine: function (t) { + return 1 * Math.sin(t / 1 * (Math.PI / 2)); + }, + easeInOutSine: function (t) { + return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); + }, + easeInExpo: function (t) { + return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); + }, + easeOutExpo: function (t) { + return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); + }, + easeInOutExpo: function (t) { + if (t === 0) return 0; + if (t === 1) return 1; + if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1)); + return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); + }, + easeInCirc: function (t) { + if (t >= 1) return t; + return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); + }, + easeOutCirc: function (t) { + return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); + }, + easeInOutCirc: function (t) { + if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1); + return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); + }, + easeInElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) return 0; + if ((t /= 1) == 1) return 1; + if (!p) p = 1 * 0.3; + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else s = p / (2 * Math.PI) * Math.asin(1 / a); + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); + }, + easeOutElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) return 0; + if ((t /= 1) == 1) return 1; + if (!p) p = 1 * 0.3; + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else s = p / (2 * Math.PI) * Math.asin(1 / a); + return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; + }, + easeInOutElastic: function (t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) return 0; + if ((t /= 1 / 2) == 2) return 1; + if (!p) p = 1 * (0.3 * 1.5); + if (a < Math.abs(1)) { + a = 1; + s = p / 4; + } else s = p / (2 * Math.PI) * Math.asin(1 / a); + if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1; + }, + easeInBack: function (t) { + var s = 1.70158; + return 1 * (t /= 1) * t * ((s + 1) * t - s); + }, + easeOutBack: function (t) { + var s = 1.70158; + return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); + }, + easeInOutBack: function (t) { + var s = 1.70158; + if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); + return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); + }, + easeInBounce: function (t) { + return 1 - easingEffects.easeOutBounce(1 - t); + }, + easeOutBounce: function (t) { + if ((t /= 1) < (1 / 2.75)) { + return 1 * (7.5625 * t * t); + } else if (t < (2 / 2.75)) { + return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75); + } else if (t < (2.5 / 2.75)) { + return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375); + } else { + return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375); + } + }, + easeInOutBounce: function (t) { + if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5; + return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5; + } + }, + //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ + requestAnimFrame = helpers.requestAnimFrame = (function(){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback) { + return window.setTimeout(callback, 1000 / 60); + }; + })(), + cancelAnimFrame = helpers.cancelAnimFrame = (function(){ + return window.cancelAnimationFrame || + window.webkitCancelAnimationFrame || + window.mozCancelAnimationFrame || + window.oCancelAnimationFrame || + window.msCancelAnimationFrame || + function(callback) { + return window.clearTimeout(callback, 1000 / 60); + }; + })(), + animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){ + + var currentStep = 0, + easingFunction = easingEffects[easingString] || easingEffects.linear; + + var animationFrame = function(){ + currentStep++; + var stepDecimal = currentStep/totalSteps; + var easeDecimal = easingFunction(stepDecimal); + + callback.call(chartInstance,easeDecimal,stepDecimal, currentStep); + onProgress.call(chartInstance,easeDecimal,stepDecimal); + if (currentStep < totalSteps){ + chartInstance.animationFrame = requestAnimFrame(animationFrame); + } else{ + onComplete.apply(chartInstance); + } + }; + requestAnimFrame(animationFrame); + }, + //-- DOM methods + getRelativePosition = helpers.getRelativePosition = function(evt){ + var mouseX, mouseY; + var e = evt.originalEvent || evt, + canvas = evt.currentTarget || evt.srcElement, + boundingRect = canvas.getBoundingClientRect(); + + if (e.touches){ + mouseX = e.touches[0].clientX - boundingRect.left; + mouseY = e.touches[0].clientY - boundingRect.top; + + } + else{ + mouseX = e.clientX - boundingRect.left; + mouseY = e.clientY - boundingRect.top; + } + + return { + x : mouseX, + y : mouseY + }; + + }, + addEvent = helpers.addEvent = function(node,eventType,method){ + if (node.addEventListener){ + node.addEventListener(eventType,method); + } else if (node.attachEvent){ + node.attachEvent("on"+eventType, method); + } else { + node["on"+eventType] = method; + } + }, + removeEvent = helpers.removeEvent = function(node, eventType, handler){ + if (node.removeEventListener){ + node.removeEventListener(eventType, handler, false); + } else if (node.detachEvent){ + node.detachEvent("on"+eventType,handler); + } else{ + node["on" + eventType] = noop; + } + }, + bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){ + // Create the events object if it's not already present + if (!chartInstance.events) chartInstance.events = {}; + + each(arrayOfEvents,function(eventName){ + chartInstance.events[eventName] = function(){ + handler.apply(chartInstance, arguments); + }; + addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]); + }); + }, + unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) { + each(arrayOfEvents, function(handler,eventName){ + removeEvent(chartInstance.chart.canvas, eventName, handler); + }); + }, + getMaximumWidth = helpers.getMaximumWidth = function(domNode){ + var container = domNode.parentNode; + // TODO = check cross browser stuff with this. + return container.clientWidth; + }, + getMaximumHeight = helpers.getMaximumHeight = function(domNode){ + var container = domNode.parentNode; + // TODO = check cross browser stuff with this. + return container.clientHeight; + }, + getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support + retinaScale = helpers.retinaScale = function(chart){ + var ctx = chart.ctx, + width = chart.canvas.width, + height = chart.canvas.height; + + if (window.devicePixelRatio) { + ctx.canvas.style.width = width + "px"; + ctx.canvas.style.height = height + "px"; + ctx.canvas.height = height * window.devicePixelRatio; + ctx.canvas.width = width * window.devicePixelRatio; + ctx.scale(window.devicePixelRatio, window.devicePixelRatio); + } + }, + //-- Canvas methods + clear = helpers.clear = function(chart){ + chart.ctx.clearRect(0,0,chart.width,chart.height); + }, + fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){ + return fontStyle + " " + pixelSize+"px " + fontFamily; + }, + longestText = helpers.longestText = function(ctx,font,arrayOfStrings){ + ctx.font = font; + var longest = 0; + each(arrayOfStrings,function(string){ + var textWidth = ctx.measureText(string).width; + longest = (textWidth > longest) ? textWidth : longest; + }); + return longest; + }, + drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){ + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); + }; + + + //Store a reference to each instance - allowing us to globally resize chart instances on window resize. + //Destroy method on the chart will remove the instance of the chart from this reference. + Chart.instances = {}; + + Chart.Type = function(data,options,chart){ + this.options = options; + this.chart = chart; + this.id = uid(); + //Add the chart instance to the global namespace + Chart.instances[this.id] = this; + + // Initialize is always called when a chart type is created + // By default it is a no op, but it should be extended + if (options.responsive){ + this.resize(); + } + this.initialize.call(this,data); + }; + + //Core methods that'll be a part of every chart type + extend(Chart.Type.prototype,{ + initialize : function(){return this;}, + clear : function(){ + clear(this.chart); + return this; + }, + stop : function(){ + // Stops any current animation loop occuring + cancelAnimFrame(this.animationFrame); + return this; + }, + resize : function(callback){ + this.stop(); + var canvas = this.chart.canvas, + newWidth = getMaximumWidth(this.chart.canvas), + newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas); + + canvas.width = this.chart.width = newWidth; + canvas.height = this.chart.height = newHeight; + + retinaScale(this.chart); + + if (typeof callback === "function"){ + callback.apply(this, Array.prototype.slice.call(arguments, 1)); + } + return this; + }, + reflow : noop, + render : function(reflow){ + if (reflow){ + this.reflow(); + } + if (this.options.animation && !reflow){ + helpers.animationLoop( + this.draw, + this.options.animationSteps, + this.options.animationEasing, + this.options.onAnimationProgress, + this.options.onAnimationComplete, + this + ); + } + else{ + this.draw(); + this.options.onAnimationComplete.call(this); + } + return this; + }, + generateLegend : function(){ + return template(this.options.legendTemplate,this); + }, + destroy : function(){ + this.clear(); + unbindEvents(this, this.events); + var canvas = this.chart.canvas; + + // Reset canvas height/width attributes starts a fresh with the canvas context + canvas.width = this.chart.width; + canvas.height = this.chart.height; + + // < IE9 doesn't support removeProperty + if (canvas.style.removeProperty) { + canvas.style.removeProperty('width'); + canvas.style.removeProperty('height'); + } else { + canvas.style.removeAttribute('width'); + canvas.style.removeAttribute('height'); + } + + delete Chart.instances[this.id]; + }, + showTooltip : function(ChartElements, forceRedraw){ + // Only redraw the chart if we've actually changed what we're hovering on. + if (typeof this.activeElements === 'undefined') this.activeElements = []; + + var isChanged = (function(Elements){ + var changed = false; + + if (Elements.length !== this.activeElements.length){ + changed = true; + return changed; + } + + each(Elements, function(element, index){ + if (element !== this.activeElements[index]){ + changed = true; + } + }, this); + return changed; + }).call(this, ChartElements); + + if (!isChanged && !forceRedraw){ + return; + } + else{ + this.activeElements = ChartElements; + } + this.draw(); + if(this.options.customTooltips){ + this.options.customTooltips(false); + } + if (ChartElements.length > 0){ + // If we have multiple datasets, show a MultiTooltip for all of the data points at that index + if (this.datasets && this.datasets.length > 1) { + var dataArray, + dataIndex; + + for (var i = this.datasets.length - 1; i >= 0; i--) { + dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments; + dataIndex = indexOf(dataArray, ChartElements[0]); + if (dataIndex !== -1){ + break; + } + } + var tooltipLabels = [], + tooltipColors = [], + medianPosition = (function(index) { + + // Get all the points at that particular index + var Elements = [], + dataCollection, + xPositions = [], + yPositions = [], + xMax, + yMax, + xMin, + yMin; + helpers.each(this.datasets, function(dataset){ + dataCollection = dataset.points || dataset.bars || dataset.segments; + if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ + Elements.push(dataCollection[dataIndex]); + } + }); + + helpers.each(Elements, function(element) { + xPositions.push(element.x); + yPositions.push(element.y); + + + //Include any colour information about the element + tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element)); + tooltipColors.push({ + fill: element._saved.fillColor || element.fillColor, + stroke: element._saved.strokeColor || element.strokeColor + }); + + }, this); + + yMin = min(yPositions); + yMax = max(yPositions); + + xMin = min(xPositions); + xMax = max(xPositions); + + return { + x: (xMin > this.chart.width/2) ? xMin : xMax, + y: (yMin + yMax)/2 + }; + }).call(this, dataIndex); + + new Chart.MultiTooltip({ + x: medianPosition.x, + y: medianPosition.y, + xPadding: this.options.tooltipXPadding, + yPadding: this.options.tooltipYPadding, + xOffset: this.options.tooltipXOffset, + fillColor: this.options.tooltipFillColor, + textColor: this.options.tooltipFontColor, + fontFamily: this.options.tooltipFontFamily, + fontStyle: this.options.tooltipFontStyle, + fontSize: this.options.tooltipFontSize, + titleTextColor: this.options.tooltipTitleFontColor, + titleFontFamily: this.options.tooltipTitleFontFamily, + titleFontStyle: this.options.tooltipTitleFontStyle, + titleFontSize: this.options.tooltipTitleFontSize, + cornerRadius: this.options.tooltipCornerRadius, + labels: tooltipLabels, + legendColors: tooltipColors, + legendColorBackground : this.options.multiTooltipKeyBackground, + title: ChartElements[0].label, + chart: this.chart, + ctx: this.chart.ctx, + custom: this.options.customTooltips + }).draw(); + + } else { + each(ChartElements, function(Element) { + var tooltipPosition = Element.tooltipPosition(); + new Chart.Tooltip({ + x: Math.round(tooltipPosition.x), + y: Math.round(tooltipPosition.y), + xPadding: this.options.tooltipXPadding, + yPadding: this.options.tooltipYPadding, + fillColor: this.options.tooltipFillColor, + textColor: this.options.tooltipFontColor, + fontFamily: this.options.tooltipFontFamily, + fontStyle: this.options.tooltipFontStyle, + fontSize: this.options.tooltipFontSize, + caretHeight: this.options.tooltipCaretSize, + cornerRadius: this.options.tooltipCornerRadius, + text: template(this.options.tooltipTemplate, Element), + chart: this.chart, + custom: this.options.customTooltips + }).draw(); + }, this); + } + } + return this; + }, + toBase64Image : function(){ + return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments); + } + }); + + Chart.Type.extend = function(extensions){ + + var parent = this; + + var ChartType = function(){ + return parent.apply(this,arguments); + }; + + //Copy the prototype object of the this class + ChartType.prototype = clone(parent.prototype); + //Now overwrite some of the properties in the base class with the new extensions + extend(ChartType.prototype, extensions); + + ChartType.extend = Chart.Type.extend; + + if (extensions.name || parent.prototype.name){ + + var chartName = extensions.name || parent.prototype.name; + //Assign any potential default values of the new chart type + + //If none are defined, we'll use a clone of the chart type this is being extended from. + //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart + //doesn't define some defaults of their own. + + var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {}; + + Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults); + + Chart.types[chartName] = ChartType; + + //Register this new chart type in the Chart prototype + Chart.prototype[chartName] = function(data,options){ + var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {}); + return new ChartType(data,config,this); + }; + } else{ + warn("Name not provided for this chart, so it hasn't been registered"); + } + return parent; + }; + + Chart.Element = function(configuration){ + extend(this,configuration); + this.initialize.apply(this,arguments); + this.save(); + }; + extend(Chart.Element.prototype,{ + initialize : function(){}, + restore : function(props){ + if (!props){ + extend(this,this._saved); + } else { + each(props,function(key){ + this[key] = this._saved[key]; + },this); + } + return this; + }, + save : function(){ + this._saved = clone(this); + delete this._saved._saved; + return this; + }, + update : function(newProps){ + each(newProps,function(value,key){ + this._saved[key] = this[key]; + this[key] = value; + },this); + return this; + }, + transition : function(props,ease){ + each(props,function(value,key){ + this[key] = ((value - this._saved[key]) * ease) + this._saved[key]; + },this); + return this; + }, + tooltipPosition : function(){ + return { + x : this.x, + y : this.y + }; + }, + hasValue: function(){ + return isNumber(this.value); + } + }); + + Chart.Element.extend = inherits; + + + Chart.Point = Chart.Element.extend({ + display: true, + inRange: function(chartX,chartY){ + var hitDetectionRange = this.hitDetectionRadius + this.radius; + return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2)); + }, + draw : function(){ + if (this.display){ + var ctx = this.ctx; + ctx.beginPath(); + + ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); + ctx.closePath(); + + ctx.strokeStyle = this.strokeColor; + ctx.lineWidth = this.strokeWidth; + + ctx.fillStyle = this.fillColor; + + ctx.fill(); + ctx.stroke(); + } + + + //Quick debug for bezier curve splining + //Highlights control points and the line between them. + //Handy for dev - stripped in the min version. + + // ctx.save(); + // ctx.fillStyle = "black"; + // ctx.strokeStyle = "black" + // ctx.beginPath(); + // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2); + // ctx.fill(); + + // ctx.beginPath(); + // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2); + // ctx.fill(); + + // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y); + // ctx.lineTo(this.x, this.y); + // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y); + // ctx.stroke(); + + // ctx.restore(); + + + + } + }); + + Chart.Arc = Chart.Element.extend({ + inRange : function(chartX,chartY){ + + var pointRelativePosition = helpers.getAngleFromPoint(this, { + x: chartX, + y: chartY + }); + + //Check if within the range of the open/close angle + var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle), + withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius); + + return (betweenAngles && withinRadius); + //Ensure within the outside of the arc centre, but inside arc outer + }, + tooltipPosition : function(){ + var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2), + rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius; + return { + x : this.x + (Math.cos(centreAngle) * rangeFromCentre), + y : this.y + (Math.sin(centreAngle) * rangeFromCentre) + }; + }, + draw : function(animationPercent){ + + var easingDecimal = animationPercent || 1; + + var ctx = this.ctx; + + ctx.beginPath(); + + ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle); + + ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true); + + ctx.closePath(); + ctx.strokeStyle = this.strokeColor; + ctx.lineWidth = this.strokeWidth; + + ctx.fillStyle = this.fillColor; + + ctx.fill(); + ctx.lineJoin = 'bevel'; + + if (this.showStroke){ + ctx.stroke(); + } + } + }); + + Chart.Rectangle = Chart.Element.extend({ + draw : function(){ + var ctx = this.ctx, + halfWidth = this.width/2, + leftX = this.x - halfWidth, + rightX = this.x + halfWidth, + top = this.base - (this.base - this.y), + halfStroke = this.strokeWidth / 2; + + // Canvas doesn't allow us to stroke inside the width so we can + // adjust the sizes to fit if we're setting a stroke on the line + if (this.showStroke){ + leftX += halfStroke; + rightX -= halfStroke; + top += halfStroke; + } + + ctx.beginPath(); + + ctx.fillStyle = this.fillColor; + ctx.strokeStyle = this.strokeColor; + ctx.lineWidth = this.strokeWidth; + + // It'd be nice to keep this class totally generic to any rectangle + // and simply specify which border to miss out. + ctx.moveTo(leftX, this.base); + ctx.lineTo(leftX, top); + ctx.lineTo(rightX, top); + ctx.lineTo(rightX, this.base); + ctx.fill(); + if (this.showStroke){ + ctx.stroke(); + } + }, + height : function(){ + return this.base - this.y; + }, + inRange : function(chartX,chartY){ + return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base); + } + }); + + Chart.Tooltip = Chart.Element.extend({ + draw : function(){ + + var ctx = this.chart.ctx; + + ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily); + + this.xAlign = "center"; + this.yAlign = "above"; + + //Distance between the actual element.y position and the start of the tooltip caret + var caretPadding = this.caretPadding = 2; + + var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding, + tooltipRectHeight = this.fontSize + 2*this.yPadding, + tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding; + + if (this.x + tooltipWidth/2 >this.chart.width){ + this.xAlign = "left"; + } else if (this.x - tooltipWidth/2 < 0){ + this.xAlign = "right"; + } + + if (this.y - tooltipHeight < 0){ + this.yAlign = "below"; + } + + + var tooltipX = this.x - tooltipWidth/2, + tooltipY = this.y - tooltipHeight; + + ctx.fillStyle = this.fillColor; + + // Custom Tooltips + if(this.custom){ + this.custom(this); + } + else{ + switch(this.yAlign) + { + case "above": + //Draw a caret above the x/y + ctx.beginPath(); + ctx.moveTo(this.x,this.y - caretPadding); + ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight)); + ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight)); + ctx.closePath(); + ctx.fill(); + break; + case "below": + tooltipY = this.y + caretPadding + this.caretHeight; + //Draw a caret below the x/y + ctx.beginPath(); + ctx.moveTo(this.x, this.y + caretPadding); + ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight); + ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight); + ctx.closePath(); + ctx.fill(); + break; + } + + switch(this.xAlign) + { + case "left": + tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight); + break; + case "right": + tooltipX = this.x - (this.cornerRadius + this.caretHeight); + break; + } + + drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius); + + ctx.fill(); + + ctx.fillStyle = this.textColor; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2); + } + } + }); + + Chart.MultiTooltip = Chart.Element.extend({ + initialize : function(){ + this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily); + + this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily); + + this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5; + + this.ctx.font = this.titleFont; + + var titleWidth = this.ctx.measureText(this.title).width, + //Label has a legend square as well so account for this. + labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3, + longestTextWidth = max([labelWidth,titleWidth]); + + this.width = longestTextWidth + (this.xPadding*2); + + + var halfHeight = this.height/2; + + //Check to ensure the height will fit on the canvas + if (this.y - halfHeight < 0 ){ + this.y = halfHeight; + } else if (this.y + halfHeight > this.chart.height){ + this.y = this.chart.height - halfHeight; + } + + //Decide whether to align left or right based on position on canvas + if (this.x > this.chart.width/2){ + this.x -= this.xOffset + this.width; + } else { + this.x += this.xOffset; + } + + + }, + getLineHeight : function(index){ + var baseLineHeight = this.y - (this.height/2) + this.yPadding, + afterTitleIndex = index-1; + + //If the index is zero, we're getting the title + if (index === 0){ + return baseLineHeight + this.titleFontSize/2; + } else{ + return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5; + } + + }, + draw : function(){ + // Custom Tooltips + if(this.custom){ + this.custom(this); + } + else{ + drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius); + var ctx = this.ctx; + ctx.fillStyle = this.fillColor; + ctx.fill(); + ctx.closePath(); + + ctx.textAlign = "left"; + ctx.textBaseline = "middle"; + ctx.fillStyle = this.titleTextColor; + ctx.font = this.titleFont; + + ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0)); + + ctx.font = this.font; + helpers.each(this.labels,function(label,index){ + ctx.fillStyle = this.textColor; + ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1)); + + //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas) + //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); + //Instead we'll make a white filled block to put the legendColour palette over. + + ctx.fillStyle = this.legendColorBackground; + ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); + + ctx.fillStyle = this.legendColors[index].fill; + ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); + + + },this); + } + } + }); + + Chart.Scale = Chart.Element.extend({ + initialize : function(){ + this.fit(); + }, + buildYLabels : function(){ + this.yLabels = []; + + var stepDecimalPlaces = getDecimalPlaces(this.stepValue); + + for (var i=0; i<=this.steps; i++){ + this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)})); + } + this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0; + }, + addXLabel : function(label){ + this.xLabels.push(label); + this.valuesCount++; + this.fit(); + }, + removeXLabel : function(){ + this.xLabels.shift(); + this.valuesCount--; + this.fit(); + }, + // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use + fit: function(){ + // First we need the width of the yLabels, assuming the xLabels aren't rotated + + // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation + this.startPoint = (this.display) ? this.fontSize : 0; + this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels + + // Apply padding settings to the start and end point. + this.startPoint += this.padding; + this.endPoint -= this.padding; + + // Cache the starting height, so can determine if we need to recalculate the scale yAxis + var cachedHeight = this.endPoint - this.startPoint, + cachedYLabelWidth; + + // Build the current yLabels so we have an idea of what size they'll be to start + /* + * This sets what is returned from calculateScaleRange as static properties of this class: + * + this.steps; + this.stepValue; + this.min; + this.max; + * + */ + this.calculateYRange(cachedHeight); + + // With these properties set we can now build the array of yLabels + // and also the width of the largest yLabel + this.buildYLabels(); + + this.calculateXLabelRotation(); + + while((cachedHeight > this.endPoint - this.startPoint)){ + cachedHeight = this.endPoint - this.startPoint; + cachedYLabelWidth = this.yLabelWidth; + + this.calculateYRange(cachedHeight); + this.buildYLabels(); + + // Only go through the xLabel loop again if the yLabel width has changed + if (cachedYLabelWidth < this.yLabelWidth){ + this.calculateXLabelRotation(); + } + } + + }, + calculateXLabelRotation : function(){ + //Get the width of each grid by calculating the difference + //between x offsets between 0 and 1. + + this.ctx.font = this.font; + + var firstWidth = this.ctx.measureText(this.xLabels[0]).width, + lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width, + firstRotated, + lastRotated; + + + this.xScalePaddingRight = lastWidth/2 + 3; + this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10; + + this.xLabelRotation = 0; + if (this.display){ + var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels), + cosRotation, + firstRotatedWidth; + this.xLabelWidth = originalLabelWidth; + //Allow 3 pixels x2 padding either side for label readability + var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6; + + //Max label rotate should be 90 - also act as a loop counter + while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){ + cosRotation = Math.cos(toRadians(this.xLabelRotation)); + + firstRotated = cosRotation * firstWidth; + lastRotated = cosRotation * lastWidth; + + // We're right aligning the text now. + if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){ + this.xScalePaddingLeft = firstRotated + this.fontSize / 2; + } + this.xScalePaddingRight = this.fontSize/2; + + + this.xLabelRotation++; + this.xLabelWidth = cosRotation * originalLabelWidth; + + } + if (this.xLabelRotation > 0){ + this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3; + } + } + else{ + this.xLabelWidth = 0; + this.xScalePaddingRight = this.padding; + this.xScalePaddingLeft = this.padding; + } + + }, + // Needs to be overidden in each Chart type + // Otherwise we need to pass all the data into the scale class + calculateYRange: noop, + drawingArea: function(){ + return this.startPoint - this.endPoint; + }, + calculateY : function(value){ + var scalingFactor = this.drawingArea() / (this.min - this.max); + return this.endPoint - (scalingFactor * (value - this.min)); + }, + calculateX : function(index){ + var isRotated = (this.xLabelRotation > 0), + // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding, + innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight), + valueWidth = innerWidth/Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1), + valueOffset = (valueWidth * index) + this.xScalePaddingLeft; + + if (this.offsetGridLines){ + valueOffset += (valueWidth/2); + } + + return Math.round(valueOffset); + }, + update : function(newProps){ + helpers.extend(this, newProps); + this.fit(); + }, + draw : function(){ + var ctx = this.ctx, + yLabelGap = (this.endPoint - this.startPoint) / this.steps, + xStart = Math.round(this.xScalePaddingLeft); + if (this.display){ + ctx.fillStyle = this.textColor; + ctx.font = this.font; + each(this.yLabels,function(labelString,index){ + var yLabelCenter = this.endPoint - (yLabelGap * index), + linePositionY = Math.round(yLabelCenter), + drawHorizontalLine = this.showHorizontalLines; + + ctx.textAlign = "right"; + ctx.textBaseline = "middle"; + if (this.showLabels){ + ctx.fillText(labelString,xStart - 10,yLabelCenter); + } + + // This is X axis, so draw it + if (index === 0 && !drawHorizontalLine){ + drawHorizontalLine = true; + } + + if (drawHorizontalLine){ + ctx.beginPath(); + } + + if (index > 0){ + // This is a grid line in the centre, so drop that + ctx.lineWidth = this.gridLineWidth; + ctx.strokeStyle = this.gridLineColor; + } else { + // This is the first line on the scale + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.lineColor; + } + + linePositionY += helpers.aliasPixel(ctx.lineWidth); + + if(drawHorizontalLine){ + ctx.moveTo(xStart, linePositionY); + ctx.lineTo(this.width, linePositionY); + ctx.stroke(); + ctx.closePath(); + } + + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.lineColor; + ctx.beginPath(); + ctx.moveTo(xStart - 5, linePositionY); + ctx.lineTo(xStart, linePositionY); + ctx.stroke(); + ctx.closePath(); + + },this); + + each(this.xLabels,function(label,index){ + var xPos = this.calculateX(index) + aliasPixel(this.lineWidth), + // Check to see if line/bar here and decide where to place the line + linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth), + isRotated = (this.xLabelRotation > 0), + drawVerticalLine = this.showVerticalLines; + + // This is Y axis, so draw it + if (index === 0 && !drawVerticalLine){ + drawVerticalLine = true; + } + + if (drawVerticalLine){ + ctx.beginPath(); + } + + if (index > 0){ + // This is a grid line in the centre, so drop that + ctx.lineWidth = this.gridLineWidth; + ctx.strokeStyle = this.gridLineColor; + } else { + // This is the first line on the scale + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.lineColor; + } + + if (drawVerticalLine){ + ctx.moveTo(linePos,this.endPoint); + ctx.lineTo(linePos,this.startPoint - 3); + ctx.stroke(); + ctx.closePath(); + } + + + ctx.lineWidth = this.lineWidth; + ctx.strokeStyle = this.lineColor; + + + // Small lines at the bottom of the base grid line + ctx.beginPath(); + ctx.moveTo(linePos,this.endPoint); + ctx.lineTo(linePos,this.endPoint + 5); + ctx.stroke(); + ctx.closePath(); + + ctx.save(); + ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8); + ctx.rotate(toRadians(this.xLabelRotation)*-1); + ctx.font = this.font; + ctx.textAlign = (isRotated) ? "right" : "center"; + ctx.textBaseline = (isRotated) ? "middle" : "top"; + ctx.fillText(label, 0, 0); + ctx.restore(); + },this); + + } + } + + }); + + Chart.RadialScale = Chart.Element.extend({ + initialize: function(){ + this.size = min([this.height, this.width]); + this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2); + }, + calculateCenterOffset: function(value){ + // Take into account half font size + the yPadding of the top value + var scalingFactor = this.drawingArea / (this.max - this.min); + + return (value - this.min) * scalingFactor; + }, + update : function(){ + if (!this.lineArc){ + this.setScaleSize(); + } else { + this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2); + } + this.buildYLabels(); + }, + buildYLabels: function(){ + this.yLabels = []; + + var stepDecimalPlaces = getDecimalPlaces(this.stepValue); + + for (var i=0; i<=this.steps; i++){ + this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)})); + } + }, + getCircumference : function(){ + return ((Math.PI*2) / this.valuesCount); + }, + setScaleSize: function(){ + /* + * Right, this is really confusing and there is a lot of maths going on here + * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 + * + * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif + * + * Solution: + * + * We assume the radius of the polygon is half the size of the canvas at first + * at each index we check if the text overlaps. + * + * Where it does, we store that angle and that index. + * + * After finding the largest index and angle we calculate how much we need to remove + * from the shape radius to move the point inwards by that x. + * + * We average the left and right distances to get the maximum shape radius that can fit in the box + * along with labels. + * + * Once we have that, we can find the centre point for the chart, by taking the x text protrusion + * on each side, removing that from the size, halving it and adding the left x protrusion width. + * + * This will mean we have a shape fitted to the canvas, as large as it can be with the labels + * and position it in the most space efficient manner + * + * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif + */ + + + // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. + // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points + var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]), + pointPosition, + i, + textWidth, + halfTextWidth, + furthestRight = this.width, + furthestRightIndex, + furthestRightAngle, + furthestLeft = 0, + furthestLeftIndex, + furthestLeftAngle, + xProtrusionLeft, + xProtrusionRight, + radiusReductionRight, + radiusReductionLeft, + maxWidthRadius; + this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily); + for (i=0;i furthestRight) { + furthestRight = pointPosition.x + halfTextWidth; + furthestRightIndex = i; + } + if (pointPosition.x - halfTextWidth < furthestLeft) { + furthestLeft = pointPosition.x - halfTextWidth; + furthestLeftIndex = i; + } + } + else if (i < this.valuesCount/2) { + // Less than half the values means we'll left align the text + if (pointPosition.x + textWidth > furthestRight) { + furthestRight = pointPosition.x + textWidth; + furthestRightIndex = i; + } + } + else if (i > this.valuesCount/2){ + // More than half the values means we'll right align the text + if (pointPosition.x - textWidth < furthestLeft) { + furthestLeft = pointPosition.x - textWidth; + furthestLeftIndex = i; + } + } + } + + xProtrusionLeft = furthestLeft; + + xProtrusionRight = Math.ceil(furthestRight - this.width); + + furthestRightAngle = this.getIndexAngle(furthestRightIndex); + + furthestLeftAngle = this.getIndexAngle(furthestLeftIndex); + + radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2); + + radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2); + + // Ensure we actually need to reduce the size of the chart + radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0; + radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0; + + this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2; + + //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2]) + this.setCenterPoint(radiusReductionLeft, radiusReductionRight); + + }, + setCenterPoint: function(leftMovement, rightMovement){ + + var maxRight = this.width - rightMovement - this.drawingArea, + maxLeft = leftMovement + this.drawingArea; + + this.xCenter = (maxLeft + maxRight)/2; + // Always vertically in the centre as the text height doesn't change + this.yCenter = (this.height/2); + }, + + getIndexAngle : function(index){ + var angleMultiplier = (Math.PI * 2) / this.valuesCount; + // Start from the top instead of right, so remove a quarter of the circle + + return index * angleMultiplier - (Math.PI/2); + }, + getPointPosition : function(index, distanceFromCenter){ + var thisAngle = this.getIndexAngle(index); + return { + x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter, + y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter + }; + }, + draw: function(){ + if (this.display){ + var ctx = this.ctx; + each(this.yLabels, function(label, index){ + // Don't draw a centre value + if (index > 0){ + var yCenterOffset = index * (this.drawingArea/this.steps), + yHeight = this.yCenter - yCenterOffset, + pointPosition; + + // Draw circular lines around the scale + if (this.lineWidth > 0){ + ctx.strokeStyle = this.lineColor; + ctx.lineWidth = this.lineWidth; + + if(this.lineArc){ + ctx.beginPath(); + ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2); + ctx.closePath(); + ctx.stroke(); + } else{ + ctx.beginPath(); + for (var i=0;i= 0; i--) { + if (this.angleLineWidth > 0){ + var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max)); + ctx.beginPath(); + ctx.moveTo(this.xCenter, this.yCenter); + ctx.lineTo(outerPosition.x, outerPosition.y); + ctx.stroke(); + ctx.closePath(); + } + // Extra 3px out for some label spacing + var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5); + ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily); + ctx.fillStyle = this.pointLabelFontColor; + + var labelsCount = this.labels.length, + halfLabelsCount = this.labels.length/2, + quarterLabelsCount = halfLabelsCount/2, + upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount), + exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount); + if (i === 0){ + ctx.textAlign = 'center'; + } else if(i === halfLabelsCount){ + ctx.textAlign = 'center'; + } else if (i < halfLabelsCount){ + ctx.textAlign = 'left'; + } else { + ctx.textAlign = 'right'; + } + + // Set the correct text baseline based on outer positioning + if (exactQuarter){ + ctx.textBaseline = 'middle'; + } else if (upperHalf){ + ctx.textBaseline = 'bottom'; + } else { + ctx.textBaseline = 'top'; + } + + ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y); + } + } + } + } + }); + + // Attach global event to resize each chart instance when the browser resizes + helpers.addEvent(window, "resize", (function(){ + // Basic debounce of resize function so it doesn't hurt performance when resizing browser. + var timeout; + return function(){ + clearTimeout(timeout); + timeout = setTimeout(function(){ + each(Chart.instances,function(instance){ + // If the responsive flag is set in the chart instance config + // Cascade the resize event down to the chart. + if (instance.options.responsive){ + instance.resize(instance.render, true); + } + }); + }, 50); + }; + })()); + + + if (amd) { + define(function(){ + return Chart; + }); + } else if (typeof module === 'object' && module.exports) { + module.exports = Chart; + } + + root.Chart = Chart; + + Chart.noConflict = function(){ + root.Chart = previous; + return Chart; + }; + +}).call(this); + +(function(){ + "use strict"; + + var root = this, + Chart = root.Chart, + helpers = Chart.helpers; + + + var defaultConfig = { + //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value + scaleBeginAtZero : true, + + //Boolean - Whether grid lines are shown across the chart + scaleShowGridLines : true, + + //String - Colour of the grid lines + scaleGridLineColor : "rgba(0,0,0,.05)", + + //Number - Width of the grid lines + scaleGridLineWidth : 1, + + //Boolean - Whether to show horizontal lines (except X axis) + scaleShowHorizontalLines: true, + + //Boolean - Whether to show vertical lines (except Y axis) + scaleShowVerticalLines: true, + + //Boolean - If there is a stroke on each bar + barShowStroke : true, + + //Number - Pixel width of the bar stroke + barStrokeWidth : 2, + + //Number - Spacing between each of the X value sets + barValueSpacing : 5, + + //Number - Spacing between data sets within X values + barDatasetSpacing : 1, + + //String - A legend template + legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + + }; + + + Chart.Type.extend({ + name: "Bar", + defaults : defaultConfig, + initialize: function(data){ + + //Expose options as a scope variable here so we can access it in the ScaleClass + var options = this.options; + + this.ScaleClass = Chart.Scale.extend({ + offsetGridLines : true, + calculateBarX : function(datasetCount, datasetIndex, barIndex){ + //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar + var xWidth = this.calculateBaseWidth(), + xAbsolute = this.calculateX(barIndex) - (xWidth/2), + barWidth = this.calculateBarWidth(datasetCount); + + return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2; + }, + calculateBaseWidth : function(){ + return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing); + }, + calculateBarWidth : function(datasetCount){ + //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset + var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); + + return (baseWidth / datasetCount); + } + }); + + this.datasets = []; + + //Set up tooltip events on the chart + if (this.options.showTooltips){ + helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ + var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : []; + + this.eachBars(function(bar){ + bar.restore(['fillColor', 'strokeColor']); + }); + helpers.each(activeBars, function(activeBar){ + activeBar.fillColor = activeBar.highlightFill; + activeBar.strokeColor = activeBar.highlightStroke; + }); + this.showTooltip(activeBars); + }); + } + + //Declare the extension of the default point, to cater for the options passed in to the constructor + this.BarClass = Chart.Rectangle.extend({ + strokeWidth : this.options.barStrokeWidth, + showStroke : this.options.barShowStroke, + ctx : this.chart.ctx + }); + + //Iterate through each of the datasets, and build this into a property of the chart + helpers.each(data.datasets,function(dataset,datasetIndex){ + + var datasetObject = { + label : dataset.label || null, + fillColor : dataset.fillColor, + strokeColor : dataset.strokeColor, + bars : [] + }; + + this.datasets.push(datasetObject); + + helpers.each(dataset.data,function(dataPoint,index){ + //Add a new point for each piece of data, passing any required data to draw. + datasetObject.bars.push(new this.BarClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.strokeColor, + fillColor : dataset.fillColor, + highlightFill : dataset.highlightFill || dataset.fillColor, + highlightStroke : dataset.highlightStroke || dataset.strokeColor + })); + },this); + + },this); + + this.buildScale(data.labels); + + this.BarClass.prototype.base = this.scale.endPoint; + + this.eachBars(function(bar, index, datasetIndex){ + helpers.extend(bar, { + width : this.scale.calculateBarWidth(this.datasets.length), + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y: this.scale.endPoint + }); + bar.save(); + }, this); + + this.render(); + }, + update : function(){ + this.scale.update(); + // Reset any highlight colours before updating. + helpers.each(this.activeElements, function(activeElement){ + activeElement.restore(['fillColor', 'strokeColor']); + }); + + this.eachBars(function(bar){ + bar.save(); + }); + this.render(); + }, + eachBars : function(callback){ + helpers.each(this.datasets,function(dataset, datasetIndex){ + helpers.each(dataset.bars, callback, this, datasetIndex); + },this); + }, + getBarsAtEvent : function(e){ + var barsArray = [], + eventPosition = helpers.getRelativePosition(e), + datasetIterator = function(dataset){ + barsArray.push(dataset.bars[barIndex]); + }, + barIndex; + + for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) { + for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) { + if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){ + helpers.each(this.datasets, datasetIterator); + return barsArray; + } + } + } + + return barsArray; + }, + buildScale : function(labels){ + var self = this; + + var dataTotal = function(){ + var values = []; + self.eachBars(function(bar){ + values.push(bar.value); + }); + return values; + }; + + var scaleOptions = { + templateString : this.options.scaleLabel, + height : this.chart.height, + width : this.chart.width, + ctx : this.chart.ctx, + textColor : this.options.scaleFontColor, + fontSize : this.options.scaleFontSize, + fontStyle : this.options.scaleFontStyle, + fontFamily : this.options.scaleFontFamily, + valuesCount : labels.length, + beginAtZero : this.options.scaleBeginAtZero, + integersOnly : this.options.scaleIntegersOnly, + calculateYRange: function(currentHeight){ + var updatedRanges = helpers.calculateScaleRange( + dataTotal(), + currentHeight, + this.fontSize, + this.beginAtZero, + this.integersOnly + ); + helpers.extend(this, updatedRanges); + }, + xLabels : labels, + font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), + lineWidth : this.options.scaleLineWidth, + lineColor : this.options.scaleLineColor, + showHorizontalLines : this.options.scaleShowHorizontalLines, + showVerticalLines : this.options.scaleShowVerticalLines, + gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, + gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", + padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0, + showLabels : this.options.scaleShowLabels, + display : this.options.showScale + }; + + if (this.options.scaleOverride){ + helpers.extend(scaleOptions, { + calculateYRange: helpers.noop, + steps: this.options.scaleSteps, + stepValue: this.options.scaleStepWidth, + min: this.options.scaleStartValue, + max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) + }); + } + + this.scale = new this.ScaleClass(scaleOptions); + }, + addData : function(valuesArray,label){ + //Map the values array for each of the datasets + helpers.each(valuesArray,function(value,datasetIndex){ + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].bars.push(new this.BarClass({ + value : value, + label : label, + x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), + y: this.scale.endPoint, + width : this.scale.calculateBarWidth(this.datasets.length), + base : this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].strokeColor, + fillColor : this.datasets[datasetIndex].fillColor + })); + },this); + + this.scale.addXLabel(label); + //Then re-render the chart. + this.update(); + }, + removeData : function(){ + this.scale.removeXLabel(); + //Then re-render the chart. + helpers.each(this.datasets,function(dataset){ + dataset.bars.shift(); + },this); + this.update(); + }, + reflow : function(){ + helpers.extend(this.BarClass.prototype,{ + y: this.scale.endPoint, + base : this.scale.endPoint + }); + var newScaleProps = helpers.extend({ + height : this.chart.height, + width : this.chart.width + }); + this.scale.update(newScaleProps); + }, + draw : function(ease){ + var easingDecimal = ease || 1; + this.clear(); + + var ctx = this.chart.ctx; + + this.scale.draw(easingDecimal); + + //Draw all the bars for each dataset + helpers.each(this.datasets,function(dataset,datasetIndex){ + helpers.each(dataset.bars,function(bar,index){ + if (bar.hasValue()){ + bar.base = this.scale.endPoint; + //Transition then draw + bar.transition({ + x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), + y : this.scale.calculateY(bar.value), + width : this.scale.calculateBarWidth(this.datasets.length) + }, easingDecimal).draw(); + } + },this); + + },this); + } + }); + + +}).call(this); + +(function(){ + "use strict"; + + var root = this, + Chart = root.Chart, + //Cache a local reference to Chart.helpers + helpers = Chart.helpers; + + var defaultConfig = { + //Boolean - Whether we should show a stroke on each segment + segmentShowStroke : true, + + //String - The colour of each segment stroke + segmentStrokeColor : "#fff", + + //Number - The width of each segment stroke + segmentStrokeWidth : 2, + + //The percentage of the chart that we cut out of the middle. + percentageInnerCutout : 50, + + //Number - Amount of animation steps + animationSteps : 100, + + //String - Animation easing effect + animationEasing : "easeOutBounce", + + //Boolean - Whether we animate the rotation of the Doughnut + animateRotate : true, + + //Boolean - Whether we animate scaling the Doughnut from the centre + animateScale : false, + + //String - A legend template + legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
" + + }; + + + Chart.Type.extend({ + //Passing in a name registers this chart in the Chart namespace + name: "Doughnut", + //Providing a defaults will also register the deafults in the chart namespace + defaults : defaultConfig, + //Initialize is fired when the chart is initialized - Data is passed in as a parameter + //Config is automatically merged by the core of Chart.js, and is available at this.options + initialize: function(data){ + + //Declare segments as a static property to prevent inheriting across the Chart type prototype + this.segments = []; + this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2; + + this.SegmentArc = Chart.Arc.extend({ + ctx : this.chart.ctx, + x : this.chart.width/2, + y : this.chart.height/2 + }); + + //Set up tooltip events on the chart + if (this.options.showTooltips){ + helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ + var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : []; + + helpers.each(this.segments,function(segment){ + segment.restore(["fillColor"]); + }); + helpers.each(activeSegments,function(activeSegment){ + activeSegment.fillColor = activeSegment.highlightColor; + }); + this.showTooltip(activeSegments); + }); + } + this.calculateTotal(data); + + helpers.each(data,function(datapoint, index){ + this.addData(datapoint, index, true); + },this); + + this.render(); + }, + getSegmentsAtEvent : function(e){ + var segmentsArray = []; + + var location = helpers.getRelativePosition(e); + + helpers.each(this.segments,function(segment){ + if (segment.inRange(location.x,location.y)) segmentsArray.push(segment); + },this); + return segmentsArray; + }, + addData : function(segment, atIndex, silent){ + var index = atIndex || this.segments.length; + this.segments.splice(index, 0, new this.SegmentArc({ + value : segment.value, + outerRadius : (this.options.animateScale) ? 0 : this.outerRadius, + innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout, + fillColor : segment.color, + highlightColor : segment.highlight || segment.color, + showStroke : this.options.segmentShowStroke, + strokeWidth : this.options.segmentStrokeWidth, + strokeColor : this.options.segmentStrokeColor, + startAngle : Math.PI * 1.5, + circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value), + label : segment.label + })); + if (!silent){ + this.reflow(); + this.update(); + } + }, + calculateCircumference : function(value){ + return (Math.PI*2)*(Math.abs(value) / this.total); + }, + calculateTotal : function(data){ + this.total = 0; + helpers.each(data,function(segment){ + this.total += Math.abs(segment.value); + },this); + }, + update : function(){ + this.calculateTotal(this.segments); + + // Reset any highlight colours before updating. + helpers.each(this.activeElements, function(activeElement){ + activeElement.restore(['fillColor']); + }); + + helpers.each(this.segments,function(segment){ + segment.save(); + }); + this.render(); + }, + + removeData: function(atIndex){ + var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1; + this.segments.splice(indexToDelete, 1); + this.reflow(); + this.update(); + }, + + reflow : function(){ + helpers.extend(this.SegmentArc.prototype,{ + x : this.chart.width/2, + y : this.chart.height/2 + }); + this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2; + helpers.each(this.segments, function(segment){ + segment.update({ + outerRadius : this.outerRadius, + innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout + }); + }, this); + }, + draw : function(easeDecimal){ + var animDecimal = (easeDecimal) ? easeDecimal : 1; + this.clear(); + helpers.each(this.segments,function(segment,index){ + segment.transition({ + circumference : this.calculateCircumference(segment.value), + outerRadius : this.outerRadius, + innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout + },animDecimal); + + segment.endAngle = segment.startAngle + segment.circumference; + + segment.draw(); + if (index === 0){ + segment.startAngle = Math.PI * 1.5; + } + //Check to see if it's the last segment, if not get the next and update the start angle + if (index < this.segments.length-1){ + this.segments[index+1].startAngle = segment.endAngle; + } + },this); + + } + }); + + Chart.types.Doughnut.extend({ + name : "Pie", + defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0}) + }); + +}).call(this); +(function(){ + "use strict"; + + var root = this, + Chart = root.Chart, + helpers = Chart.helpers; + + var defaultConfig = { + + ///Boolean - Whether grid lines are shown across the chart + scaleShowGridLines : true, + + //String - Colour of the grid lines + scaleGridLineColor : "rgba(0,0,0,.05)", + + //Number - Width of the grid lines + scaleGridLineWidth : 1, + + //Boolean - Whether to show horizontal lines (except X axis) + scaleShowHorizontalLines: true, + + //Boolean - Whether to show vertical lines (except Y axis) + scaleShowVerticalLines: true, + + //Boolean - Whether the line is curved between points + bezierCurve : true, + + //Number - Tension of the bezier curve between points + bezierCurveTension : 0.4, + + //Boolean - Whether to show a dot for each point + pointDot : true, + + //Number - Radius of each point dot in pixels + pointDotRadius : 4, + + //Number - Pixel width of point dot stroke + pointDotStrokeWidth : 1, + + //Number - amount extra to add to the radius to cater for hit detection outside the drawn point + pointHitDetectionRadius : 20, + + //Boolean - Whether to show a stroke for datasets + datasetStroke : true, + + //Number - Pixel width of dataset stroke + datasetStrokeWidth : 2, + + //Boolean - Whether to fill the dataset with a colour + datasetFill : true, + + //String - A legend template + legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + + }; + + + Chart.Type.extend({ + name: "Line", + defaults : defaultConfig, + initialize: function(data){ + //Declare the extension of the default point, to cater for the options passed in to the constructor + this.PointClass = Chart.Point.extend({ + strokeWidth : this.options.pointDotStrokeWidth, + radius : this.options.pointDotRadius, + display: this.options.pointDot, + hitDetectionRadius : this.options.pointHitDetectionRadius, + ctx : this.chart.ctx, + inRange : function(mouseX){ + return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2)); + } + }); + + this.datasets = []; + + //Set up tooltip events on the chart + if (this.options.showTooltips){ + helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ + var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : []; + this.eachPoints(function(point){ + point.restore(['fillColor', 'strokeColor']); + }); + helpers.each(activePoints, function(activePoint){ + activePoint.fillColor = activePoint.highlightFill; + activePoint.strokeColor = activePoint.highlightStroke; + }); + this.showTooltip(activePoints); + }); + } + + //Iterate through each of the datasets, and build this into a property of the chart + helpers.each(data.datasets,function(dataset){ + + var datasetObject = { + label : dataset.label || null, + fillColor : dataset.fillColor, + strokeColor : dataset.strokeColor, + pointColor : dataset.pointColor, + pointStrokeColor : dataset.pointStrokeColor, + points : [] + }; + + this.datasets.push(datasetObject); + + + helpers.each(dataset.data,function(dataPoint,index){ + //Add a new point for each piece of data, passing any required data to draw. + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); + },this); + + this.buildScale(data.labels); + + + this.eachPoints(function(point, index){ + helpers.extend(point, { + x: this.scale.calculateX(index), + y: this.scale.endPoint + }); + point.save(); + }, this); + + },this); + + + this.render(); + }, + update : function(){ + this.scale.update(); + // Reset any highlight colours before updating. + helpers.each(this.activeElements, function(activeElement){ + activeElement.restore(['fillColor', 'strokeColor']); + }); + this.eachPoints(function(point){ + point.save(); + }); + this.render(); + }, + eachPoints : function(callback){ + helpers.each(this.datasets,function(dataset){ + helpers.each(dataset.points,callback,this); + },this); + }, + getPointsAtEvent : function(e){ + var pointsArray = [], + eventPosition = helpers.getRelativePosition(e); + helpers.each(this.datasets,function(dataset){ + helpers.each(dataset.points,function(point){ + if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point); + }); + },this); + return pointsArray; + }, + buildScale : function(labels){ + var self = this; + + var dataTotal = function(){ + var values = []; + self.eachPoints(function(point){ + values.push(point.value); + }); + + return values; + }; + + var scaleOptions = { + templateString : this.options.scaleLabel, + height : this.chart.height, + width : this.chart.width, + ctx : this.chart.ctx, + textColor : this.options.scaleFontColor, + fontSize : this.options.scaleFontSize, + fontStyle : this.options.scaleFontStyle, + fontFamily : this.options.scaleFontFamily, + valuesCount : labels.length, + beginAtZero : this.options.scaleBeginAtZero, + integersOnly : this.options.scaleIntegersOnly, + calculateYRange : function(currentHeight){ + var updatedRanges = helpers.calculateScaleRange( + dataTotal(), + currentHeight, + this.fontSize, + this.beginAtZero, + this.integersOnly + ); + helpers.extend(this, updatedRanges); + }, + xLabels : labels, + font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), + lineWidth : this.options.scaleLineWidth, + lineColor : this.options.scaleLineColor, + showHorizontalLines : this.options.scaleShowHorizontalLines, + showVerticalLines : this.options.scaleShowVerticalLines, + gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, + gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", + padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth, + showLabels : this.options.scaleShowLabels, + display : this.options.showScale + }; + + if (this.options.scaleOverride){ + helpers.extend(scaleOptions, { + calculateYRange: helpers.noop, + steps: this.options.scaleSteps, + stepValue: this.options.scaleStepWidth, + min: this.options.scaleStartValue, + max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) + }); + } + + + this.scale = new Chart.Scale(scaleOptions); + }, + addData : function(valuesArray,label){ + //Map the values array for each of the datasets + + helpers.each(valuesArray,function(value,datasetIndex){ + //Add a new point for each piece of data, passing any required data to draw. + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: this.scale.calculateX(this.scale.valuesCount+1), + y: this.scale.endPoint, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); + },this); + + this.scale.addXLabel(label); + //Then re-render the chart. + this.update(); + }, + removeData : function(){ + this.scale.removeXLabel(); + //Then re-render the chart. + helpers.each(this.datasets,function(dataset){ + dataset.points.shift(); + },this); + this.update(); + }, + reflow : function(){ + var newScaleProps = helpers.extend({ + height : this.chart.height, + width : this.chart.width + }); + this.scale.update(newScaleProps); + }, + draw : function(ease){ + var easingDecimal = ease || 1; + this.clear(); + + var ctx = this.chart.ctx; + + // Some helper methods for getting the next/prev points + var hasValue = function(item){ + return item.value !== null; + }, + nextPoint = function(point, collection, index){ + return helpers.findNextWhere(collection, hasValue, index) || point; + }, + previousPoint = function(point, collection, index){ + return helpers.findPreviousWhere(collection, hasValue, index) || point; + }; + + this.scale.draw(easingDecimal); + + + helpers.each(this.datasets,function(dataset){ + var pointsWithValues = helpers.where(dataset.points, hasValue); + + //Transition each point first so that the line and point drawing isn't out of sync + //We can use this extra loop to calculate the control points of this dataset also in this loop + + helpers.each(dataset.points, function(point, index){ + if (point.hasValue()){ + point.transition({ + y : this.scale.calculateY(point.value), + x : this.scale.calculateX(index) + }, easingDecimal); + } + },this); + + + // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point + // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed + if (this.options.bezierCurve){ + helpers.each(pointsWithValues, function(point, index){ + var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0; + point.controlPoints = helpers.splineCurve( + previousPoint(point, pointsWithValues, index), + point, + nextPoint(point, pointsWithValues, index), + tension + ); + + // Prevent the bezier going outside of the bounds of the graph + + // Cap puter bezier handles to the upper/lower scale bounds + if (point.controlPoints.outer.y > this.scale.endPoint){ + point.controlPoints.outer.y = this.scale.endPoint; + } + else if (point.controlPoints.outer.y < this.scale.startPoint){ + point.controlPoints.outer.y = this.scale.startPoint; + } + + // Cap inner bezier handles to the upper/lower scale bounds + if (point.controlPoints.inner.y > this.scale.endPoint){ + point.controlPoints.inner.y = this.scale.endPoint; + } + else if (point.controlPoints.inner.y < this.scale.startPoint){ + point.controlPoints.inner.y = this.scale.startPoint; + } + },this); + } + + + //Draw the line between all the points + ctx.lineWidth = this.options.datasetStrokeWidth; + ctx.strokeStyle = dataset.strokeColor; + ctx.beginPath(); + + helpers.each(pointsWithValues, function(point, index){ + if (index === 0){ + ctx.moveTo(point.x, point.y); + } + else{ + if(this.options.bezierCurve){ + var previous = previousPoint(point, pointsWithValues, index); + + ctx.bezierCurveTo( + previous.controlPoints.outer.x, + previous.controlPoints.outer.y, + point.controlPoints.inner.x, + point.controlPoints.inner.y, + point.x, + point.y + ); + } + else{ + ctx.lineTo(point.x,point.y); + } + } + }, this); + + ctx.stroke(); + + if (this.options.datasetFill && pointsWithValues.length > 0){ + //Round off the line by going to the base of the chart, back to the start, then fill. + ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint); + ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint); + ctx.fillStyle = dataset.fillColor; + ctx.closePath(); + ctx.fill(); + } + + //Now draw the points over the line + //A little inefficient double looping, but better than the line + //lagging behind the point positions + helpers.each(pointsWithValues,function(point){ + point.draw(); + }); + },this); + } + }); + + +}).call(this); + +(function(){ + "use strict"; + + var root = this, + Chart = root.Chart, + //Cache a local reference to Chart.helpers + helpers = Chart.helpers; + + var defaultConfig = { + //Boolean - Show a backdrop to the scale label + scaleShowLabelBackdrop : true, + + //String - The colour of the label backdrop + scaleBackdropColor : "rgba(255,255,255,0.75)", + + // Boolean - Whether the scale should begin at zero + scaleBeginAtZero : true, + + //Number - The backdrop padding above & below the label in pixels + scaleBackdropPaddingY : 2, + + //Number - The backdrop padding to the side of the label in pixels + scaleBackdropPaddingX : 2, + + //Boolean - Show line for each value in the scale + scaleShowLine : true, + + //Boolean - Stroke a line around each segment in the chart + segmentShowStroke : true, + + //String - The colour of the stroke on each segement. + segmentStrokeColor : "#fff", + + //Number - The width of the stroke value in pixels + segmentStrokeWidth : 2, + + //Number - Amount of animation steps + animationSteps : 100, + + //String - Animation easing effect. + animationEasing : "easeOutBounce", + + //Boolean - Whether to animate the rotation of the chart + animateRotate : true, + + //Boolean - Whether to animate scaling the chart from the centre + animateScale : false, + + //String - A legend template + legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
" + }; + + + Chart.Type.extend({ + //Passing in a name registers this chart in the Chart namespace + name: "PolarArea", + //Providing a defaults will also register the deafults in the chart namespace + defaults : defaultConfig, + //Initialize is fired when the chart is initialized - Data is passed in as a parameter + //Config is automatically merged by the core of Chart.js, and is available at this.options + initialize: function(data){ + this.segments = []; + //Declare segment class as a chart instance specific class, so it can share props for this instance + this.SegmentArc = Chart.Arc.extend({ + showStroke : this.options.segmentShowStroke, + strokeWidth : this.options.segmentStrokeWidth, + strokeColor : this.options.segmentStrokeColor, + ctx : this.chart.ctx, + innerRadius : 0, + x : this.chart.width/2, + y : this.chart.height/2 + }); + this.scale = new Chart.RadialScale({ + display: this.options.showScale, + fontStyle: this.options.scaleFontStyle, + fontSize: this.options.scaleFontSize, + fontFamily: this.options.scaleFontFamily, + fontColor: this.options.scaleFontColor, + showLabels: this.options.scaleShowLabels, + showLabelBackdrop: this.options.scaleShowLabelBackdrop, + backdropColor: this.options.scaleBackdropColor, + backdropPaddingY : this.options.scaleBackdropPaddingY, + backdropPaddingX: this.options.scaleBackdropPaddingX, + lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0, + lineColor: this.options.scaleLineColor, + lineArc: true, + width: this.chart.width, + height: this.chart.height, + xCenter: this.chart.width/2, + yCenter: this.chart.height/2, + ctx : this.chart.ctx, + templateString: this.options.scaleLabel, + valuesCount: data.length + }); + + this.updateScaleRange(data); + + this.scale.update(); + + helpers.each(data,function(segment,index){ + this.addData(segment,index,true); + },this); + + //Set up tooltip events on the chart + if (this.options.showTooltips){ + helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ + var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : []; + helpers.each(this.segments,function(segment){ + segment.restore(["fillColor"]); + }); + helpers.each(activeSegments,function(activeSegment){ + activeSegment.fillColor = activeSegment.highlightColor; + }); + this.showTooltip(activeSegments); + }); + } + + this.render(); + }, + getSegmentsAtEvent : function(e){ + var segmentsArray = []; + + var location = helpers.getRelativePosition(e); + + helpers.each(this.segments,function(segment){ + if (segment.inRange(location.x,location.y)) segmentsArray.push(segment); + },this); + return segmentsArray; + }, + addData : function(segment, atIndex, silent){ + var index = atIndex || this.segments.length; + + this.segments.splice(index, 0, new this.SegmentArc({ + fillColor: segment.color, + highlightColor: segment.highlight || segment.color, + label: segment.label, + value: segment.value, + outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value), + circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(), + startAngle: Math.PI * 1.5 + })); + if (!silent){ + this.reflow(); + this.update(); + } + }, + removeData: function(atIndex){ + var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1; + this.segments.splice(indexToDelete, 1); + this.reflow(); + this.update(); + }, + calculateTotal: function(data){ + this.total = 0; + helpers.each(data,function(segment){ + this.total += segment.value; + },this); + this.scale.valuesCount = this.segments.length; + }, + updateScaleRange: function(datapoints){ + var valuesArray = []; + helpers.each(datapoints,function(segment){ + valuesArray.push(segment.value); + }); + + var scaleSizes = (this.options.scaleOverride) ? + { + steps: this.options.scaleSteps, + stepValue: this.options.scaleStepWidth, + min: this.options.scaleStartValue, + max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) + } : + helpers.calculateScaleRange( + valuesArray, + helpers.min([this.chart.width, this.chart.height])/2, + this.options.scaleFontSize, + this.options.scaleBeginAtZero, + this.options.scaleIntegersOnly + ); + + helpers.extend( + this.scale, + scaleSizes, + { + size: helpers.min([this.chart.width, this.chart.height]), + xCenter: this.chart.width/2, + yCenter: this.chart.height/2 + } + ); + + }, + update : function(){ + this.calculateTotal(this.segments); + + helpers.each(this.segments,function(segment){ + segment.save(); + }); + + this.reflow(); + this.render(); + }, + reflow : function(){ + helpers.extend(this.SegmentArc.prototype,{ + x : this.chart.width/2, + y : this.chart.height/2 + }); + this.updateScaleRange(this.segments); + this.scale.update(); + + helpers.extend(this.scale,{ + xCenter: this.chart.width/2, + yCenter: this.chart.height/2 + }); + + helpers.each(this.segments, function(segment){ + segment.update({ + outerRadius : this.scale.calculateCenterOffset(segment.value) + }); + }, this); + + }, + draw : function(ease){ + var easingDecimal = ease || 1; + //Clear & draw the canvas + this.clear(); + helpers.each(this.segments,function(segment, index){ + segment.transition({ + circumference : this.scale.getCircumference(), + outerRadius : this.scale.calculateCenterOffset(segment.value) + },easingDecimal); + + segment.endAngle = segment.startAngle + segment.circumference; + + // If we've removed the first segment we need to set the first one to + // start at the top. + if (index === 0){ + segment.startAngle = Math.PI * 1.5; + } + + //Check to see if it's the last segment, if not get the next and update the start angle + if (index < this.segments.length - 1){ + this.segments[index+1].startAngle = segment.endAngle; + } + segment.draw(); + }, this); + this.scale.draw(); + } + }); + +}).call(this); +(function(){ + "use strict"; + + var root = this, + Chart = root.Chart, + helpers = Chart.helpers; + + + + Chart.Type.extend({ + name: "Radar", + defaults:{ + //Boolean - Whether to show lines for each scale point + scaleShowLine : true, + + //Boolean - Whether we show the angle lines out of the radar + angleShowLineOut : true, + + //Boolean - Whether to show labels on the scale + scaleShowLabels : false, + + // Boolean - Whether the scale should begin at zero + scaleBeginAtZero : true, + + //String - Colour of the angle line + angleLineColor : "rgba(0,0,0,.1)", + + //Number - Pixel width of the angle line + angleLineWidth : 1, + + //String - Point label font declaration + pointLabelFontFamily : "'Arial'", + + //String - Point label font weight + pointLabelFontStyle : "normal", + + //Number - Point label font size in pixels + pointLabelFontSize : 10, + + //String - Point label font colour + pointLabelFontColor : "#666", + + //Boolean - Whether to show a dot for each point + pointDot : true, + + //Number - Radius of each point dot in pixels + pointDotRadius : 3, + + //Number - Pixel width of point dot stroke + pointDotStrokeWidth : 1, + + //Number - amount extra to add to the radius to cater for hit detection outside the drawn point + pointHitDetectionRadius : 20, + + //Boolean - Whether to show a stroke for datasets + datasetStroke : true, + + //Number - Pixel width of dataset stroke + datasetStrokeWidth : 2, + + //Boolean - Whether to fill the dataset with a colour + datasetFill : true, + + //String - A legend template + legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + + }, + + initialize: function(data){ + this.PointClass = Chart.Point.extend({ + strokeWidth : this.options.pointDotStrokeWidth, + radius : this.options.pointDotRadius, + display: this.options.pointDot, + hitDetectionRadius : this.options.pointHitDetectionRadius, + ctx : this.chart.ctx + }); + + this.datasets = []; + + this.buildScale(data); + + //Set up tooltip events on the chart + if (this.options.showTooltips){ + helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ + var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : []; + + this.eachPoints(function(point){ + point.restore(['fillColor', 'strokeColor']); + }); + helpers.each(activePointsCollection, function(activePoint){ + activePoint.fillColor = activePoint.highlightFill; + activePoint.strokeColor = activePoint.highlightStroke; + }); + + this.showTooltip(activePointsCollection); + }); + } + + //Iterate through each of the datasets, and build this into a property of the chart + helpers.each(data.datasets,function(dataset){ + + var datasetObject = { + label: dataset.label || null, + fillColor : dataset.fillColor, + strokeColor : dataset.strokeColor, + pointColor : dataset.pointColor, + pointStrokeColor : dataset.pointStrokeColor, + points : [] + }; + + this.datasets.push(datasetObject); + + helpers.each(dataset.data,function(dataPoint,index){ + //Add a new point for each piece of data, passing any required data to draw. + var pointPosition; + if (!this.scale.animation){ + pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); + } + datasetObject.points.push(new this.PointClass({ + value : dataPoint, + label : data.labels[index], + datasetLabel: dataset.label, + x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, + y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, + strokeColor : dataset.pointStrokeColor, + fillColor : dataset.pointColor, + highlightFill : dataset.pointHighlightFill || dataset.pointColor, + highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor + })); + },this); + + },this); + + this.render(); + }, + eachPoints : function(callback){ + helpers.each(this.datasets,function(dataset){ + helpers.each(dataset.points,callback,this); + },this); + }, + + getPointsAtEvent : function(evt){ + var mousePosition = helpers.getRelativePosition(evt), + fromCenter = helpers.getAngleFromPoint({ + x: this.scale.xCenter, + y: this.scale.yCenter + }, mousePosition); + + var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount, + pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex), + activePointsCollection = []; + + // If we're at the top, make the pointIndex 0 to get the first of the array. + if (pointIndex >= this.scale.valuesCount || pointIndex < 0){ + pointIndex = 0; + } + + if (fromCenter.distance <= this.scale.drawingArea){ + helpers.each(this.datasets, function(dataset){ + activePointsCollection.push(dataset.points[pointIndex]); + }); + } + + return activePointsCollection; + }, + + buildScale : function(data){ + this.scale = new Chart.RadialScale({ + display: this.options.showScale, + fontStyle: this.options.scaleFontStyle, + fontSize: this.options.scaleFontSize, + fontFamily: this.options.scaleFontFamily, + fontColor: this.options.scaleFontColor, + showLabels: this.options.scaleShowLabels, + showLabelBackdrop: this.options.scaleShowLabelBackdrop, + backdropColor: this.options.scaleBackdropColor, + backdropPaddingY : this.options.scaleBackdropPaddingY, + backdropPaddingX: this.options.scaleBackdropPaddingX, + lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0, + lineColor: this.options.scaleLineColor, + angleLineColor : this.options.angleLineColor, + angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0, + // Point labels at the edge of each line + pointLabelFontColor : this.options.pointLabelFontColor, + pointLabelFontSize : this.options.pointLabelFontSize, + pointLabelFontFamily : this.options.pointLabelFontFamily, + pointLabelFontStyle : this.options.pointLabelFontStyle, + height : this.chart.height, + width: this.chart.width, + xCenter: this.chart.width/2, + yCenter: this.chart.height/2, + ctx : this.chart.ctx, + templateString: this.options.scaleLabel, + labels: data.labels, + valuesCount: data.datasets[0].data.length + }); + + this.scale.setScaleSize(); + this.updateScaleRange(data.datasets); + this.scale.buildYLabels(); + }, + updateScaleRange: function(datasets){ + var valuesArray = (function(){ + var totalDataArray = []; + helpers.each(datasets,function(dataset){ + if (dataset.data){ + totalDataArray = totalDataArray.concat(dataset.data); + } + else { + helpers.each(dataset.points, function(point){ + totalDataArray.push(point.value); + }); + } + }); + return totalDataArray; + })(); + + + var scaleSizes = (this.options.scaleOverride) ? + { + steps: this.options.scaleSteps, + stepValue: this.options.scaleStepWidth, + min: this.options.scaleStartValue, + max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) + } : + helpers.calculateScaleRange( + valuesArray, + helpers.min([this.chart.width, this.chart.height])/2, + this.options.scaleFontSize, + this.options.scaleBeginAtZero, + this.options.scaleIntegersOnly + ); + + helpers.extend( + this.scale, + scaleSizes + ); + + }, + addData : function(valuesArray,label){ + //Map the values array for each of the datasets + this.scale.valuesCount++; + helpers.each(valuesArray,function(value,datasetIndex){ + var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); + this.datasets[datasetIndex].points.push(new this.PointClass({ + value : value, + label : label, + x: pointPosition.x, + y: pointPosition.y, + strokeColor : this.datasets[datasetIndex].pointStrokeColor, + fillColor : this.datasets[datasetIndex].pointColor + })); + },this); + + this.scale.labels.push(label); + + this.reflow(); + + this.update(); + }, + removeData : function(){ + this.scale.valuesCount--; + this.scale.labels.shift(); + helpers.each(this.datasets,function(dataset){ + dataset.points.shift(); + },this); + this.reflow(); + this.update(); + }, + update : function(){ + this.eachPoints(function(point){ + point.save(); + }); + this.reflow(); + this.render(); + }, + reflow: function(){ + helpers.extend(this.scale, { + width : this.chart.width, + height: this.chart.height, + size : helpers.min([this.chart.width, this.chart.height]), + xCenter: this.chart.width/2, + yCenter: this.chart.height/2 + }); + this.updateScaleRange(this.datasets); + this.scale.setScaleSize(); + this.scale.buildYLabels(); + }, + draw : function(ease){ + var easeDecimal = ease || 1, + ctx = this.chart.ctx; + this.clear(); + this.scale.draw(); + + helpers.each(this.datasets,function(dataset){ + + //Transition each point first so that the line and point drawing isn't out of sync + helpers.each(dataset.points,function(point,index){ + if (point.hasValue()){ + point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); + } + },this); + + + + //Draw the line between all the points + ctx.lineWidth = this.options.datasetStrokeWidth; + ctx.strokeStyle = dataset.strokeColor; + ctx.beginPath(); + helpers.each(dataset.points,function(point,index){ + if (index === 0){ + ctx.moveTo(point.x,point.y); + } + else{ + ctx.lineTo(point.x,point.y); + } + },this); + ctx.closePath(); + ctx.stroke(); + + ctx.fillStyle = dataset.fillColor; + ctx.fill(); + + //Now draw the points over the line + //A little inefficient double looping, but better than the line + //lagging behind the point positions + helpers.each(dataset.points,function(point){ + if (point.hasValue()){ + point.draw(); + } + }); + + },this); + + } + + }); + + + + + +}).call(this); + })(); +}); + require.register("jquery/dist/jquery.js", function(exports, require, module) { require = __makeRelativeRequire(require, {}, "jquery"); (function() { @@ -13004,16 +16487,103 @@ process.umask = function() { return 0; }; require.register("web/static/js/dashboard.js", function(exports, require, module) { 'use strict'; +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + var _jquery = require('jquery'); var _jquery2 = _interopRequireDefault(_jquery); +var _chart = require('chart.js'); + +var _chart2 = _interopRequireDefault(_chart); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + window.jQuery = _jquery2.default; window.$ = _jquery2.default; require('bootstrap-sass'); require('admin-lte'); + +var App = function () { + function App() { + _classCallCheck(this, App); + } + + _createClass(App, [{ + key: 'render', + value: function render() { + this.renderRequestsChart(); + } + }, { + key: 'renderRequestsChart', + value: function renderRequestsChart() { + var areaChartCanvas = (0, _jquery2.default)('#areaChart').get(0).getContext('2d'); + var areaChart = new _chart2.default(areaChartCanvas); + + var areaChartData = { + labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [{ + label: 'Digital Goods', + fillColor: 'rgba(60,141,188,0.9)', + strokeColor: 'rgba(60,141,188,0.8)', + pointColor: '#3b8bba', + pointStrokeColor: 'rgba(60,141,188,1)', + pointHighlightFill: '#fff', + pointHighlightStroke: 'rgba(60,141,188,1)', + data: [28, 48, 40, 19, 86, 27, 90] + }] + }; + + var areaChartOptions = { + //Boolean - If we should show the scale at all + showScale: true, + //Boolean - Whether grid lines are shown across the chart + scaleShowGridLines: true, + //String - Colour of the grid lines + scaleGridLineColor: 'rgba(0,0,0,.05)', + //Number - Width of the grid lines + scaleGridLineWidth: 1, + //Boolean - Whether to show horizontal lines (except X axis) + scaleShowHorizontalLines: true, + //Boolean - Whether to show vertical lines (except Y axis) + scaleShowVerticalLines: true, + //Boolean - Whether the line is curved between points + bezierCurve: true, + //Number - Tension of the bezier curve between points + bezierCurveTension: 0.3, + //Boolean - Whether to show a dot for each point + pointDot: false, + //Number - Radius of each point dot in pixels + pointDotRadius: 4, + //Number - Pixel width of point dot stroke + pointDotStrokeWidth: 1, + //Number - amount extra to add to the radius to cater for hit detection outside the drawn point + pointHitDetectionRadius: 20, + //Boolean - Whether to show a stroke for datasets + datasetStroke: true, + //Number - Pixel width of dataset stroke + datasetStrokeWidth: 2, + //Boolean - Whether to fill the dataset with a color + datasetFill: true, + //String - A legend template + legendTemplate: '
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
', + //Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container + maintainAspectRatio: true, + //Boolean - whether to make the chart responsive to window resizing + responsive: true + }; + + //Create the line chart + areaChart.Line(areaChartData, areaChartOptions); + } + }]); + + return App; +}(); + +new App().render(); }); require.alias("admin-lte/dist/js/adminlte.min.js", "admin-lte"); @@ -13022,7 +16592,8 @@ require.alias("jquery/dist/jquery.js", "jquery"); require.alias("process/browser.js", "process"); require.alias("phoenix/priv/static/phoenix.js", "phoenix"); require.alias("prismjs/prism.js", "prismjs"); -require.alias("xterm/lib/xterm.js", "xterm");process = require('process');require.register("___globals___", function(exports, require, module) { +require.alias("xterm/lib/xterm.js", "xterm"); +require.alias("chart.js/Chart.js", "chart.js");process = require('process');require.register("___globals___", function(exports, require, module) { });})();require('___globals___'); diff --git a/web/controllers/dashboard_controller.ex b/web/controllers/dashboard_controller.ex index a0975ab..2a89166 100644 --- a/web/controllers/dashboard_controller.ex +++ b/web/controllers/dashboard_controller.ex @@ -6,6 +6,8 @@ defmodule ExDebugToolbar.DashboardController do plug :put_layout, {ExDebugToolbar.DashboardLayoutView, :app} def show(conn, _) do - conn |> render("show.html") + conn + |> assign(:requests, ExDebugToolbar.get_all_requests()) + |> render("show.html") end end diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index f06a6b6..5f3224d 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -3,3 +3,75 @@ window.jQuery = $; window.$ = $; require('bootstrap-sass'); require('admin-lte'); +import Chart from 'chart.js'; + +class App { + render() { + this.renderRequestsChart(); + } + + renderRequestsChart() { + const areaChartCanvas = $('#areaChart').get(0).getContext('2d'); + const areaChart = new Chart(areaChartCanvas); + + const areaChartData = { + labels : ['January', 'February', 'March', 'April', 'May', 'June', 'July'], + datasets: [ + { + label : 'Digital Goods', + fillColor : 'rgba(60,141,188,0.9)', + strokeColor : 'rgba(60,141,188,0.8)', + pointColor : '#3b8bba', + pointStrokeColor : 'rgba(60,141,188,1)', + pointHighlightFill : '#fff', + pointHighlightStroke: 'rgba(60,141,188,1)', + data : [28, 48, 40, 19, 86, 27, 90] + } + ] + } + + const areaChartOptions = { + //Boolean - If we should show the scale at all + showScale : true, + //Boolean - Whether grid lines are shown across the chart + scaleShowGridLines : true, + //String - Colour of the grid lines + scaleGridLineColor : 'rgba(0,0,0,.05)', + //Number - Width of the grid lines + scaleGridLineWidth : 1, + //Boolean - Whether to show horizontal lines (except X axis) + scaleShowHorizontalLines: true, + //Boolean - Whether to show vertical lines (except Y axis) + scaleShowVerticalLines : true, + //Boolean - Whether the line is curved between points + bezierCurve : true, + //Number - Tension of the bezier curve between points + bezierCurveTension : 0.3, + //Boolean - Whether to show a dot for each point + pointDot : false, + //Number - Radius of each point dot in pixels + pointDotRadius : 4, + //Number - Pixel width of point dot stroke + pointDotStrokeWidth : 1, + //Number - amount extra to add to the radius to cater for hit detection outside the drawn point + pointHitDetectionRadius : 20, + //Boolean - Whether to show a stroke for datasets + datasetStroke : true, + //Number - Pixel width of dataset stroke + datasetStrokeWidth : 2, + //Boolean - Whether to fill the dataset with a color + datasetFill : true, + //String - A legend template + legendTemplate : '
    <% for (var i=0; i
  • <%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
', + //Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container + maintainAspectRatio : true, + //Boolean - whether to make the chart responsive to window resizing + responsive : true + } + + //Create the line chart + areaChart.Line(areaChartData, areaChartOptions) + } +} + +(new App()).render(); diff --git a/web/templates/dashboard/show.html.eex b/web/templates/dashboard/show.html.eex index 4cd2b39..5384eac 100644 --- a/web/templates/dashboard/show.html.eex +++ b/web/templates/dashboard/show.html.eex @@ -1 +1,115 @@ -I am dashboard! +
+
+ + +
+ Requests + <%= length(@requests) %> +
+
+
+
+
+ + +
+ Logs + <%= count_logs(@requests) %> +
+
+
+
+
+ + +
+ Database + <%= count_ecto_queries(@requests) %> +
+
+
+
+
+ + +
+ Breakpoints + <%= count_breakpoints(@requests) %> +
+
+
+ +
+
+
+

Area Chart

+ +
+ +
+
+
+
+ +
+
+
+
+ + +
+
+
+

Responsive Hover Table

+ +
+
+ + +
+ +
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IDUserDateStatusReason
183John Doe11-7-2014ApprovedBacon ipsum dolor sit amet salami venison chicken flank fatback doner.
219Alexander Pierce11-7-2014PendingBacon ipsum dolor sit amet salami venison chicken flank fatback doner.
657Bob Doe11-7-2014ApprovedBacon ipsum dolor sit amet salami venison chicken flank fatback doner.
175Mike Doe11-7-2014DeniedBacon ipsum dolor sit amet salami venison chicken flank fatback doner.
+
+
+
diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index b543bbc..1fa66d4 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -96,7 +96,9 @@
- <%= render @view_module, @view_template, assigns %> +
+ <%= render @view_module, @view_template, assigns %> +
diff --git a/web/views/dashboard_view.ex b/web/views/dashboard_view.ex index 93c99aa..2105a19 100644 --- a/web/views/dashboard_view.ex +++ b/web/views/dashboard_view.ex @@ -6,4 +6,25 @@ defmodule ExDebugToolbar.DashboardView do def header(_), do: "Requests" def description(_), do: "Overview of all recorded requests" + + def count_logs(requests) do + requests + |> Stream.map(&(&1.logs)) + |> Stream.map(&length/1) + |> Enum.sum + end + + def count_ecto_queries(requests) do + requests + |> Stream.map(&(&1.ecto)) + |> Stream.map(&length/1) + |> Enum.sum + end + + def count_breakpoints(requests) do + requests + |> Stream.map(&(&1.breakpoints)) + |> Stream.map(&(&1.count)) + |> Enum.sum + end end From 4c02757efc215217f154ff5cde36a15042dd5d39 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 11 Oct 2017 09:43:02 +0200 Subject: [PATCH 13/55] wip chart --- package.json | 1 + priv/static/css/dashboard.css | 3 + priv/static/js/dashboard.js | 37496 +++++++++++++++++------- priv/static/js/toolbar.js | 9 +- web/static/css/dashboard.scss | 4 + web/static/js/dashboard.js | 105 +- web/templates/dashboard/show.html.eex | 9 +- web/views/dashboard_view.ex | 28 + yarn.lock | 30 +- 9 files changed, 26483 insertions(+), 11202 deletions(-) diff --git a/package.json b/package.json index 3c9fe01..8a9a741 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "dependencies": { "admin-lte": "^2.4.0", "bootstrap-sass": "^3.3.7", + "chart.js": "^2.7.0", "copycat-brunch": "^1.1.0", "css-reset-and-normalize-sass": "^0.1.2", "google-fonts-offline": "^0.1.2", diff --git a/priv/static/css/dashboard.css b/priv/static/css/dashboard.css index 3ea71f9..b7474a2 100644 --- a/priv/static/css/dashboard.css +++ b/priv/static/css/dashboard.css @@ -13245,5 +13245,8 @@ table.text-center th { border-bottom-right-radius: 2px; border-bottom-left-radius: 0; } +#requests-chart { + max-height: 300px; } + /*# sourceMappingURL=dashboard.css.map*/ \ No newline at end of file diff --git a/priv/static/js/dashboard.js b/priv/static/js/dashboard.js index a698b15..519c8ac 100644 --- a/priv/static/js/dashboard.js +++ b/priv/static/js/dashboard.js @@ -2553,13745 +2553,28974 @@ if (typeof jQuery === 'undefined') { })(); }); -require.register("chart.js/Chart.js", function(exports, require, module) { +require.register("chart.js/src/chart.js", function(exports, require, module) { require = __makeRelativeRequire(require, {}, "chart.js"); (function() { - /*! - * Chart.js - * http://chartjs.org/ - * Version: 1.0.2 - * - * Copyright 2015 Nick Downie - * Released under the MIT license - * https://github.com/nnnick/Chart.js/blob/master/LICENSE.md + /** + * @namespace Chart */ +var Chart = require('./core/core')(); + +Chart.helpers = require('./helpers/index'); + +// @todo dispatch these helpers into appropriated helpers/helpers.* file and write unit tests! +require('./core/core.helpers')(Chart); + +Chart.defaults = require('./core/core.defaults'); +Chart.Element = require('./core/core.element'); +Chart.elements = require('./elements/index'); +Chart.Interaction = require('./core/core.interaction'); +Chart.platform = require('./platforms/platform'); + +require('./core/core.plugin')(Chart); +require('./core/core.animation')(Chart); +require('./core/core.controller')(Chart); +require('./core/core.datasetController')(Chart); +require('./core/core.layoutService')(Chart); +require('./core/core.scaleService')(Chart); +require('./core/core.scale')(Chart); +require('./core/core.tooltip')(Chart); + +require('./scales/scale.linearbase')(Chart); +require('./scales/scale.category')(Chart); +require('./scales/scale.linear')(Chart); +require('./scales/scale.logarithmic')(Chart); +require('./scales/scale.radialLinear')(Chart); +require('./scales/scale.time')(Chart); + +// Controllers must be loaded after elements +// See Chart.core.datasetController.dataElementType +require('./controllers/controller.bar')(Chart); +require('./controllers/controller.bubble')(Chart); +require('./controllers/controller.doughnut')(Chart); +require('./controllers/controller.line')(Chart); +require('./controllers/controller.polarArea')(Chart); +require('./controllers/controller.radar')(Chart); +require('./controllers/controller.scatter')(Chart); + +require('./charts/Chart.Bar')(Chart); +require('./charts/Chart.Bubble')(Chart); +require('./charts/Chart.Doughnut')(Chart); +require('./charts/Chart.Line')(Chart); +require('./charts/Chart.PolarArea')(Chart); +require('./charts/Chart.Radar')(Chart); +require('./charts/Chart.Scatter')(Chart); + +// Loading built-it plugins +var plugins = []; + +plugins.push( + require('./plugins/plugin.filler')(Chart), + require('./plugins/plugin.legend')(Chart), + require('./plugins/plugin.title')(Chart) +); +Chart.plugins.register(plugins); -(function(){ +Chart.platform.initialize(); - "use strict"; +module.exports = Chart; +if (typeof window !== 'undefined') { + window.Chart = Chart; +} - //Declare root variable - window in the browser, global on the server - var root = this, - previous = root.Chart; +// DEPRECATIONS - //Occupy the global variable of Chart, and create a simple base class - var Chart = function(context){ - var chart = this; - this.canvas = context.canvas; +/** + * Provided for backward compatibility, use Chart.helpers.canvas instead. + * @namespace Chart.canvasHelpers + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +Chart.canvasHelpers = Chart.helpers.canvas; + })(); +}); - this.ctx = context; +require.register("chart.js/src/charts/Chart.Bar.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - //Variables global to the chart - var computeDimension = function(element,dimension) - { - if (element['offset'+dimension]) - { - return element['offset'+dimension]; - } - else - { - return document.defaultView.getComputedStyle(element).getPropertyValue(dimension); - } - } +module.exports = function(Chart) { - var width = this.width = computeDimension(context.canvas,'Width'); - var height = this.height = computeDimension(context.canvas,'Height'); + Chart.Bar = function(context, config) { + config.type = 'bar'; - // Firefox requires this to work correctly - context.canvas.width = width; - context.canvas.height = height; + return new Chart(context, config); + }; - var width = this.width = context.canvas.width; - var height = this.height = context.canvas.height; - this.aspectRatio = this.width / this.height; - //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale. - helpers.retinaScale(this); +}; + })(); +}); - return this; - }; - //Globally expose the defaults to allow for user updating/changing - Chart.defaults = { - global: { - // Boolean - Whether to animate the chart - animation: true, +require.register("chart.js/src/charts/Chart.Bubble.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Number - Number of animation steps - animationSteps: 60, +module.exports = function(Chart) { - // String - Animation easing effect - animationEasing: "easeOutQuart", + Chart.Bubble = function(context, config) { + config.type = 'bubble'; + return new Chart(context, config); + }; - // Boolean - If we should show the scale at all - showScale: true, +}; + })(); +}); - // Boolean - If we want to override with a hard coded scale - scaleOverride: false, +require.register("chart.js/src/charts/Chart.Doughnut.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // ** Required if scaleOverride is true ** - // Number - The number of steps in a hard coded scale - scaleSteps: null, - // Number - The value jump in the hard coded scale - scaleStepWidth: null, - // Number - The scale starting value - scaleStartValue: null, +module.exports = function(Chart) { - // String - Colour of the scale line - scaleLineColor: "rgba(0,0,0,.1)", + Chart.Doughnut = function(context, config) { + config.type = 'doughnut'; - // Number - Pixel width of the scale line - scaleLineWidth: 1, + return new Chart(context, config); + }; - // Boolean - Whether to show labels on the scale - scaleShowLabels: true, +}; + })(); +}); - // Interpolated JS string - can access value - scaleLabel: "<%=value%>", +require.register("chart.js/src/charts/Chart.Line.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there - scaleIntegersOnly: true, +module.exports = function(Chart) { - // Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value - scaleBeginAtZero: false, + Chart.Line = function(context, config) { + config.type = 'line'; - // String - Scale label font declaration for the scale label - scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + return new Chart(context, config); + }; - // Number - Scale label font size in pixels - scaleFontSize: 12, +}; + })(); +}); - // String - Scale label font weight style - scaleFontStyle: "normal", +require.register("chart.js/src/charts/Chart.PolarArea.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // String - Scale label font colour - scaleFontColor: "#666", +module.exports = function(Chart) { - // Boolean - whether or not the chart should be responsive and resize when the browser does. - responsive: false, + Chart.PolarArea = function(context, config) { + config.type = 'polarArea'; - // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container - maintainAspectRatio: true, + return new Chart(context, config); + }; - // Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove - showTooltips: true, +}; + })(); +}); - // Boolean - Determines whether to draw built-in tooltip or call custom tooltip function - customTooltips: false, +require.register("chart.js/src/charts/Chart.Radar.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Array - Array of string names to attach tooltip events - tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"], +module.exports = function(Chart) { - // String - Tooltip background colour - tooltipFillColor: "rgba(0,0,0,0.8)", + Chart.Radar = function(context, config) { + config.type = 'radar'; - // String - Tooltip label font declaration for the scale label - tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + return new Chart(context, config); + }; - // Number - Tooltip label font size in pixels - tooltipFontSize: 14, +}; + })(); +}); - // String - Tooltip font weight style - tooltipFontStyle: "normal", +require.register("chart.js/src/charts/Chart.Scatter.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // String - Tooltip label font colour - tooltipFontColor: "#fff", +module.exports = function(Chart) { + Chart.Scatter = function(context, config) { + config.type = 'scatter'; + return new Chart(context, config); + }; +}; + })(); +}); - // String - Tooltip title font declaration for the scale label - tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", +require.register("chart.js/src/controllers/controller.bar.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Number - Tooltip title font size in pixels - tooltipTitleFontSize: 14, +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - // String - Tooltip title font weight style - tooltipTitleFontStyle: "bold", +defaults._set('bar', { + hover: { + mode: 'label' + }, - // String - Tooltip title font colour - tooltipTitleFontColor: "#fff", + scales: { + xAxes: [{ + type: 'category', - // Number - pixel width of padding around tooltip text - tooltipYPadding: 6, + // Specific to Bar Controller + categoryPercentage: 0.8, + barPercentage: 0.9, - // Number - pixel width of padding around tooltip text - tooltipXPadding: 6, + // offset settings + offset: true, - // Number - Size of the caret on the tooltip - tooltipCaretSize: 8, + // grid line settings + gridLines: { + offsetGridLines: true + } + }], - // Number - Pixel radius of the tooltip border - tooltipCornerRadius: 6, + yAxes: [{ + type: 'linear' + }] + } +}); - // Number - Pixel offset from point x to tooltip edge - tooltipXOffset: 10, +defaults._set('horizontalBar', { + hover: { + mode: 'index', + axis: 'y' + }, - // String - Template string for single tooltips - tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>", + scales: { + xAxes: [{ + type: 'linear', + position: 'bottom' + }], - // String - Template string for single tooltips - multiTooltipTemplate: "<%= value %>", + yAxes: [{ + position: 'left', + type: 'category', - // String - Colour behind the legend colour block - multiTooltipKeyBackground: '#fff', + // Specific to Horizontal Bar Controller + categoryPercentage: 0.8, + barPercentage: 0.9, - // Function - Will fire on animation progression. - onAnimationProgress: function(){}, + // offset settings + offset: true, - // Function - Will fire on animation completion. - onAnimationComplete: function(){} + // grid line settings + gridLines: { + offsetGridLines: true + } + }] + }, + elements: { + rectangle: { + borderSkipped: 'left' } - }; - - //Create a dictionary of chart types, to allow for extension of existing types - Chart.types = {}; + }, - //Global Chart helpers object for utility methods and classes - var helpers = Chart.helpers = {}; - - //-- Basic js utility methods - var each = helpers.each = function(loopable,callback,self){ - var additionalArgs = Array.prototype.slice.call(arguments, 3); - // Check to see if null or undefined firstly. - if (loopable){ - if (loopable.length === +loopable.length){ - var i; - for (i=0; i 0) { + if (item[0].yLabel) { + title = item[0].yLabel; + } else if (data.labels.length > 0 && item[0].index < data.labels.length) { + title = data.labels[item[0].index]; } } - else{ - for (var item in loopable){ - callback.apply(self,[loopable[item],item].concat(additionalArgs)); - } - } - } - }, - clone = helpers.clone = function(obj){ - var objClone = {}; - each(obj,function(value,key){ - if (obj.hasOwnProperty(key)) objClone[key] = value; - }); - return objClone; - }, - extend = helpers.extend = function(base){ - each(Array.prototype.slice.call(arguments,1), function(extensionObject) { - each(extensionObject,function(value,key){ - if (extensionObject.hasOwnProperty(key)) base[key] = value; - }); - }); - return base; - }, - merge = helpers.merge = function(base,master){ - //Merge properties in left object over to a shallow clone of object right. - var args = Array.prototype.slice.call(arguments,0); - args.unshift({}); - return extend.apply(null, args); - }, - indexOf = helpers.indexOf = function(arrayToSearch, item){ - if (Array.prototype.indexOf) { - return arrayToSearch.indexOf(item); - } - else{ - for (var i = 0; i < arrayToSearch.length; i++) { - if (arrayToSearch[i] === item) return i; - } - return -1; + + return title; + }, + + label: function(item, data) { + var datasetLabel = data.datasets[item.datasetIndex].label || ''; + return datasetLabel + ': ' + item.xLabel; } }, - where = helpers.where = function(collection, filterCallback){ - var filtered = []; + mode: 'index', + axis: 'y' + } +}); - helpers.each(collection, function(item){ - if (filterCallback(item)){ - filtered.push(item); - } - }); +module.exports = function(Chart) { - return filtered; - }, - findNextWhere = helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex){ - // Default to start of the array - if (!startIndex){ - startIndex = -1; - } - for (var i = startIndex + 1; i < arrayToSearch.length; i++) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)){ - return currentItem; - } - } + Chart.controllers.bar = Chart.DatasetController.extend({ + + dataElementType: elements.Rectangle, + + initialize: function() { + var me = this; + var meta; + + Chart.DatasetController.prototype.initialize.apply(me, arguments); + + meta = me.getMeta(); + meta.stack = me.getDataset().stack; + meta.bar = true; }, - findPreviousWhere = helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex){ - // Default to end of the array - if (!startIndex){ - startIndex = arrayToSearch.length; - } - for (var i = startIndex - 1; i >= 0; i--) { - var currentItem = arrayToSearch[i]; - if (filterCallback(currentItem)){ - return currentItem; - } + + update: function(reset) { + var me = this; + var rects = me.getMeta().data; + var i, ilen; + + me._ruler = me.getRuler(); + + for (i = 0, ilen = rects.length; i < ilen; ++i) { + me.updateElement(rects[i], i, reset); } }, - inherits = helpers.inherits = function(extensions){ - //Basic javascript inheritance based on the model created in Backbone.js - var parent = this; - var ChartElement = (extensions && extensions.hasOwnProperty("constructor")) ? extensions.constructor : function(){ return parent.apply(this, arguments); }; - - var Surrogate = function(){ this.constructor = ChartElement;}; - Surrogate.prototype = parent.prototype; - ChartElement.prototype = new Surrogate(); - ChartElement.extend = inherits; + updateElement: function(rectangle, index, reset) { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var dataset = me.getDataset(); + var custom = rectangle.custom || {}; + var rectangleOptions = chart.options.elements.rectangle; + + rectangle._xScale = me.getScaleForId(meta.xAxisID); + rectangle._yScale = me.getScaleForId(meta.yAxisID); + rectangle._datasetIndex = me.index; + rectangle._index = index; + + rectangle._model = { + datasetLabel: dataset.label, + label: chart.data.labels[index], + borderSkipped: custom.borderSkipped ? custom.borderSkipped : rectangleOptions.borderSkipped, + backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleOptions.backgroundColor), + borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleOptions.borderColor), + borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleOptions.borderWidth) + }; - if (extensions) extend(ChartElement.prototype, extensions); + me.updateElementGeometry(rectangle, index, reset); - ChartElement.__super__ = parent.prototype; + rectangle.pivot(); + }, - return ChartElement; + /** + * @private + */ + updateElementGeometry: function(rectangle, index, reset) { + var me = this; + var model = rectangle._model; + var vscale = me.getValueScale(); + var base = vscale.getBasePixel(); + var horizontal = vscale.isHorizontal(); + var ruler = me._ruler || me.getRuler(); + var vpixels = me.calculateBarValuePixels(me.index, index); + var ipixels = me.calculateBarIndexPixels(me.index, index, ruler); + + model.horizontal = horizontal; + model.base = reset ? base : vpixels.base; + model.x = horizontal ? reset ? base : vpixels.head : ipixels.center; + model.y = horizontal ? ipixels.center : reset ? base : vpixels.head; + model.height = horizontal ? ipixels.size : undefined; + model.width = horizontal ? undefined : ipixels.size; }, - noop = helpers.noop = function(){}, - uid = helpers.uid = (function(){ - var id=0; - return function(){ - return "chart-" + id++; - }; - })(), - warn = helpers.warn = function(str){ - //Method for warning of errors - if (window.console && typeof window.console.warn == "function") console.warn(str); + + /** + * @private + */ + getValueScaleId: function() { + return this.getMeta().yAxisID; }, - amd = helpers.amd = (typeof define == 'function' && define.amd), - //-- Math methods - isNumber = helpers.isNumber = function(n){ - return !isNaN(parseFloat(n)) && isFinite(n); + + /** + * @private + */ + getIndexScaleId: function() { + return this.getMeta().xAxisID; }, - max = helpers.max = function(array){ - return Math.max.apply( Math, array ); + + /** + * @private + */ + getValueScale: function() { + return this.getScaleForId(this.getValueScaleId()); }, - min = helpers.min = function(array){ - return Math.min.apply( Math, array ); + + /** + * @private + */ + getIndexScale: function() { + return this.getScaleForId(this.getIndexScaleId()); }, - cap = helpers.cap = function(valueToCap,maxValue,minValue){ - if(isNumber(maxValue)) { - if( valueToCap > maxValue ) { - return maxValue; - } - } - else if(isNumber(minValue)){ - if ( valueToCap < minValue ){ - return minValue; + + /** + * Returns the effective number of stacks based on groups and bar visibility. + * @private + */ + getStackCount: function(last) { + var me = this; + var chart = me.chart; + var scale = me.getIndexScale(); + var stacked = scale.options.stacked; + var ilen = last === undefined ? chart.data.datasets.length : last + 1; + var stacks = []; + var i, meta; + + for (i = 0; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + if (meta.bar && chart.isDatasetVisible(i) && + (stacked === false || + (stacked === true && stacks.indexOf(meta.stack) === -1) || + (stacked === undefined && (meta.stack === undefined || stacks.indexOf(meta.stack) === -1)))) { + stacks.push(meta.stack); } } - return valueToCap; - }, - getDecimalPlaces = helpers.getDecimalPlaces = function(num){ - if (num%1!==0 && isNumber(num)){ - return num.toString().split(".")[1].length; - } - else { - return 0; - } - }, - toRadians = helpers.radians = function(degrees){ - return degrees * (Math.PI/180); + + return stacks.length; }, - // Gets the angle from vertical upright to the point about a centre. - getAngleFromPoint = helpers.getAngleFromPoint = function(centrePoint, anglePoint){ - var distanceFromXCenter = anglePoint.x - centrePoint.x, - distanceFromYCenter = anglePoint.y - centrePoint.y, - radialDistanceFromCenter = Math.sqrt( distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); + /** + * Returns the stack index for the given dataset based on groups and bar visibility. + * @private + */ + getStackIndex: function(datasetIndex) { + return this.getStackCount(datasetIndex) - 1; + }, - var angle = Math.PI * 2 + Math.atan2(distanceFromYCenter, distanceFromXCenter); + /** + * @private + */ + getRuler: function() { + var me = this; + var scale = me.getIndexScale(); + var stackCount = me.getStackCount(); + var datasetIndex = me.index; + var pixels = []; + var isHorizontal = scale.isHorizontal(); + var start = isHorizontal ? scale.left : scale.top; + var end = start + (isHorizontal ? scale.width : scale.height); + var i, ilen; - //If the segment is in the top left quadrant, we need to add another rotation to the angle - if (distanceFromXCenter < 0 && distanceFromYCenter < 0){ - angle += Math.PI*2; + for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) { + pixels.push(scale.getPixelForValue(null, i, datasetIndex)); } return { - angle: angle, - distance: radialDistanceFromCenter - }; - }, - aliasPixel = helpers.aliasPixel = function(pixelWidth){ - return (pixelWidth % 2 === 0) ? 0 : 0.5; - }, - splineCurve = helpers.splineCurve = function(FirstPoint,MiddlePoint,AfterPoint,t){ - //Props to Rob Spencer at scaled innovation for his post on splining between points - //http://scaledinnovation.com/analytics/splines/aboutSplines.html - var d01=Math.sqrt(Math.pow(MiddlePoint.x-FirstPoint.x,2)+Math.pow(MiddlePoint.y-FirstPoint.y,2)), - d12=Math.sqrt(Math.pow(AfterPoint.x-MiddlePoint.x,2)+Math.pow(AfterPoint.y-MiddlePoint.y,2)), - fa=t*d01/(d01+d12),// scaling factor for triangle Ta - fb=t*d12/(d01+d12); - return { - inner : { - x : MiddlePoint.x-fa*(AfterPoint.x-FirstPoint.x), - y : MiddlePoint.y-fa*(AfterPoint.y-FirstPoint.y) - }, - outer : { - x: MiddlePoint.x+fb*(AfterPoint.x-FirstPoint.x), - y : MiddlePoint.y+fb*(AfterPoint.y-FirstPoint.y) - } + pixels: pixels, + start: start, + end: end, + stackCount: stackCount, + scale: scale }; }, - calculateOrderOfMagnitude = helpers.calculateOrderOfMagnitude = function(val){ - return Math.floor(Math.log(val) / Math.LN10); - }, - calculateScaleRange = helpers.calculateScaleRange = function(valuesArray, drawingSize, textSize, startFromZero, integersOnly){ - - //Set a minimum step of two - a point at the top of the graph, and a point at the base - var minSteps = 2, - maxSteps = Math.floor(drawingSize/(textSize * 1.5)), - skipFitting = (minSteps >= maxSteps); - - var maxValue = max(valuesArray), - minValue = min(valuesArray); - - // We need some degree of seperation here to calculate the scales if all the values are the same - // Adding/minusing 0.5 will give us a range of 1. - if (maxValue === minValue){ - maxValue += 0.5; - // So we don't end up with a graph with a negative start value if we've said always start from zero - if (minValue >= 0.5 && !startFromZero){ - minValue -= 0.5; - } - else{ - // Make up a whole number above the values - maxValue += 0.5; - } - } - - var valueRange = Math.abs(maxValue - minValue), - rangeOrderOfMagnitude = calculateOrderOfMagnitude(valueRange), - graphMax = Math.ceil(maxValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude), - graphMin = (startFromZero) ? 0 : Math.floor(minValue / (1 * Math.pow(10, rangeOrderOfMagnitude))) * Math.pow(10, rangeOrderOfMagnitude), - graphRange = graphMax - graphMin, - stepValue = Math.pow(10, rangeOrderOfMagnitude), - numberOfSteps = Math.round(graphRange / stepValue); - - //If we have more space on the graph we'll use it to give more definition to the data - while((numberOfSteps > maxSteps || (numberOfSteps * 2) < maxSteps) && !skipFitting) { - if(numberOfSteps > maxSteps){ - stepValue *=2; - numberOfSteps = Math.round(graphRange/stepValue); - // Don't ever deal with a decimal number of steps - cancel fitting and just use the minimum number of steps. - if (numberOfSteps % 1 !== 0){ - skipFitting = true; - } - } - //We can fit in double the amount of scale points on the scale - else{ - //If user has declared ints only, and the step value isn't a decimal - if (integersOnly && rangeOrderOfMagnitude >= 0){ - //If the user has said integers only, we need to check that making the scale more granular wouldn't make it a float - if(stepValue/2 % 1 === 0){ - stepValue /=2; - numberOfSteps = Math.round(graphRange/stepValue); - } - //If it would make it a float break out of the loop - else{ - break; + + /** + * Note: pixel values are not clamped to the scale area. + * @private + */ + calculateBarValuePixels: function(datasetIndex, index) { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var scale = me.getValueScale(); + var datasets = chart.data.datasets; + var value = scale.getRightValue(datasets[datasetIndex].data[index]); + var stacked = scale.options.stacked; + var stack = meta.stack; + var start = 0; + var i, imeta, ivalue, base, head, size; + + if (stacked || (stacked === undefined && stack !== undefined)) { + for (i = 0; i < datasetIndex; ++i) { + imeta = chart.getDatasetMeta(i); + + if (imeta.bar && + imeta.stack === stack && + imeta.controller.getValueScaleId() === scale.id && + chart.isDatasetVisible(i)) { + + ivalue = scale.getRightValue(datasets[i].data[index]); + if ((value < 0 && ivalue < 0) || (value >= 0 && ivalue > 0)) { + start += ivalue; } } - //If the scale doesn't have to be an int, make the scale more granular anyway. - else{ - stepValue /=2; - numberOfSteps = Math.round(graphRange/stepValue); - } - } } - if (skipFitting){ - numberOfSteps = minSteps; - stepValue = graphRange / numberOfSteps; - } + base = scale.getPixelForValue(start); + head = scale.getPixelForValue(start + value); + size = (head - base) / 2; return { - steps : numberOfSteps, - stepValue : stepValue, - min : graphMin, - max : graphMin + (numberOfSteps * stepValue) + size: size, + base: base, + head: head, + center: head + size / 2 }; - }, - /* jshint ignore:start */ - // Blows up jshint errors based on the new Function constructor - //Templating methods - //Javascript micro templating by John Resig - source at http://ejohn.org/blog/javascript-micro-templating/ - template = helpers.template = function(templateString, valuesObject){ - - // If templateString is function rather than string-template - call the function for valuesObject - - if(templateString instanceof Function){ - return templateString(valuesObject); - } - - var cache = {}; - function tmpl(str, data){ - // Figure out if we're getting a template, or if we need to - // load the template - and be sure to cache the result. - var fn = !/\W/.test(str) ? - cache[str] = cache[str] : - - // Generate a reusable function that will serve as a template - // generator (and which will be cached). - new Function("obj", - "var p=[],print=function(){p.push.apply(p,arguments);};" + - - // Introduce the data as local variables using with(){} - "with(obj){p.push('" + - - // Convert the template into pure JavaScript - str - .replace(/[\r\t\n]/g, " ") - .split("<%").join("\t") - .replace(/((^|%>)[^\t]*)'/g, "$1\r") - .replace(/\t=(.*?)%>/g, "',$1,'") - .split("\t").join("');") - .split("%>").join("p.push('") - .split("\r").join("\\'") + - "');}return p.join('');" - ); - // Provide some basic currying to the user - return data ? fn( data ) : fn; - } - return tmpl(templateString,valuesObject); - }, - /* jshint ignore:end */ - generateLabels = helpers.generateLabels = function(templateString,numberOfSteps,graphMin,stepValue){ - var labelsArray = new Array(numberOfSteps); - if (labelTemplateString){ - each(labelsArray,function(val,index){ - labelsArray[index] = template(templateString,{value: (graphMin + (stepValue*(index+1)))}); - }); - } - return labelsArray; - }, - //--Animation methods - //Easing functions adapted from Robert Penner's easing equations - //http://www.robertpenner.com/easing/ - easingEffects = helpers.easingEffects = { - linear: function (t) { - return t; - }, - easeInQuad: function (t) { - return t * t; - }, - easeOutQuad: function (t) { - return -1 * t * (t - 2); - }, - easeInOutQuad: function (t) { - if ((t /= 1 / 2) < 1) return 1 / 2 * t * t; - return -1 / 2 * ((--t) * (t - 2) - 1); - }, - easeInCubic: function (t) { - return t * t * t; - }, - easeOutCubic: function (t) { - return 1 * ((t = t / 1 - 1) * t * t + 1); - }, - easeInOutCubic: function (t) { - if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t; - return 1 / 2 * ((t -= 2) * t * t + 2); - }, - easeInQuart: function (t) { - return t * t * t * t; - }, - easeOutQuart: function (t) { - return -1 * ((t = t / 1 - 1) * t * t * t - 1); - }, - easeInOutQuart: function (t) { - if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t; - return -1 / 2 * ((t -= 2) * t * t * t - 2); - }, - easeInQuint: function (t) { - return 1 * (t /= 1) * t * t * t * t; - }, - easeOutQuint: function (t) { - return 1 * ((t = t / 1 - 1) * t * t * t * t + 1); - }, - easeInOutQuint: function (t) { - if ((t /= 1 / 2) < 1) return 1 / 2 * t * t * t * t * t; - return 1 / 2 * ((t -= 2) * t * t * t * t + 2); - }, - easeInSine: function (t) { - return -1 * Math.cos(t / 1 * (Math.PI / 2)) + 1; - }, - easeOutSine: function (t) { - return 1 * Math.sin(t / 1 * (Math.PI / 2)); - }, - easeInOutSine: function (t) { - return -1 / 2 * (Math.cos(Math.PI * t / 1) - 1); - }, - easeInExpo: function (t) { - return (t === 0) ? 1 : 1 * Math.pow(2, 10 * (t / 1 - 1)); - }, - easeOutExpo: function (t) { - return (t === 1) ? 1 : 1 * (-Math.pow(2, -10 * t / 1) + 1); - }, - easeInOutExpo: function (t) { - if (t === 0) return 0; - if (t === 1) return 1; - if ((t /= 1 / 2) < 1) return 1 / 2 * Math.pow(2, 10 * (t - 1)); - return 1 / 2 * (-Math.pow(2, -10 * --t) + 2); - }, - easeInCirc: function (t) { - if (t >= 1) return t; - return -1 * (Math.sqrt(1 - (t /= 1) * t) - 1); - }, - easeOutCirc: function (t) { - return 1 * Math.sqrt(1 - (t = t / 1 - 1) * t); - }, - easeInOutCirc: function (t) { - if ((t /= 1 / 2) < 1) return -1 / 2 * (Math.sqrt(1 - t * t) - 1); - return 1 / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1); - }, - easeInElastic: function (t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) return 0; - if ((t /= 1) == 1) return 1; - if (!p) p = 1 * 0.3; - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else s = p / (2 * Math.PI) * Math.asin(1 / a); - return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - }, - easeOutElastic: function (t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) return 0; - if ((t /= 1) == 1) return 1; - if (!p) p = 1 * 0.3; - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else s = p / (2 * Math.PI) * Math.asin(1 / a); - return a * Math.pow(2, -10 * t) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) + 1; - }, - easeInOutElastic: function (t) { - var s = 1.70158; - var p = 0; - var a = 1; - if (t === 0) return 0; - if ((t /= 1 / 2) == 2) return 1; - if (!p) p = 1 * (0.3 * 1.5); - if (a < Math.abs(1)) { - a = 1; - s = p / 4; - } else s = p / (2 * Math.PI) * Math.asin(1 / a); - if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p)); - return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * 1 - s) * (2 * Math.PI) / p) * 0.5 + 1; - }, - easeInBack: function (t) { - var s = 1.70158; - return 1 * (t /= 1) * t * ((s + 1) * t - s); - }, - easeOutBack: function (t) { - var s = 1.70158; - return 1 * ((t = t / 1 - 1) * t * ((s + 1) * t + s) + 1); - }, - easeInOutBack: function (t) { - var s = 1.70158; - if ((t /= 1 / 2) < 1) return 1 / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)); - return 1 / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); - }, - easeInBounce: function (t) { - return 1 - easingEffects.easeOutBounce(1 - t); - }, - easeOutBounce: function (t) { - if ((t /= 1) < (1 / 2.75)) { - return 1 * (7.5625 * t * t); - } else if (t < (2 / 2.75)) { - return 1 * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75); - } else if (t < (2.5 / 2.75)) { - return 1 * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375); - } else { - return 1 * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375); + /** + * @private + */ + calculateBarIndexPixels: function(datasetIndex, index, ruler) { + var me = this; + var options = ruler.scale.options; + var stackIndex = me.getStackIndex(datasetIndex); + var pixels = ruler.pixels; + var base = pixels[index]; + var length = pixels.length; + var start = ruler.start; + var end = ruler.end; + var leftSampleSize, rightSampleSize, leftCategorySize, rightCategorySize, fullBarSize, size; + + if (length === 1) { + leftSampleSize = base > start ? base - start : end - base; + rightSampleSize = base < end ? end - base : base - start; + } else { + if (index > 0) { + leftSampleSize = (base - pixels[index - 1]) / 2; + if (index === length - 1) { + rightSampleSize = leftSampleSize; + } } - }, - easeInOutBounce: function (t) { - if (t < 1 / 2) return easingEffects.easeInBounce(t * 2) * 0.5; - return easingEffects.easeOutBounce(t * 2 - 1) * 0.5 + 1 * 0.5; - } - }, - //Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ - requestAnimFrame = helpers.requestAnimFrame = (function(){ - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - window.oRequestAnimationFrame || - window.msRequestAnimationFrame || - function(callback) { - return window.setTimeout(callback, 1000 / 60); - }; - })(), - cancelAnimFrame = helpers.cancelAnimFrame = (function(){ - return window.cancelAnimationFrame || - window.webkitCancelAnimationFrame || - window.mozCancelAnimationFrame || - window.oCancelAnimationFrame || - window.msCancelAnimationFrame || - function(callback) { - return window.clearTimeout(callback, 1000 / 60); - }; - })(), - animationLoop = helpers.animationLoop = function(callback,totalSteps,easingString,onProgress,onComplete,chartInstance){ + if (index < length - 1) { + rightSampleSize = (pixels[index + 1] - base) / 2; + if (index === 0) { + leftSampleSize = rightSampleSize; + } + } + } - var currentStep = 0, - easingFunction = easingEffects[easingString] || easingEffects.linear; + leftCategorySize = leftSampleSize * options.categoryPercentage; + rightCategorySize = rightSampleSize * options.categoryPercentage; + fullBarSize = (leftCategorySize + rightCategorySize) / ruler.stackCount; + size = fullBarSize * options.barPercentage; - var animationFrame = function(){ - currentStep++; - var stepDecimal = currentStep/totalSteps; - var easeDecimal = easingFunction(stepDecimal); + size = Math.min( + helpers.valueOrDefault(options.barThickness, size), + helpers.valueOrDefault(options.maxBarThickness, Infinity)); - callback.call(chartInstance,easeDecimal,stepDecimal, currentStep); - onProgress.call(chartInstance,easeDecimal,stepDecimal); - if (currentStep < totalSteps){ - chartInstance.animationFrame = requestAnimFrame(animationFrame); - } else{ - onComplete.apply(chartInstance); - } + base -= leftCategorySize; + base += fullBarSize * stackIndex; + base += (fullBarSize - size) / 2; + + return { + size: size, + base: base, + head: base + size, + center: base + size / 2 }; - requestAnimFrame(animationFrame); }, - //-- DOM methods - getRelativePosition = helpers.getRelativePosition = function(evt){ - var mouseX, mouseY; - var e = evt.originalEvent || evt, - canvas = evt.currentTarget || evt.srcElement, - boundingRect = canvas.getBoundingClientRect(); - if (e.touches){ - mouseX = e.touches[0].clientX - boundingRect.left; - mouseY = e.touches[0].clientY - boundingRect.top; - - } - else{ - mouseX = e.clientX - boundingRect.left; - mouseY = e.clientY - boundingRect.top; - } + draw: function() { + var me = this; + var chart = me.chart; + var scale = me.getValueScale(); + var rects = me.getMeta().data; + var dataset = me.getDataset(); + var ilen = rects.length; + var i = 0; - return { - x : mouseX, - y : mouseY - }; + helpers.canvas.clipArea(chart.ctx, chart.chartArea); - }, - addEvent = helpers.addEvent = function(node,eventType,method){ - if (node.addEventListener){ - node.addEventListener(eventType,method); - } else if (node.attachEvent){ - node.attachEvent("on"+eventType, method); - } else { - node["on"+eventType] = method; - } - }, - removeEvent = helpers.removeEvent = function(node, eventType, handler){ - if (node.removeEventListener){ - node.removeEventListener(eventType, handler, false); - } else if (node.detachEvent){ - node.detachEvent("on"+eventType,handler); - } else{ - node["on" + eventType] = noop; + for (; i < ilen; ++i) { + if (!isNaN(scale.getRightValue(dataset.data[i]))) { + rects[i].draw(); + } } - }, - bindEvents = helpers.bindEvents = function(chartInstance, arrayOfEvents, handler){ - // Create the events object if it's not already present - if (!chartInstance.events) chartInstance.events = {}; - each(arrayOfEvents,function(eventName){ - chartInstance.events[eventName] = function(){ - handler.apply(chartInstance, arguments); - }; - addEvent(chartInstance.chart.canvas,eventName,chartInstance.events[eventName]); - }); - }, - unbindEvents = helpers.unbindEvents = function (chartInstance, arrayOfEvents) { - each(arrayOfEvents, function(handler,eventName){ - removeEvent(chartInstance.chart.canvas, eventName, handler); - }); + helpers.canvas.unclipArea(chart.ctx); }, - getMaximumWidth = helpers.getMaximumWidth = function(domNode){ - var container = domNode.parentNode; - // TODO = check cross browser stuff with this. - return container.clientWidth; - }, - getMaximumHeight = helpers.getMaximumHeight = function(domNode){ - var container = domNode.parentNode; - // TODO = check cross browser stuff with this. - return container.clientHeight; - }, - getMaximumSize = helpers.getMaximumSize = helpers.getMaximumWidth, // legacy support - retinaScale = helpers.retinaScale = function(chart){ - var ctx = chart.ctx, - width = chart.canvas.width, - height = chart.canvas.height; - - if (window.devicePixelRatio) { - ctx.canvas.style.width = width + "px"; - ctx.canvas.style.height = height + "px"; - ctx.canvas.height = height * window.devicePixelRatio; - ctx.canvas.width = width * window.devicePixelRatio; - ctx.scale(window.devicePixelRatio, window.devicePixelRatio); - } - }, - //-- Canvas methods - clear = helpers.clear = function(chart){ - chart.ctx.clearRect(0,0,chart.width,chart.height); - }, - fontString = helpers.fontString = function(pixelSize,fontStyle,fontFamily){ - return fontStyle + " " + pixelSize+"px " + fontFamily; - }, - longestText = helpers.longestText = function(ctx,font,arrayOfStrings){ - ctx.font = font; - var longest = 0; - each(arrayOfStrings,function(string){ - var textWidth = ctx.measureText(string).width; - longest = (textWidth > longest) ? textWidth : longest; - }); - return longest; - }, - drawRoundedRectangle = helpers.drawRoundedRectangle = function(ctx,x,y,width,height,radius){ - ctx.beginPath(); - ctx.moveTo(x + radius, y); - ctx.lineTo(x + width - radius, y); - ctx.quadraticCurveTo(x + width, y, x + width, y + radius); - ctx.lineTo(x + width, y + height - radius); - ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); - ctx.lineTo(x + radius, y + height); - ctx.quadraticCurveTo(x, y + height, x, y + height - radius); - ctx.lineTo(x, y + radius); - ctx.quadraticCurveTo(x, y, x + radius, y); - ctx.closePath(); - }; + setHoverStyle: function(rectangle) { + var dataset = this.chart.data.datasets[rectangle._datasetIndex]; + var index = rectangle._index; + var custom = rectangle.custom || {}; + var model = rectangle._model; - //Store a reference to each instance - allowing us to globally resize chart instances on window resize. - //Destroy method on the chart will remove the instance of the chart from this reference. - Chart.instances = {}; + model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.hoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); + model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.hoverBorderColor, index, helpers.getHoverColor(model.borderColor)); + model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); + }, - Chart.Type = function(data,options,chart){ - this.options = options; - this.chart = chart; - this.id = uid(); - //Add the chart instance to the global namespace - Chart.instances[this.id] = this; + removeHoverStyle: function(rectangle) { + var dataset = this.chart.data.datasets[rectangle._datasetIndex]; + var index = rectangle._index; + var custom = rectangle.custom || {}; + var model = rectangle._model; + var rectangleElementOptions = this.chart.options.elements.rectangle; - // Initialize is always called when a chart type is created - // By default it is a no op, but it should be extended - if (options.responsive){ - this.resize(); + model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.backgroundColor, index, rectangleElementOptions.backgroundColor); + model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.borderColor, index, rectangleElementOptions.borderColor); + model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.borderWidth, index, rectangleElementOptions.borderWidth); } - this.initialize.call(this,data); - }; + }); - //Core methods that'll be a part of every chart type - extend(Chart.Type.prototype,{ - initialize : function(){return this;}, - clear : function(){ - clear(this.chart); - return this; + Chart.controllers.horizontalBar = Chart.controllers.bar.extend({ + /** + * @private + */ + getValueScaleId: function() { + return this.getMeta().xAxisID; }, - stop : function(){ - // Stops any current animation loop occuring - cancelAnimFrame(this.animationFrame); - return this; - }, - resize : function(callback){ - this.stop(); - var canvas = this.chart.canvas, - newWidth = getMaximumWidth(this.chart.canvas), - newHeight = this.options.maintainAspectRatio ? newWidth / this.chart.aspectRatio : getMaximumHeight(this.chart.canvas); - canvas.width = this.chart.width = newWidth; - canvas.height = this.chart.height = newHeight; + /** + * @private + */ + getIndexScaleId: function() { + return this.getMeta().yAxisID; + } + }); +}; + })(); +}); + +require.register("chart.js/src/controllers/controller.bubble.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - retinaScale(this.chart); +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - if (typeof callback === "function"){ - callback.apply(this, Array.prototype.slice.call(arguments, 1)); - } - return this; - }, - reflow : noop, - render : function(reflow){ - if (reflow){ - this.reflow(); - } - if (this.options.animation && !reflow){ - helpers.animationLoop( - this.draw, - this.options.animationSteps, - this.options.animationEasing, - this.options.onAnimationProgress, - this.options.onAnimationComplete, - this - ); - } - else{ - this.draw(); - this.options.onAnimationComplete.call(this); - } - return this; - }, - generateLegend : function(){ - return template(this.options.legendTemplate,this); - }, - destroy : function(){ - this.clear(); - unbindEvents(this, this.events); - var canvas = this.chart.canvas; +defaults._set('bubble', { + hover: { + mode: 'single' + }, - // Reset canvas height/width attributes starts a fresh with the canvas context - canvas.width = this.chart.width; - canvas.height = this.chart.height; + scales: { + xAxes: [{ + type: 'linear', // bubble should probably use a linear scale by default + position: 'bottom', + id: 'x-axis-0' // need an ID so datasets can reference the scale + }], + yAxes: [{ + type: 'linear', + position: 'left', + id: 'y-axis-0' + }] + }, - // < IE9 doesn't support removeProperty - if (canvas.style.removeProperty) { - canvas.style.removeProperty('width'); - canvas.style.removeProperty('height'); - } else { - canvas.style.removeAttribute('width'); - canvas.style.removeAttribute('height'); + tooltips: { + callbacks: { + title: function() { + // Title doesn't make sense for scatter since we format the data as a point + return ''; + }, + label: function(item, data) { + var datasetLabel = data.datasets[item.datasetIndex].label || ''; + var dataPoint = data.datasets[item.datasetIndex].data[item.index]; + return datasetLabel + ': (' + item.xLabel + ', ' + item.yLabel + ', ' + dataPoint.r + ')'; } + } + } +}); - delete Chart.instances[this.id]; - }, - showTooltip : function(ChartElements, forceRedraw){ - // Only redraw the chart if we've actually changed what we're hovering on. - if (typeof this.activeElements === 'undefined') this.activeElements = []; - var isChanged = (function(Elements){ - var changed = false; +module.exports = function(Chart) { - if (Elements.length !== this.activeElements.length){ - changed = true; - return changed; - } + Chart.controllers.bubble = Chart.DatasetController.extend({ + /** + * @protected + */ + dataElementType: elements.Point, - each(Elements, function(element, index){ - if (element !== this.activeElements[index]){ - changed = true; - } - }, this); - return changed; - }).call(this, ChartElements); + /** + * @protected + */ + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var points = meta.data; - if (!isChanged && !forceRedraw){ - return; - } - else{ - this.activeElements = ChartElements; - } - this.draw(); - if(this.options.customTooltips){ - this.options.customTooltips(false); - } - if (ChartElements.length > 0){ - // If we have multiple datasets, show a MultiTooltip for all of the data points at that index - if (this.datasets && this.datasets.length > 1) { - var dataArray, - dataIndex; + // Update Points + helpers.each(points, function(point, index) { + me.updateElement(point, index, reset); + }); + }, - for (var i = this.datasets.length - 1; i >= 0; i--) { - dataArray = this.datasets[i].points || this.datasets[i].bars || this.datasets[i].segments; - dataIndex = indexOf(dataArray, ChartElements[0]); - if (dataIndex !== -1){ - break; - } - } - var tooltipLabels = [], - tooltipColors = [], - medianPosition = (function(index) { - - // Get all the points at that particular index - var Elements = [], - dataCollection, - xPositions = [], - yPositions = [], - xMax, - yMax, - xMin, - yMin; - helpers.each(this.datasets, function(dataset){ - dataCollection = dataset.points || dataset.bars || dataset.segments; - if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ - Elements.push(dataCollection[dataIndex]); - } - }); - - helpers.each(Elements, function(element) { - xPositions.push(element.x); - yPositions.push(element.y); + /** + * @protected + */ + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var xScale = me.getScaleForId(meta.xAxisID); + var yScale = me.getScaleForId(meta.yAxisID); + var options = me._resolveElementOptions(point, index); + var data = me.getDataset().data[index]; + var dsIndex = me.index; + + var x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(typeof data === 'object' ? data : NaN, index, dsIndex); + var y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(data, index, dsIndex); + + point._xScale = xScale; + point._yScale = yScale; + point._options = options; + point._datasetIndex = dsIndex; + point._index = index; + point._model = { + backgroundColor: options.backgroundColor, + borderColor: options.borderColor, + borderWidth: options.borderWidth, + hitRadius: options.hitRadius, + pointStyle: options.pointStyle, + radius: reset ? 0 : options.radius, + skip: custom.skip || isNaN(x) || isNaN(y), + x: x, + y: y, + }; + point.pivot(); + }, - //Include any colour information about the element - tooltipLabels.push(helpers.template(this.options.multiTooltipTemplate, element)); - tooltipColors.push({ - fill: element._saved.fillColor || element.fillColor, - stroke: element._saved.strokeColor || element.strokeColor - }); + /** + * @protected + */ + setHoverStyle: function(point) { + var model = point._model; + var options = point._options; + + model.backgroundColor = helpers.valueOrDefault(options.hoverBackgroundColor, helpers.getHoverColor(options.backgroundColor)); + model.borderColor = helpers.valueOrDefault(options.hoverBorderColor, helpers.getHoverColor(options.borderColor)); + model.borderWidth = helpers.valueOrDefault(options.hoverBorderWidth, options.borderWidth); + model.radius = options.radius + options.hoverRadius; + }, - }, this); + /** + * @protected + */ + removeHoverStyle: function(point) { + var model = point._model; + var options = point._options; + + model.backgroundColor = options.backgroundColor; + model.borderColor = options.borderColor; + model.borderWidth = options.borderWidth; + model.radius = options.radius; + }, - yMin = min(yPositions); - yMax = max(yPositions); + /** + * @private + */ + _resolveElementOptions: function(point, index) { + var me = this; + var chart = me.chart; + var datasets = chart.data.datasets; + var dataset = datasets[me.index]; + var custom = point.custom || {}; + var options = chart.options.elements.point; + var resolve = helpers.options.resolve; + var data = dataset.data[index]; + var values = {}; + var i, ilen, key; + + // Scriptable options + var context = { + chart: chart, + dataIndex: index, + dataset: dataset, + datasetIndex: me.index + }; - xMin = min(xPositions); - xMax = max(xPositions); + var keys = [ + 'backgroundColor', + 'borderColor', + 'borderWidth', + 'hoverBackgroundColor', + 'hoverBorderColor', + 'hoverBorderWidth', + 'hoverRadius', + 'hitRadius', + 'pointStyle' + ]; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + values[key] = resolve([ + custom[key], + dataset[key], + options[key] + ], context, index); + } + + // Custom radius resolution + values.radius = resolve([ + custom.radius, + data ? data.r : undefined, + dataset.radius, + options.radius + ], context, index); + + return values; + } + }); +}; + })(); +}); - return { - x: (xMin > this.chart.width/2) ? xMin : xMax, - y: (yMin + yMax)/2 - }; - }).call(this, dataIndex); - - new Chart.MultiTooltip({ - x: medianPosition.x, - y: medianPosition.y, - xPadding: this.options.tooltipXPadding, - yPadding: this.options.tooltipYPadding, - xOffset: this.options.tooltipXOffset, - fillColor: this.options.tooltipFillColor, - textColor: this.options.tooltipFontColor, - fontFamily: this.options.tooltipFontFamily, - fontStyle: this.options.tooltipFontStyle, - fontSize: this.options.tooltipFontSize, - titleTextColor: this.options.tooltipTitleFontColor, - titleFontFamily: this.options.tooltipTitleFontFamily, - titleFontStyle: this.options.tooltipTitleFontStyle, - titleFontSize: this.options.tooltipTitleFontSize, - cornerRadius: this.options.tooltipCornerRadius, - labels: tooltipLabels, - legendColors: tooltipColors, - legendColorBackground : this.options.multiTooltipKeyBackground, - title: ChartElements[0].label, - chart: this.chart, - ctx: this.chart.ctx, - custom: this.options.customTooltips - }).draw(); +require.register("chart.js/src/controllers/controller.doughnut.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); + +defaults._set('doughnut', { + animation: { + // Boolean - Whether we animate the rotation of the Doughnut + animateRotate: true, + // Boolean - Whether we animate scaling the Doughnut from the centre + animateScale: false + }, + hover: { + mode: 'single' + }, + legendCallback: function(chart) { + var text = []; + text.push('
    '); + + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; + + if (datasets.length) { + for (var i = 0; i < datasets[0].data.length; ++i) { + text.push('
  • '); + if (labels[i]) { + text.push(labels[i]); + } + text.push('
  • '); + } + } - } else { - each(ChartElements, function(Element) { - var tooltipPosition = Element.tooltipPosition(); - new Chart.Tooltip({ - x: Math.round(tooltipPosition.x), - y: Math.round(tooltipPosition.y), - xPadding: this.options.tooltipXPadding, - yPadding: this.options.tooltipYPadding, - fillColor: this.options.tooltipFillColor, - textColor: this.options.tooltipFontColor, - fontFamily: this.options.tooltipFontFamily, - fontStyle: this.options.tooltipFontStyle, - fontSize: this.options.tooltipFontSize, - caretHeight: this.options.tooltipCaretSize, - cornerRadius: this.options.tooltipCornerRadius, - text: template(this.options.tooltipTemplate, Element), - chart: this.chart, - custom: this.options.customTooltips - }).draw(); - }, this); + text.push('
'); + return text.join(''); + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var ds = data.datasets[0]; + var arc = meta.data[i]; + var custom = arc && arc.custom || {}; + var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + var arcOpts = chart.options.elements.arc; + var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); + var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); + var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); + + return { + text: label, + fillStyle: fill, + strokeStyle: stroke, + lineWidth: bw, + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); } + return []; } - return this; }, - toBase64Image : function(){ - return this.chart.canvas.toDataURL.apply(this.chart.canvas, arguments); - } - }); - Chart.Type.extend = function(extensions){ + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; + + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + // toggle visibility of index if exists + if (meta.data[index]) { + meta.data[index].hidden = !meta.data[index].hidden; + } + } - var parent = this; + chart.update(); + } + }, - var ChartType = function(){ - return parent.apply(this,arguments); - }; + // The percentage of the chart that we cut out of the middle. + cutoutPercentage: 50, - //Copy the prototype object of the this class - ChartType.prototype = clone(parent.prototype); - //Now overwrite some of the properties in the base class with the new extensions - extend(ChartType.prototype, extensions); + // The rotation of the chart, where the first data arc begins. + rotation: Math.PI * -0.5, - ChartType.extend = Chart.Type.extend; + // The total circumference of the chart. + circumference: Math.PI * 2.0, - if (extensions.name || parent.prototype.name){ + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(tooltipItem, data) { + var dataLabel = data.labels[tooltipItem.index]; + var value = ': ' + data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index]; + + if (helpers.isArray(dataLabel)) { + // show value on first line of multiline label + // need to clone because we are changing the value + dataLabel = dataLabel.slice(); + dataLabel[0] += value; + } else { + dataLabel += value; + } - var chartName = extensions.name || parent.prototype.name; - //Assign any potential default values of the new chart type + return dataLabel; + } + } + } +}); - //If none are defined, we'll use a clone of the chart type this is being extended from. - //I.e. if we extend a line chart, we'll use the defaults from the line chart if our new chart - //doesn't define some defaults of their own. +defaults._set('pie', helpers.clone(defaults.doughnut)); +defaults._set('pie', { + cutoutPercentage: 0 +}); - var baseDefaults = (Chart.defaults[parent.prototype.name]) ? clone(Chart.defaults[parent.prototype.name]) : {}; +module.exports = function(Chart) { - Chart.defaults[chartName] = extend(baseDefaults,extensions.defaults); + Chart.controllers.doughnut = Chart.controllers.pie = Chart.DatasetController.extend({ - Chart.types[chartName] = ChartType; + dataElementType: elements.Arc, - //Register this new chart type in the Chart prototype - Chart.prototype[chartName] = function(data,options){ - var config = merge(Chart.defaults.global, Chart.defaults[chartName], options || {}); - return new ChartType(data,config,this); - }; - } else{ - warn("Name not provided for this chart, so it hasn't been registered"); - } - return parent; - }; + linkScales: helpers.noop, - Chart.Element = function(configuration){ - extend(this,configuration); - this.initialize.apply(this,arguments); - this.save(); - }; - extend(Chart.Element.prototype,{ - initialize : function(){}, - restore : function(props){ - if (!props){ - extend(this,this._saved); - } else { - each(props,function(key){ - this[key] = this._saved[key]; - },this); - } - return this; - }, - save : function(){ - this._saved = clone(this); - delete this._saved._saved; - return this; - }, - update : function(newProps){ - each(newProps,function(value,key){ - this._saved[key] = this[key]; - this[key] = value; - },this); - return this; - }, - transition : function(props,ease){ - each(props,function(value,key){ - this[key] = ((value - this._saved[key]) * ease) + this._saved[key]; - },this); - return this; - }, - tooltipPosition : function(){ - return { - x : this.x, - y : this.y - }; - }, - hasValue: function(){ - return isNumber(this.value); - } - }); + // Get index of the dataset in relation to the visible datasets. This allows determining the inner and outer radius correctly + getRingIndex: function(datasetIndex) { + var ringIndex = 0; - Chart.Element.extend = inherits; + for (var j = 0; j < datasetIndex; ++j) { + if (this.chart.isDatasetVisible(j)) { + ++ringIndex; + } + } + return ringIndex; + }, - Chart.Point = Chart.Element.extend({ - display: true, - inRange: function(chartX,chartY){ - var hitDetectionRange = this.hitDetectionRadius + this.radius; - return ((Math.pow(chartX-this.x, 2)+Math.pow(chartY-this.y, 2)) < Math.pow(hitDetectionRange,2)); + update: function(reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var arcOpts = opts.elements.arc; + var availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth; + var availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth; + var minSize = Math.min(availableWidth, availableHeight); + var offset = {x: 0, y: 0}; + var meta = me.getMeta(); + var cutoutPercentage = opts.cutoutPercentage; + var circumference = opts.circumference; + + // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc + if (circumference < Math.PI * 2.0) { + var startAngle = opts.rotation % (Math.PI * 2.0); + startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0); + var endAngle = startAngle + circumference; + var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)}; + var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)}; + var contains0 = (startAngle <= 0 && endAngle >= 0) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle); + var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle); + var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle); + var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle); + var cutout = cutoutPercentage / 100.0; + var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))}; + var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))}; + var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5}; + minSize = Math.min(availableWidth / size.width, availableHeight / size.height); + offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5}; + } + + chart.borderWidth = me.getMaxBorderWidth(meta.data); + chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0); + chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); + chart.offsetX = offset.x * chart.outerRadius; + chart.offsetY = offset.y * chart.outerRadius; + + meta.total = me.calculateTotal(); + + me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index)); + me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0); + + helpers.each(meta.data, function(arc, index) { + me.updateElement(arc, index, reset); + }); }, - draw : function(){ - if (this.display){ - var ctx = this.ctx; - ctx.beginPath(); - ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2); - ctx.closePath(); + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var opts = chart.options; + var animationOpts = opts.animation; + var centerX = (chartArea.left + chartArea.right) / 2; + var centerY = (chartArea.top + chartArea.bottom) / 2; + var startAngle = opts.rotation; // non reset case handled later + var endAngle = opts.rotation; // non reset case handled later + var dataset = me.getDataset(); + var circumference = reset && animationOpts.animateRotate ? 0 : arc.hidden ? 0 : me.calculateCircumference(dataset.data[index]) * (opts.circumference / (2.0 * Math.PI)); + var innerRadius = reset && animationOpts.animateScale ? 0 : me.innerRadius; + var outerRadius = reset && animationOpts.animateScale ? 0 : me.outerRadius; + var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + + helpers.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + + // Desired view properties + _model: { + x: centerX + chart.offsetX, + y: centerY + chart.offsetY, + startAngle: startAngle, + endAngle: endAngle, + circumference: circumference, + outerRadius: outerRadius, + innerRadius: innerRadius, + label: valueAtIndexOrDefault(dataset.label, index, chart.data.labels[index]) + } + }); - ctx.strokeStyle = this.strokeColor; - ctx.lineWidth = this.strokeWidth; + var model = arc._model; + // Resets the visual styles + this.removeHoverStyle(arc); - ctx.fillStyle = this.fillColor; + // Set correct angles if not resetting + if (!reset || !animationOpts.animateRotate) { + if (index === 0) { + model.startAngle = opts.rotation; + } else { + model.startAngle = me.getMeta().data[index - 1]._model.endAngle; + } - ctx.fill(); - ctx.stroke(); + model.endAngle = model.startAngle + model.circumference; } + arc.pivot(); + }, + + removeHoverStyle: function(arc) { + Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); + }, - //Quick debug for bezier curve splining - //Highlights control points and the line between them. - //Handy for dev - stripped in the min version. + calculateTotal: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var total = 0; + var value; - // ctx.save(); - // ctx.fillStyle = "black"; - // ctx.strokeStyle = "black" - // ctx.beginPath(); - // ctx.arc(this.controlPoints.inner.x,this.controlPoints.inner.y, 2, 0, Math.PI*2); - // ctx.fill(); + helpers.each(meta.data, function(element, index) { + value = dataset.data[index]; + if (!isNaN(value) && !element.hidden) { + total += Math.abs(value); + } + }); - // ctx.beginPath(); - // ctx.arc(this.controlPoints.outer.x,this.controlPoints.outer.y, 2, 0, Math.PI*2); - // ctx.fill(); + /* if (total === 0) { + total = NaN; + }*/ - // ctx.moveTo(this.controlPoints.inner.x,this.controlPoints.inner.y); - // ctx.lineTo(this.x, this.y); - // ctx.lineTo(this.controlPoints.outer.x,this.controlPoints.outer.y); - // ctx.stroke(); + return total; + }, - // ctx.restore(); + calculateCircumference: function(value) { + var total = this.getMeta().total; + if (total > 0 && !isNaN(value)) { + return (Math.PI * 2.0) * (value / total); + } + return 0; + }, + // gets the max border or hover width to properly scale pie charts + getMaxBorderWidth: function(arcs) { + var max = 0; + var index = this.index; + var length = arcs.length; + var borderWidth; + var hoverWidth; + for (var i = 0; i < length; i++) { + borderWidth = arcs[i]._model ? arcs[i]._model.borderWidth : 0; + hoverWidth = arcs[i]._chart ? arcs[i]._chart.config.data.datasets[index].hoverBorderWidth : 0; + max = borderWidth > max ? borderWidth : max; + max = hoverWidth > max ? hoverWidth : max; + } + return max; } }); +}; + })(); +}); - Chart.Arc = Chart.Element.extend({ - inRange : function(chartX,chartY){ +require.register("chart.js/src/controllers/controller.line.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - var pointRelativePosition = helpers.getAngleFromPoint(this, { - x: chartX, - y: chartY - }); +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - //Check if within the range of the open/close angle - var betweenAngles = (pointRelativePosition.angle >= this.startAngle && pointRelativePosition.angle <= this.endAngle), - withinRadius = (pointRelativePosition.distance >= this.innerRadius && pointRelativePosition.distance <= this.outerRadius); +defaults._set('line', { + showLines: true, + spanGaps: false, - return (betweenAngles && withinRadius); - //Ensure within the outside of the arc centre, but inside arc outer - }, - tooltipPosition : function(){ - var centreAngle = this.startAngle + ((this.endAngle - this.startAngle) / 2), - rangeFromCentre = (this.outerRadius - this.innerRadius) / 2 + this.innerRadius; - return { - x : this.x + (Math.cos(centreAngle) * rangeFromCentre), - y : this.y + (Math.sin(centreAngle) * rangeFromCentre) - }; - }, - draw : function(animationPercent){ + hover: { + mode: 'label' + }, - var easingDecimal = animationPercent || 1; + scales: { + xAxes: [{ + type: 'category', + id: 'x-axis-0' + }], + yAxes: [{ + type: 'linear', + id: 'y-axis-0' + }] + } +}); - var ctx = this.ctx; +module.exports = function(Chart) { - ctx.beginPath(); + function lineEnabled(dataset, options) { + return helpers.valueOrDefault(dataset.showLine, options.showLines); + } - ctx.arc(this.x, this.y, this.outerRadius, this.startAngle, this.endAngle); + Chart.controllers.line = Chart.DatasetController.extend({ - ctx.arc(this.x, this.y, this.innerRadius, this.endAngle, this.startAngle, true); + datasetElementType: elements.Line, - ctx.closePath(); - ctx.strokeStyle = this.strokeColor; - ctx.lineWidth = this.strokeWidth; + dataElementType: elements.Point, - ctx.fillStyle = this.fillColor; + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data || []; + var options = me.chart.options; + var lineElementOptions = options.elements.line; + var scale = me.getScaleForId(meta.yAxisID); + var i, ilen, custom; + var dataset = me.getDataset(); + var showLine = lineEnabled(dataset, options); - ctx.fill(); - ctx.lineJoin = 'bevel'; + // Update Line + if (showLine) { + custom = line.custom || {}; - if (this.showStroke){ - ctx.stroke(); - } - } - }); + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { + dataset.lineTension = dataset.tension; + } - Chart.Rectangle = Chart.Element.extend({ - draw : function(){ - var ctx = this.ctx, - halfWidth = this.width/2, - leftX = this.x - halfWidth, - rightX = this.x + halfWidth, - top = this.base - (this.base - this.y), - halfStroke = this.strokeWidth / 2; + // Utility + line._scale = scale; + line._datasetIndex = me.index; + // Data + line._children = points; + // Model + line._model = { + // Appearance + // The default behavior of lines is to break at null values, according + // to https://github.com/chartjs/Chart.js/issues/2435#issuecomment-216718158 + // This option gives lines the ability to span gaps + spanGaps: dataset.spanGaps ? dataset.spanGaps : options.spanGaps, + tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension), + backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), + borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), + borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), + borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), + borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), + borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), + borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), + fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), + steppedLine: custom.steppedLine ? custom.steppedLine : helpers.valueOrDefault(dataset.steppedLine, lineElementOptions.stepped), + cubicInterpolationMode: custom.cubicInterpolationMode ? custom.cubicInterpolationMode : helpers.valueOrDefault(dataset.cubicInterpolationMode, lineElementOptions.cubicInterpolationMode), + }; - // Canvas doesn't allow us to stroke inside the width so we can - // adjust the sizes to fit if we're setting a stroke on the line - if (this.showStroke){ - leftX += halfStroke; - rightX -= halfStroke; - top += halfStroke; + line.pivot(); } - ctx.beginPath(); + // Update Points + for (i = 0, ilen = points.length; i < ilen; ++i) { + me.updateElement(points[i], i, reset); + } - ctx.fillStyle = this.fillColor; - ctx.strokeStyle = this.strokeColor; - ctx.lineWidth = this.strokeWidth; + if (showLine && line._model.tension !== 0) { + me.updateBezierControlPoints(); + } - // It'd be nice to keep this class totally generic to any rectangle - // and simply specify which border to miss out. - ctx.moveTo(leftX, this.base); - ctx.lineTo(leftX, top); - ctx.lineTo(rightX, top); - ctx.lineTo(rightX, this.base); - ctx.fill(); - if (this.showStroke){ - ctx.stroke(); + // Now pivot the point for animation + for (i = 0, ilen = points.length; i < ilen; ++i) { + points[i].pivot(); } }, - height : function(){ - return this.base - this.y; - }, - inRange : function(chartX,chartY){ - return (chartX >= this.x - this.width/2 && chartX <= this.x + this.width/2) && (chartY >= this.y && chartY <= this.base); - } - }); - Chart.Tooltip = Chart.Element.extend({ - draw : function(){ + getPointBackgroundColor: function(point, index) { + var backgroundColor = this.chart.options.elements.point.backgroundColor; + var dataset = this.getDataset(); + var custom = point.custom || {}; - var ctx = this.chart.ctx; + if (custom.backgroundColor) { + backgroundColor = custom.backgroundColor; + } else if (dataset.pointBackgroundColor) { + backgroundColor = helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, backgroundColor); + } else if (dataset.backgroundColor) { + backgroundColor = dataset.backgroundColor; + } - ctx.font = fontString(this.fontSize,this.fontStyle,this.fontFamily); + return backgroundColor; + }, - this.xAlign = "center"; - this.yAlign = "above"; + getPointBorderColor: function(point, index) { + var borderColor = this.chart.options.elements.point.borderColor; + var dataset = this.getDataset(); + var custom = point.custom || {}; - //Distance between the actual element.y position and the start of the tooltip caret - var caretPadding = this.caretPadding = 2; + if (custom.borderColor) { + borderColor = custom.borderColor; + } else if (dataset.pointBorderColor) { + borderColor = helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, borderColor); + } else if (dataset.borderColor) { + borderColor = dataset.borderColor; + } - var tooltipWidth = ctx.measureText(this.text).width + 2*this.xPadding, - tooltipRectHeight = this.fontSize + 2*this.yPadding, - tooltipHeight = tooltipRectHeight + this.caretHeight + caretPadding; + return borderColor; + }, - if (this.x + tooltipWidth/2 >this.chart.width){ - this.xAlign = "left"; - } else if (this.x - tooltipWidth/2 < 0){ - this.xAlign = "right"; - } + getPointBorderWidth: function(point, index) { + var borderWidth = this.chart.options.elements.point.borderWidth; + var dataset = this.getDataset(); + var custom = point.custom || {}; - if (this.y - tooltipHeight < 0){ - this.yAlign = "below"; + if (!isNaN(custom.borderWidth)) { + borderWidth = custom.borderWidth; + } else if (!isNaN(dataset.pointBorderWidth) || helpers.isArray(dataset.pointBorderWidth)) { + borderWidth = helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, borderWidth); + } else if (!isNaN(dataset.borderWidth)) { + borderWidth = dataset.borderWidth; } + return borderWidth; + }, - var tooltipX = this.x - tooltipWidth/2, - tooltipY = this.y - tooltipHeight; - - ctx.fillStyle = this.fillColor; + updateElement: function(point, index, reset) { + var me = this; + var meta = me.getMeta(); + var custom = point.custom || {}; + var dataset = me.getDataset(); + var datasetIndex = me.index; + var value = dataset.data[index]; + var yScale = me.getScaleForId(meta.yAxisID); + var xScale = me.getScaleForId(meta.xAxisID); + var pointOptions = me.chart.options.elements.point; + var x, y; + + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { + dataset.pointRadius = dataset.radius; + } + if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) { + dataset.pointHitRadius = dataset.hitRadius; + } + + x = xScale.getPixelForValue(typeof value === 'object' ? value : NaN, index, datasetIndex); + y = reset ? yScale.getBasePixel() : me.calculatePointY(value, index, datasetIndex); + + // Utility + point._xScale = xScale; + point._yScale = yScale; + point._datasetIndex = datasetIndex; + point._index = index; + + // Desired view properties + point._model = { + x: x, + y: y, + skip: custom.skip || isNaN(x) || isNaN(y), + // Appearance + radius: custom.radius || helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointOptions.radius), + pointStyle: custom.pointStyle || helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointOptions.pointStyle), + backgroundColor: me.getPointBackgroundColor(point, index), + borderColor: me.getPointBorderColor(point, index), + borderWidth: me.getPointBorderWidth(point, index), + tension: meta.dataset._model ? meta.dataset._model.tension : 0, + steppedLine: meta.dataset._model ? meta.dataset._model.steppedLine : false, + // Tooltip + hitRadius: custom.hitRadius || helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointOptions.hitRadius) + }; + }, - // Custom Tooltips - if(this.custom){ - this.custom(this); - } - else{ - switch(this.yAlign) - { - case "above": - //Draw a caret above the x/y - ctx.beginPath(); - ctx.moveTo(this.x,this.y - caretPadding); - ctx.lineTo(this.x + this.caretHeight, this.y - (caretPadding + this.caretHeight)); - ctx.lineTo(this.x - this.caretHeight, this.y - (caretPadding + this.caretHeight)); - ctx.closePath(); - ctx.fill(); - break; - case "below": - tooltipY = this.y + caretPadding + this.caretHeight; - //Draw a caret below the x/y - ctx.beginPath(); - ctx.moveTo(this.x, this.y + caretPadding); - ctx.lineTo(this.x + this.caretHeight, this.y + caretPadding + this.caretHeight); - ctx.lineTo(this.x - this.caretHeight, this.y + caretPadding + this.caretHeight); - ctx.closePath(); - ctx.fill(); - break; + calculatePointY: function(value, index, datasetIndex) { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var yScale = me.getScaleForId(meta.yAxisID); + var sumPos = 0; + var sumNeg = 0; + var i, ds, dsMeta; + + if (yScale.options.stacked) { + for (i = 0; i < datasetIndex; i++) { + ds = chart.data.datasets[i]; + dsMeta = chart.getDatasetMeta(i); + if (dsMeta.type === 'line' && dsMeta.yAxisID === yScale.id && chart.isDatasetVisible(i)) { + var stackedRightValue = Number(yScale.getRightValue(ds.data[index])); + if (stackedRightValue < 0) { + sumNeg += stackedRightValue || 0; + } else { + sumPos += stackedRightValue || 0; + } + } } - switch(this.xAlign) - { - case "left": - tooltipX = this.x - tooltipWidth + (this.cornerRadius + this.caretHeight); - break; - case "right": - tooltipX = this.x - (this.cornerRadius + this.caretHeight); - break; + var rightValue = Number(yScale.getRightValue(value)); + if (rightValue < 0) { + return yScale.getPixelForValue(sumNeg + rightValue); } - - drawRoundedRectangle(ctx,tooltipX,tooltipY,tooltipWidth,tooltipRectHeight,this.cornerRadius); - - ctx.fill(); - - ctx.fillStyle = this.textColor; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillText(this.text, tooltipX + tooltipWidth/2, tooltipY + tooltipRectHeight/2); + return yScale.getPixelForValue(sumPos + rightValue); } - } - }); - - Chart.MultiTooltip = Chart.Element.extend({ - initialize : function(){ - this.font = fontString(this.fontSize,this.fontStyle,this.fontFamily); - - this.titleFont = fontString(this.titleFontSize,this.titleFontStyle,this.titleFontFamily); - - this.height = (this.labels.length * this.fontSize) + ((this.labels.length-1) * (this.fontSize/2)) + (this.yPadding*2) + this.titleFontSize *1.5; - - this.ctx.font = this.titleFont; - - var titleWidth = this.ctx.measureText(this.title).width, - //Label has a legend square as well so account for this. - labelWidth = longestText(this.ctx,this.font,this.labels) + this.fontSize + 3, - longestTextWidth = max([labelWidth,titleWidth]); - - this.width = longestTextWidth + (this.xPadding*2); + return yScale.getPixelForValue(value); + }, - var halfHeight = this.height/2; + updateBezierControlPoints: function() { + var me = this; + var meta = me.getMeta(); + var area = me.chart.chartArea; + var points = (meta.data || []); + var i, ilen, point, model, controlPoints; + + // Only consider points that are drawn in case the spanGaps option is used + if (meta.dataset._model.spanGaps) { + points = points.filter(function(pt) { + return !pt._model.skip; + }); + } - //Check to ensure the height will fit on the canvas - if (this.y - halfHeight < 0 ){ - this.y = halfHeight; - } else if (this.y + halfHeight > this.chart.height){ - this.y = this.chart.height - halfHeight; + function capControlPoint(pt, min, max) { + return Math.max(Math.min(pt, max), min); } - //Decide whether to align left or right based on position on canvas - if (this.x > this.chart.width/2){ - this.x -= this.xOffset + this.width; + if (meta.dataset._model.cubicInterpolationMode === 'monotone') { + helpers.splineCurveMonotone(points); } else { - this.x += this.xOffset; + for (i = 0, ilen = points.length; i < ilen; ++i) { + point = points[i]; + model = point._model; + controlPoints = helpers.splineCurve( + helpers.previousItem(points, i)._model, + model, + helpers.nextItem(points, i)._model, + meta.dataset._model.tension + ); + model.controlPointPreviousX = controlPoints.previous.x; + model.controlPointPreviousY = controlPoints.previous.y; + model.controlPointNextX = controlPoints.next.x; + model.controlPointNextY = controlPoints.next.y; + } } - - }, - getLineHeight : function(index){ - var baseLineHeight = this.y - (this.height/2) + this.yPadding, - afterTitleIndex = index-1; - - //If the index is zero, we're getting the title - if (index === 0){ - return baseLineHeight + this.titleFontSize/2; - } else{ - return baseLineHeight + ((this.fontSize*1.5*afterTitleIndex) + this.fontSize/2) + this.titleFontSize * 1.5; + if (me.chart.options.elements.line.capBezierPoints) { + for (i = 0, ilen = points.length; i < ilen; ++i) { + model = points[i]._model; + model.controlPointPreviousX = capControlPoint(model.controlPointPreviousX, area.left, area.right); + model.controlPointPreviousY = capControlPoint(model.controlPointPreviousY, area.top, area.bottom); + model.controlPointNextX = capControlPoint(model.controlPointNextX, area.left, area.right); + model.controlPointNextY = capControlPoint(model.controlPointNextY, area.top, area.bottom); + } } - }, - draw : function(){ - // Custom Tooltips - if(this.custom){ - this.custom(this); - } - else{ - drawRoundedRectangle(this.ctx,this.x,this.y - this.height/2,this.width,this.height,this.cornerRadius); - var ctx = this.ctx; - ctx.fillStyle = this.fillColor; - ctx.fill(); - ctx.closePath(); - ctx.textAlign = "left"; - ctx.textBaseline = "middle"; - ctx.fillStyle = this.titleTextColor; - ctx.font = this.titleFont; + draw: function() { + var me = this; + var chart = me.chart; + var meta = me.getMeta(); + var points = meta.data || []; + var area = chart.chartArea; + var ilen = points.length; + var i = 0; - ctx.fillText(this.title,this.x + this.xPadding, this.getLineHeight(0)); + helpers.canvas.clipArea(chart.ctx, area); - ctx.font = this.font; - helpers.each(this.labels,function(label,index){ - ctx.fillStyle = this.textColor; - ctx.fillText(label,this.x + this.xPadding + this.fontSize + 3, this.getLineHeight(index + 1)); + if (lineEnabled(me.getDataset(), chart.options)) { + meta.dataset.draw(); + } - //A bit gnarly, but clearing this rectangle breaks when using explorercanvas (clears whole canvas) - //ctx.clearRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); - //Instead we'll make a white filled block to put the legendColour palette over. + helpers.canvas.unclipArea(chart.ctx); - ctx.fillStyle = this.legendColorBackground; - ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); + // Draw the points + for (; i < ilen; ++i) { + points[i].draw(area); + } + }, - ctx.fillStyle = this.legendColors[index].fill; - ctx.fillRect(this.x + this.xPadding, this.getLineHeight(index + 1) - this.fontSize/2, this.fontSize, this.fontSize); + setHoverStyle: function(point) { + // Point + var dataset = this.chart.data.datasets[point._datasetIndex]; + var index = point._index; + var custom = point.custom || {}; + var model = point._model; + + model.radius = custom.hoverRadius || helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); + model.backgroundColor = custom.hoverBackgroundColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); + model.borderColor = custom.hoverBorderColor || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); + model.borderWidth = custom.hoverBorderWidth || helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); + }, + removeHoverStyle: function(point) { + var me = this; + var dataset = me.chart.data.datasets[point._datasetIndex]; + var index = point._index; + var custom = point.custom || {}; + var model = point._model; - },this); + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { + dataset.pointRadius = dataset.radius; } + + model.radius = custom.radius || helpers.valueAtIndexOrDefault(dataset.pointRadius, index, me.chart.options.elements.point.radius); + model.backgroundColor = me.getPointBackgroundColor(point, index); + model.borderColor = me.getPointBorderColor(point, index); + model.borderWidth = me.getPointBorderWidth(point, index); } }); +}; + })(); +}); - Chart.Scale = Chart.Element.extend({ - initialize : function(){ - this.fit(); - }, - buildYLabels : function(){ - this.yLabels = []; +require.register("chart.js/src/controllers/controller.polarArea.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - var stepDecimalPlaces = getDecimalPlaces(this.stepValue); +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - for (var i=0; i<=this.steps; i++){ - this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)})); - } - this.yLabelWidth = (this.display && this.showLabels) ? longestText(this.ctx,this.font,this.yLabels) : 0; +defaults._set('polarArea', { + scale: { + type: 'radialLinear', + angleLines: { + display: false }, - addXLabel : function(label){ - this.xLabels.push(label); - this.valuesCount++; - this.fit(); + gridLines: { + circular: true }, - removeXLabel : function(){ - this.xLabels.shift(); - this.valuesCount--; - this.fit(); + pointLabels: { + display: false }, - // Fitting loop to rotate x Labels and figure out what fits there, and also calculate how many Y steps to use - fit: function(){ - // First we need the width of the yLabels, assuming the xLabels aren't rotated - - // To do that we need the base line at the top and base of the chart, assuming there is no x label rotation - this.startPoint = (this.display) ? this.fontSize : 0; - this.endPoint = (this.display) ? this.height - (this.fontSize * 1.5) - 5 : this.height; // -5 to pad labels - - // Apply padding settings to the start and end point. - this.startPoint += this.padding; - this.endPoint -= this.padding; - - // Cache the starting height, so can determine if we need to recalculate the scale yAxis - var cachedHeight = this.endPoint - this.startPoint, - cachedYLabelWidth; - - // Build the current yLabels so we have an idea of what size they'll be to start - /* - * This sets what is returned from calculateScaleRange as static properties of this class: - * - this.steps; - this.stepValue; - this.min; - this.max; - * - */ - this.calculateYRange(cachedHeight); - - // With these properties set we can now build the array of yLabels - // and also the width of the largest yLabel - this.buildYLabels(); + ticks: { + beginAtZero: true + } + }, - this.calculateXLabelRotation(); + // Boolean - Whether to animate the rotation of the chart + animation: { + animateRotate: true, + animateScale: true + }, - while((cachedHeight > this.endPoint - this.startPoint)){ - cachedHeight = this.endPoint - this.startPoint; - cachedYLabelWidth = this.yLabelWidth; + startAngle: -0.5 * Math.PI, + legendCallback: function(chart) { + var text = []; + text.push('
    '); - this.calculateYRange(cachedHeight); - this.buildYLabels(); + var data = chart.data; + var datasets = data.datasets; + var labels = data.labels; - // Only go through the xLabel loop again if the yLabel width has changed - if (cachedYLabelWidth < this.yLabelWidth){ - this.calculateXLabelRotation(); + if (datasets.length) { + for (var i = 0; i < datasets[0].data.length; ++i) { + text.push('
  • '); + if (labels[i]) { + text.push(labels[i]); } + text.push('
  • '); } + } + text.push('
'); + return text.join(''); + }, + legend: { + labels: { + generateLabels: function(chart) { + var data = chart.data; + if (data.labels.length && data.datasets.length) { + return data.labels.map(function(label, i) { + var meta = chart.getDatasetMeta(0); + var ds = data.datasets[0]; + var arc = meta.data[i]; + var custom = arc.custom || {}; + var valueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + var arcOpts = chart.options.elements.arc; + var fill = custom.backgroundColor ? custom.backgroundColor : valueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor); + var stroke = custom.borderColor ? custom.borderColor : valueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor); + var bw = custom.borderWidth ? custom.borderWidth : valueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth); + + return { + text: label, + fillStyle: fill, + strokeStyle: stroke, + lineWidth: bw, + hidden: isNaN(ds.data[i]) || meta.data[i].hidden, + + // Extra data used for toggling the correct item + index: i + }; + }); + } + return []; + } }, - calculateXLabelRotation : function(){ - //Get the width of each grid by calculating the difference - //between x offsets between 0 and 1. - this.ctx.font = this.font; + onClick: function(e, legendItem) { + var index = legendItem.index; + var chart = this.chart; + var i, ilen, meta; - var firstWidth = this.ctx.measureText(this.xLabels[0]).width, - lastWidth = this.ctx.measureText(this.xLabels[this.xLabels.length - 1]).width, - firstRotated, - lastRotated; + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + meta = chart.getDatasetMeta(i); + meta.data[index].hidden = !meta.data[index].hidden; + } + chart.update(); + } + }, - this.xScalePaddingRight = lastWidth/2 + 3; - this.xScalePaddingLeft = (firstWidth/2 > this.yLabelWidth + 10) ? firstWidth/2 : this.yLabelWidth + 10; + // Need to override these to give a nice default + tooltips: { + callbacks: { + title: function() { + return ''; + }, + label: function(item, data) { + return data.labels[item.index] + ': ' + item.yLabel; + } + } + } +}); - this.xLabelRotation = 0; - if (this.display){ - var originalLabelWidth = longestText(this.ctx,this.font,this.xLabels), - cosRotation, - firstRotatedWidth; - this.xLabelWidth = originalLabelWidth; - //Allow 3 pixels x2 padding either side for label readability - var xGridWidth = Math.floor(this.calculateX(1) - this.calculateX(0)) - 6; +module.exports = function(Chart) { - //Max label rotate should be 90 - also act as a loop counter - while ((this.xLabelWidth > xGridWidth && this.xLabelRotation === 0) || (this.xLabelWidth > xGridWidth && this.xLabelRotation <= 90 && this.xLabelRotation > 0)){ - cosRotation = Math.cos(toRadians(this.xLabelRotation)); + Chart.controllers.polarArea = Chart.DatasetController.extend({ - firstRotated = cosRotation * firstWidth; - lastRotated = cosRotation * lastWidth; + dataElementType: elements.Arc, - // We're right aligning the text now. - if (firstRotated + this.fontSize / 2 > this.yLabelWidth + 8){ - this.xScalePaddingLeft = firstRotated + this.fontSize / 2; - } - this.xScalePaddingRight = this.fontSize/2; + linkScales: helpers.noop, + update: function(reset) { + var me = this; + var chart = me.chart; + var chartArea = chart.chartArea; + var meta = me.getMeta(); + var opts = chart.options; + var arcOpts = opts.elements.arc; + var minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top); + chart.outerRadius = Math.max((minSize - arcOpts.borderWidth / 2) / 2, 0); + chart.innerRadius = Math.max(opts.cutoutPercentage ? (chart.outerRadius / 100) * (opts.cutoutPercentage) : 1, 0); + chart.radiusLength = (chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount(); - this.xLabelRotation++; - this.xLabelWidth = cosRotation * originalLabelWidth; + me.outerRadius = chart.outerRadius - (chart.radiusLength * me.index); + me.innerRadius = me.outerRadius - chart.radiusLength; - } - if (this.xLabelRotation > 0){ - this.endPoint -= Math.sin(toRadians(this.xLabelRotation))*originalLabelWidth + 3; - } - } - else{ - this.xLabelWidth = 0; - this.xScalePaddingRight = this.padding; - this.xScalePaddingLeft = this.padding; - } + meta.count = me.countVisibleElements(); + helpers.each(meta.data, function(arc, index) { + me.updateElement(arc, index, reset); + }); }, - // Needs to be overidden in each Chart type - // Otherwise we need to pass all the data into the scale class - calculateYRange: noop, - drawingArea: function(){ - return this.startPoint - this.endPoint; - }, - calculateY : function(value){ - var scalingFactor = this.drawingArea() / (this.min - this.max); - return this.endPoint - (scalingFactor * (value - this.min)); - }, - calculateX : function(index){ - var isRotated = (this.xLabelRotation > 0), - // innerWidth = (this.offsetGridLines) ? this.width - offsetLeft - this.padding : this.width - (offsetLeft + halfLabelWidth * 2) - this.padding, - innerWidth = this.width - (this.xScalePaddingLeft + this.xScalePaddingRight), - valueWidth = innerWidth/Math.max((this.valuesCount - ((this.offsetGridLines) ? 0 : 1)), 1), - valueOffset = (valueWidth * index) + this.xScalePaddingLeft; - if (this.offsetGridLines){ - valueOffset += (valueWidth/2); + updateElement: function(arc, index, reset) { + var me = this; + var chart = me.chart; + var dataset = me.getDataset(); + var opts = chart.options; + var animationOpts = opts.animation; + var scale = chart.scale; + var labels = chart.data.labels; + + var circumference = me.calculateCircumference(dataset.data[index]); + var centerX = scale.xCenter; + var centerY = scale.yCenter; + + // If there is NaN data before us, we need to calculate the starting angle correctly. + // We could be way more efficient here, but its unlikely that the polar area chart will have a lot of data + var visibleCount = 0; + var meta = me.getMeta(); + for (var i = 0; i < index; ++i) { + if (!isNaN(dataset.data[i]) && !meta.data[i].hidden) { + ++visibleCount; + } } - return Math.round(valueOffset); - }, - update : function(newProps){ - helpers.extend(this, newProps); - this.fit(); - }, - draw : function(){ - var ctx = this.ctx, - yLabelGap = (this.endPoint - this.startPoint) / this.steps, - xStart = Math.round(this.xScalePaddingLeft); - if (this.display){ - ctx.fillStyle = this.textColor; - ctx.font = this.font; - each(this.yLabels,function(labelString,index){ - var yLabelCenter = this.endPoint - (yLabelGap * index), - linePositionY = Math.round(yLabelCenter), - drawHorizontalLine = this.showHorizontalLines; + // var negHalfPI = -0.5 * Math.PI; + var datasetStartAngle = opts.startAngle; + var distance = arc.hidden ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + var startAngle = datasetStartAngle + (circumference * visibleCount); + var endAngle = startAngle + (arc.hidden ? 0 : circumference); + + var resetRadius = animationOpts.animateScale ? 0 : scale.getDistanceFromCenterForValue(dataset.data[index]); + + helpers.extend(arc, { + // Utility + _datasetIndex: me.index, + _index: index, + _scale: scale, + + // Desired view properties + _model: { + x: centerX, + y: centerY, + innerRadius: 0, + outerRadius: reset ? resetRadius : distance, + startAngle: reset && animationOpts.animateRotate ? datasetStartAngle : startAngle, + endAngle: reset && animationOpts.animateRotate ? datasetStartAngle : endAngle, + label: helpers.valueAtIndexOrDefault(labels, index, labels[index]) + } + }); - ctx.textAlign = "right"; - ctx.textBaseline = "middle"; - if (this.showLabels){ - ctx.fillText(labelString,xStart - 10,yLabelCenter); - } + // Apply border and fill style + me.removeHoverStyle(arc); - // This is X axis, so draw it - if (index === 0 && !drawHorizontalLine){ - drawHorizontalLine = true; - } + arc.pivot(); + }, - if (drawHorizontalLine){ - ctx.beginPath(); - } + removeHoverStyle: function(arc) { + Chart.DatasetController.prototype.removeHoverStyle.call(this, arc, this.chart.options.elements.arc); + }, - if (index > 0){ - // This is a grid line in the centre, so drop that - ctx.lineWidth = this.gridLineWidth; - ctx.strokeStyle = this.gridLineColor; - } else { - // This is the first line on the scale - ctx.lineWidth = this.lineWidth; - ctx.strokeStyle = this.lineColor; - } + countVisibleElements: function() { + var dataset = this.getDataset(); + var meta = this.getMeta(); + var count = 0; - linePositionY += helpers.aliasPixel(ctx.lineWidth); + helpers.each(meta.data, function(element, index) { + if (!isNaN(dataset.data[index]) && !element.hidden) { + count++; + } + }); - if(drawHorizontalLine){ - ctx.moveTo(xStart, linePositionY); - ctx.lineTo(this.width, linePositionY); - ctx.stroke(); - ctx.closePath(); - } + return count; + }, - ctx.lineWidth = this.lineWidth; - ctx.strokeStyle = this.lineColor; - ctx.beginPath(); - ctx.moveTo(xStart - 5, linePositionY); - ctx.lineTo(xStart, linePositionY); - ctx.stroke(); - ctx.closePath(); - - },this); - - each(this.xLabels,function(label,index){ - var xPos = this.calculateX(index) + aliasPixel(this.lineWidth), - // Check to see if line/bar here and decide where to place the line - linePos = this.calculateX(index - (this.offsetGridLines ? 0.5 : 0)) + aliasPixel(this.lineWidth), - isRotated = (this.xLabelRotation > 0), - drawVerticalLine = this.showVerticalLines; - - // This is Y axis, so draw it - if (index === 0 && !drawVerticalLine){ - drawVerticalLine = true; - } + calculateCircumference: function(value) { + var count = this.getMeta().count; + if (count > 0 && !isNaN(value)) { + return (2 * Math.PI) / count; + } + return 0; + } + }); +}; + })(); +}); - if (drawVerticalLine){ - ctx.beginPath(); - } +require.register("chart.js/src/controllers/controller.radar.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - if (index > 0){ - // This is a grid line in the centre, so drop that - ctx.lineWidth = this.gridLineWidth; - ctx.strokeStyle = this.gridLineColor; - } else { - // This is the first line on the scale - ctx.lineWidth = this.lineWidth; - ctx.strokeStyle = this.lineColor; - } +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - if (drawVerticalLine){ - ctx.moveTo(linePos,this.endPoint); - ctx.lineTo(linePos,this.startPoint - 3); - ctx.stroke(); - ctx.closePath(); - } +defaults._set('radar', { + scale: { + type: 'radialLinear' + }, + elements: { + line: { + tension: 0 // no bezier in radar + } + } +}); +module.exports = function(Chart) { + + Chart.controllers.radar = Chart.DatasetController.extend({ + + datasetElementType: elements.Line, + + dataElementType: elements.Point, + + linkScales: helpers.noop, + + update: function(reset) { + var me = this; + var meta = me.getMeta(); + var line = meta.dataset; + var points = meta.data; + var custom = line.custom || {}; + var dataset = me.getDataset(); + var lineElementOptions = me.chart.options.elements.line; + var scale = me.chart.scale; + + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.tension !== undefined) && (dataset.lineTension === undefined)) { + dataset.lineTension = dataset.tension; + } + + helpers.extend(meta.dataset, { + // Utility + _datasetIndex: me.index, + _scale: scale, + // Data + _children: points, + _loop: true, + // Model + _model: { + // Appearance + tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, lineElementOptions.tension), + backgroundColor: custom.backgroundColor ? custom.backgroundColor : (dataset.backgroundColor || lineElementOptions.backgroundColor), + borderWidth: custom.borderWidth ? custom.borderWidth : (dataset.borderWidth || lineElementOptions.borderWidth), + borderColor: custom.borderColor ? custom.borderColor : (dataset.borderColor || lineElementOptions.borderColor), + fill: custom.fill ? custom.fill : (dataset.fill !== undefined ? dataset.fill : lineElementOptions.fill), + borderCapStyle: custom.borderCapStyle ? custom.borderCapStyle : (dataset.borderCapStyle || lineElementOptions.borderCapStyle), + borderDash: custom.borderDash ? custom.borderDash : (dataset.borderDash || lineElementOptions.borderDash), + borderDashOffset: custom.borderDashOffset ? custom.borderDashOffset : (dataset.borderDashOffset || lineElementOptions.borderDashOffset), + borderJoinStyle: custom.borderJoinStyle ? custom.borderJoinStyle : (dataset.borderJoinStyle || lineElementOptions.borderJoinStyle), + } + }); - ctx.lineWidth = this.lineWidth; - ctx.strokeStyle = this.lineColor; + meta.dataset.pivot(); + // Update Points + helpers.each(points, function(point, index) { + me.updateElement(point, index, reset); + }, me); - // Small lines at the bottom of the base grid line - ctx.beginPath(); - ctx.moveTo(linePos,this.endPoint); - ctx.lineTo(linePos,this.endPoint + 5); - ctx.stroke(); - ctx.closePath(); + // Update bezier control points + me.updateBezierControlPoints(); + }, + updateElement: function(point, index, reset) { + var me = this; + var custom = point.custom || {}; + var dataset = me.getDataset(); + var scale = me.chart.scale; + var pointElementOptions = me.chart.options.elements.point; + var pointPosition = scale.getPointPositionForValue(index, dataset.data[index]); + + // Compatibility: If the properties are defined with only the old name, use those values + if ((dataset.radius !== undefined) && (dataset.pointRadius === undefined)) { + dataset.pointRadius = dataset.radius; + } + if ((dataset.hitRadius !== undefined) && (dataset.pointHitRadius === undefined)) { + dataset.pointHitRadius = dataset.hitRadius; + } + + helpers.extend(point, { + // Utility + _datasetIndex: me.index, + _index: index, + _scale: scale, + + // Desired view properties + _model: { + x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales + y: reset ? scale.yCenter : pointPosition.y, + + // Appearance + tension: custom.tension ? custom.tension : helpers.valueOrDefault(dataset.lineTension, me.chart.options.elements.line.tension), + radius: custom.radius ? custom.radius : helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius), + backgroundColor: custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor), + borderColor: custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor), + borderWidth: custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth), + pointStyle: custom.pointStyle ? custom.pointStyle : helpers.valueAtIndexOrDefault(dataset.pointStyle, index, pointElementOptions.pointStyle), + + // Tooltip + hitRadius: custom.hitRadius ? custom.hitRadius : helpers.valueAtIndexOrDefault(dataset.pointHitRadius, index, pointElementOptions.hitRadius) + } + }); - ctx.save(); - ctx.translate(xPos,(isRotated) ? this.endPoint + 12 : this.endPoint + 8); - ctx.rotate(toRadians(this.xLabelRotation)*-1); - ctx.font = this.font; - ctx.textAlign = (isRotated) ? "right" : "center"; - ctx.textBaseline = (isRotated) ? "middle" : "top"; - ctx.fillText(label, 0, 0); - ctx.restore(); - },this); + point._model.skip = custom.skip ? custom.skip : (isNaN(point._model.x) || isNaN(point._model.y)); + }, + updateBezierControlPoints: function() { + var chartArea = this.chart.chartArea; + var meta = this.getMeta(); + + helpers.each(meta.data, function(point, index) { + var model = point._model; + var controlPoints = helpers.splineCurve( + helpers.previousItem(meta.data, index, true)._model, + model, + helpers.nextItem(meta.data, index, true)._model, + model.tension + ); - } - } + // Prevent the bezier going outside of the bounds of the graph + model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, chartArea.right), chartArea.left); + model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, chartArea.bottom), chartArea.top); - }); + model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, chartArea.right), chartArea.left); + model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, chartArea.bottom), chartArea.top); - Chart.RadialScale = Chart.Element.extend({ - initialize: function(){ - this.size = min([this.height, this.width]); - this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2); + // Now pivot the point for animation + point.pivot(); + }); }, - calculateCenterOffset: function(value){ - // Take into account half font size + the yPadding of the top value - var scalingFactor = this.drawingArea / (this.max - this.min); - return (value - this.min) * scalingFactor; + setHoverStyle: function(point) { + // Point + var dataset = this.chart.data.datasets[point._datasetIndex]; + var custom = point.custom || {}; + var index = point._index; + var model = point._model; + + model.radius = custom.hoverRadius ? custom.hoverRadius : helpers.valueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); + model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.getHoverColor(model.backgroundColor)); + model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.getHoverColor(model.borderColor)); + model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : helpers.valueAtIndexOrDefault(dataset.pointHoverBorderWidth, index, model.borderWidth); }, - update : function(){ - if (!this.lineArc){ - this.setScaleSize(); - } else { - this.drawingArea = (this.display) ? (this.size/2) - (this.fontSize/2 + this.backdropPaddingY) : (this.size/2); - } - this.buildYLabels(); - }, - buildYLabels: function(){ - this.yLabels = []; - - var stepDecimalPlaces = getDecimalPlaces(this.stepValue); - - for (var i=0; i<=this.steps; i++){ - this.yLabels.push(template(this.templateString,{value:(this.min + (i * this.stepValue)).toFixed(stepDecimalPlaces)})); - } - }, - getCircumference : function(){ - return ((Math.PI*2) / this.valuesCount); - }, - setScaleSize: function(){ - /* - * Right, this is really confusing and there is a lot of maths going on here - * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 - * - * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif - * - * Solution: - * - * We assume the radius of the polygon is half the size of the canvas at first - * at each index we check if the text overlaps. - * - * Where it does, we store that angle and that index. - * - * After finding the largest index and angle we calculate how much we need to remove - * from the shape radius to move the point inwards by that x. - * - * We average the left and right distances to get the maximum shape radius that can fit in the box - * along with labels. - * - * Once we have that, we can find the centre point for the chart, by taking the x text protrusion - * on each side, removing that from the size, halving it and adding the left x protrusion width. - * - * This will mean we have a shape fitted to the canvas, as large as it can be with the labels - * and position it in the most space efficient manner - * - * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif - */ - - - // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. - // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points - var largestPossibleRadius = min([(this.height/2 - this.pointLabelFontSize - 5), this.width/2]), - pointPosition, - i, - textWidth, - halfTextWidth, - furthestRight = this.width, - furthestRightIndex, - furthestRightAngle, - furthestLeft = 0, - furthestLeftIndex, - furthestLeftAngle, - xProtrusionLeft, - xProtrusionRight, - radiusReductionRight, - radiusReductionLeft, - maxWidthRadius; - this.ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily); - for (i=0;i furthestRight) { - furthestRight = pointPosition.x + halfTextWidth; - furthestRightIndex = i; - } - if (pointPosition.x - halfTextWidth < furthestLeft) { - furthestLeft = pointPosition.x - halfTextWidth; - furthestLeftIndex = i; - } - } - else if (i < this.valuesCount/2) { - // Less than half the values means we'll left align the text - if (pointPosition.x + textWidth > furthestRight) { - furthestRight = pointPosition.x + textWidth; - furthestRightIndex = i; - } - } - else if (i > this.valuesCount/2){ - // More than half the values means we'll right align the text - if (pointPosition.x - textWidth < furthestLeft) { - furthestLeft = pointPosition.x - textWidth; - furthestLeftIndex = i; - } - } - } - xProtrusionLeft = furthestLeft; + removeHoverStyle: function(point) { + var dataset = this.chart.data.datasets[point._datasetIndex]; + var custom = point.custom || {}; + var index = point._index; + var model = point._model; + var pointElementOptions = this.chart.options.elements.point; - xProtrusionRight = Math.ceil(furthestRight - this.width); + model.radius = custom.radius ? custom.radius : helpers.valueAtIndexOrDefault(dataset.pointRadius, index, pointElementOptions.radius); + model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : helpers.valueAtIndexOrDefault(dataset.pointBackgroundColor, index, pointElementOptions.backgroundColor); + model.borderColor = custom.borderColor ? custom.borderColor : helpers.valueAtIndexOrDefault(dataset.pointBorderColor, index, pointElementOptions.borderColor); + model.borderWidth = custom.borderWidth ? custom.borderWidth : helpers.valueAtIndexOrDefault(dataset.pointBorderWidth, index, pointElementOptions.borderWidth); + } + }); +}; + })(); +}); - furthestRightAngle = this.getIndexAngle(furthestRightIndex); +require.register("chart.js/src/controllers/controller.scatter.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - furthestLeftAngle = this.getIndexAngle(furthestLeftIndex); +var defaults = require('../core/core.defaults'); - radiusReductionRight = xProtrusionRight / Math.sin(furthestRightAngle + Math.PI/2); +defaults._set('scatter', { + hover: { + mode: 'single' + }, - radiusReductionLeft = xProtrusionLeft / Math.sin(furthestLeftAngle + Math.PI/2); + scales: { + xAxes: [{ + id: 'x-axis-1', // need an ID so datasets can reference the scale + type: 'linear', // scatter should not use a category axis + position: 'bottom' + }], + yAxes: [{ + id: 'y-axis-1', + type: 'linear', + position: 'left' + }] + }, - // Ensure we actually need to reduce the size of the chart - radiusReductionRight = (isNumber(radiusReductionRight)) ? radiusReductionRight : 0; - radiusReductionLeft = (isNumber(radiusReductionLeft)) ? radiusReductionLeft : 0; + showLines: false, - this.drawingArea = largestPossibleRadius - (radiusReductionLeft + radiusReductionRight)/2; + tooltips: { + callbacks: { + title: function() { + return ''; // doesn't make sense for scatter since data are formatted as a point + }, + label: function(item) { + return '(' + item.xLabel + ', ' + item.yLabel + ')'; + } + } + } +}); - //this.drawingArea = min([maxWidthRadius, (this.height - (2 * (this.pointLabelFontSize + 5)))/2]) - this.setCenterPoint(radiusReductionLeft, radiusReductionRight); +module.exports = function(Chart) { - }, - setCenterPoint: function(leftMovement, rightMovement){ + // Scatter charts use line controllers + Chart.controllers.scatter = Chart.controllers.line; - var maxRight = this.width - rightMovement - this.drawingArea, - maxLeft = leftMovement + this.drawingArea; +}; + })(); +}); - this.xCenter = (maxLeft + maxRight)/2; - // Always vertically in the centre as the text height doesn't change - this.yCenter = (this.height/2); - }, +require.register("chart.js/src/core/core.animation.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /* global window: false */ +'use strict'; - getIndexAngle : function(index){ - var angleMultiplier = (Math.PI * 2) / this.valuesCount; - // Start from the top instead of right, so remove a quarter of the circle +var defaults = require('./core.defaults'); +var Element = require('./core.element'); +var helpers = require('../helpers/index'); - return index * angleMultiplier - (Math.PI/2); - }, - getPointPosition : function(index, distanceFromCenter){ - var thisAngle = this.getIndexAngle(index); - return { - x : (Math.cos(thisAngle) * distanceFromCenter) + this.xCenter, - y : (Math.sin(thisAngle) * distanceFromCenter) + this.yCenter - }; - }, - draw: function(){ - if (this.display){ - var ctx = this.ctx; - each(this.yLabels, function(label, index){ - // Don't draw a centre value - if (index > 0){ - var yCenterOffset = index * (this.drawingArea/this.steps), - yHeight = this.yCenter - yCenterOffset, - pointPosition; +defaults._set('global', { + animation: { + duration: 1000, + easing: 'easeOutQuart', + onProgress: helpers.noop, + onComplete: helpers.noop + } +}); - // Draw circular lines around the scale - if (this.lineWidth > 0){ - ctx.strokeStyle = this.lineColor; - ctx.lineWidth = this.lineWidth; - - if(this.lineArc){ - ctx.beginPath(); - ctx.arc(this.xCenter, this.yCenter, yCenterOffset, 0, Math.PI*2); - ctx.closePath(); - ctx.stroke(); - } else{ - ctx.beginPath(); - for (var i=0;i= 0; i--) { - if (this.angleLineWidth > 0){ - var outerPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max)); - ctx.beginPath(); - ctx.moveTo(this.xCenter, this.yCenter); - ctx.lineTo(outerPosition.x, outerPosition.y); - ctx.stroke(); - ctx.closePath(); - } - // Extra 3px out for some label spacing - var pointLabelPosition = this.getPointPosition(i, this.calculateCenterOffset(this.max) + 5); - ctx.font = fontString(this.pointLabelFontSize,this.pointLabelFontStyle,this.pointLabelFontFamily); - ctx.fillStyle = this.pointLabelFontColor; - - var labelsCount = this.labels.length, - halfLabelsCount = this.labels.length/2, - quarterLabelsCount = halfLabelsCount/2, - upperHalf = (i < quarterLabelsCount || i > labelsCount - quarterLabelsCount), - exactQuarter = (i === quarterLabelsCount || i === labelsCount - quarterLabelsCount); - if (i === 0){ - ctx.textAlign = 'center'; - } else if(i === halfLabelsCount){ - ctx.textAlign = 'center'; - } else if (i < halfLabelsCount){ - ctx.textAlign = 'left'; - } else { - ctx.textAlign = 'right'; - } +module.exports = function(Chart) { - // Set the correct text baseline based on outer positioning - if (exactQuarter){ - ctx.textBaseline = 'middle'; - } else if (upperHalf){ - ctx.textBaseline = 'bottom'; - } else { - ctx.textBaseline = 'top'; - } + Chart.Animation = Element.extend({ + chart: null, // the animation associated chart instance + currentStep: 0, // the current animation step + numSteps: 60, // default number of steps + easing: '', // the easing to use for this animation + render: null, // render function used by the animation service - ctx.fillText(this.labels[i], pointLabelPosition.x, pointLabelPosition.y); - } - } - } - } + onAnimationProgress: null, // user specified callback to fire on each step of the animation + onAnimationComplete: null, // user specified callback to fire when the animation finishes }); - // Attach global event to resize each chart instance when the browser resizes - helpers.addEvent(window, "resize", (function(){ - // Basic debounce of resize function so it doesn't hurt performance when resizing browser. - var timeout; - return function(){ - clearTimeout(timeout); - timeout = setTimeout(function(){ - each(Chart.instances,function(instance){ - // If the responsive flag is set in the chart instance config - // Cascade the resize event down to the chart. - if (instance.options.responsive){ - instance.resize(instance.render, true); - } - }); - }, 50); - }; - })()); + Chart.animationService = { + frameDuration: 17, + animations: [], + dropFrames: 0, + request: null, + /** + * @param {Chart} chart - The chart to animate. + * @param {Chart.Animation} animation - The animation that we will animate. + * @param {Number} duration - The animation duration in ms. + * @param {Boolean} lazy - if true, the chart is not marked as animating to enable more responsive interactions + */ + addAnimation: function(chart, animation, duration, lazy) { + var animations = this.animations; + var i, ilen; - if (amd) { - define(function(){ - return Chart; - }); - } else if (typeof module === 'object' && module.exports) { - module.exports = Chart; - } + animation.chart = chart; - root.Chart = Chart; + if (!lazy) { + chart.animating = true; + } - Chart.noConflict = function(){ - root.Chart = previous; - return Chart; - }; + for (i = 0, ilen = animations.length; i < ilen; ++i) { + if (animations[i].chart === chart) { + animations[i] = animation; + return; + } + } -}).call(this); + animations.push(animation); -(function(){ - "use strict"; + // If there are no animations queued, manually kickstart a digest, for lack of a better word + if (animations.length === 1) { + this.requestAnimationFrame(); + } + }, - var root = this, - Chart = root.Chart, - helpers = Chart.helpers; + cancelAnimation: function(chart) { + var index = helpers.findIndex(this.animations, function(animation) { + return animation.chart === chart; + }); + if (index !== -1) { + this.animations.splice(index, 1); + chart.animating = false; + } + }, - var defaultConfig = { - //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value - scaleBeginAtZero : true, + requestAnimationFrame: function() { + var me = this; + if (me.request === null) { + // Skip animation frame requests until the active one is executed. + // This can happen when processing mouse events, e.g. 'mousemove' + // and 'mouseout' events will trigger multiple renders. + me.request = helpers.requestAnimFrame.call(window, function() { + me.request = null; + me.startDigest(); + }); + } + }, - //Boolean - Whether grid lines are shown across the chart - scaleShowGridLines : true, + /** + * @private + */ + startDigest: function() { + var me = this; + var startTime = Date.now(); + var framesToDrop = 0; - //String - Colour of the grid lines - scaleGridLineColor : "rgba(0,0,0,.05)", + if (me.dropFrames > 1) { + framesToDrop = Math.floor(me.dropFrames); + me.dropFrames = me.dropFrames % 1; + } - //Number - Width of the grid lines - scaleGridLineWidth : 1, + me.advance(1 + framesToDrop); - //Boolean - Whether to show horizontal lines (except X axis) - scaleShowHorizontalLines: true, + var endTime = Date.now(); - //Boolean - Whether to show vertical lines (except Y axis) - scaleShowVerticalLines: true, + me.dropFrames += (endTime - startTime) / me.frameDuration; - //Boolean - If there is a stroke on each bar - barShowStroke : true, + // Do we have more stuff to animate? + if (me.animations.length > 0) { + me.requestAnimationFrame(); + } + }, - //Number - Pixel width of the bar stroke - barStrokeWidth : 2, + /** + * @private + */ + advance: function(count) { + var animations = this.animations; + var animation, chart; + var i = 0; - //Number - Spacing between each of the X value sets - barValueSpacing : 5, + while (i < animations.length) { + animation = animations[i]; + chart = animation.chart; - //Number - Spacing between data sets within X values - barDatasetSpacing : 1, + animation.currentStep = (animation.currentStep || 0) + count; + animation.currentStep = Math.min(animation.currentStep, animation.numSteps); - //String - A legend template - legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + helpers.callback(animation.render, [chart, animation], chart); + helpers.callback(animation.onAnimationProgress, [animation], chart); + if (animation.currentStep >= animation.numSteps) { + helpers.callback(animation.onAnimationComplete, [animation], chart); + chart.animating = false; + animations.splice(i, 1); + } else { + ++i; + } + } + } }; + /** + * Provided for backward compatibility, use Chart.Animation instead + * @prop Chart.Animation#animationObject + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ + Object.defineProperty(Chart.Animation.prototype, 'animationObject', { + get: function() { + return this; + } + }); - Chart.Type.extend({ - name: "Bar", - defaults : defaultConfig, - initialize: function(data){ - - //Expose options as a scope variable here so we can access it in the ScaleClass - var options = this.options; + /** + * Provided for backward compatibility, use Chart.Animation#chart instead + * @prop Chart.Animation#chartInstance + * @deprecated since version 2.6.0 + * @todo remove at version 3 + */ + Object.defineProperty(Chart.Animation.prototype, 'chartInstance', { + get: function() { + return this.chart; + }, + set: function(value) { + this.chart = value; + } + }); - this.ScaleClass = Chart.Scale.extend({ - offsetGridLines : true, - calculateBarX : function(datasetCount, datasetIndex, barIndex){ - //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar - var xWidth = this.calculateBaseWidth(), - xAbsolute = this.calculateX(barIndex) - (xWidth/2), - barWidth = this.calculateBarWidth(datasetCount); +}; + })(); +}); - return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2; - }, - calculateBaseWidth : function(){ - return (this.calculateX(1) - this.calculateX(0)) - (2*options.barValueSpacing); - }, - calculateBarWidth : function(datasetCount){ - //The padding between datasets is to the right of each bar, providing that there are more than 1 dataset - var baseWidth = this.calculateBaseWidth() - ((datasetCount - 1) * options.barDatasetSpacing); +require.register("chart.js/src/core/core.controller.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - return (baseWidth / datasetCount); - } - }); +var defaults = require('./core.defaults'); +var helpers = require('../helpers/index'); +var Interaction = require('./core.interaction'); +var platform = require('../platforms/platform'); - this.datasets = []; +module.exports = function(Chart) { + var plugins = Chart.plugins; - //Set up tooltip events on the chart - if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activeBars = (evt.type !== 'mouseout') ? this.getBarsAtEvent(evt) : []; + // Create a dictionary of chart types, to allow for extension of existing types + Chart.types = {}; - this.eachBars(function(bar){ - bar.restore(['fillColor', 'strokeColor']); - }); - helpers.each(activeBars, function(activeBar){ - activeBar.fillColor = activeBar.highlightFill; - activeBar.strokeColor = activeBar.highlightStroke; - }); - this.showTooltip(activeBars); - }); - } + // Store a reference to each instance - allowing us to globally resize chart instances on window resize. + // Destroy method on the chart will remove the instance of the chart from this reference. + Chart.instances = {}; - //Declare the extension of the default point, to cater for the options passed in to the constructor - this.BarClass = Chart.Rectangle.extend({ - strokeWidth : this.options.barStrokeWidth, - showStroke : this.options.barShowStroke, - ctx : this.chart.ctx - }); + // Controllers available for dataset visualization eg. bar, line, slice, etc. + Chart.controllers = {}; - //Iterate through each of the datasets, and build this into a property of the chart - helpers.each(data.datasets,function(dataset,datasetIndex){ + /** + * Initializes the given config with global and chart default values. + */ + function initConfig(config) { + config = config || {}; - var datasetObject = { - label : dataset.label || null, - fillColor : dataset.fillColor, - strokeColor : dataset.strokeColor, - bars : [] - }; + // Do NOT use configMerge() for the data object because this method merges arrays + // and so would change references to labels and datasets, preventing data updates. + var data = config.data = config.data || {}; + data.datasets = data.datasets || []; + data.labels = data.labels || []; - this.datasets.push(datasetObject); + config.options = helpers.configMerge( + defaults.global, + defaults[config.type], + config.options || {}); - helpers.each(dataset.data,function(dataPoint,index){ - //Add a new point for each piece of data, passing any required data to draw. - datasetObject.bars.push(new this.BarClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.strokeColor, - fillColor : dataset.fillColor, - highlightFill : dataset.highlightFill || dataset.fillColor, - highlightStroke : dataset.highlightStroke || dataset.strokeColor - })); - },this); + return config; + } - },this); + /** + * Updates the config of the chart + * @param chart {Chart} chart to update the options for + */ + function updateConfig(chart) { + var newOptions = chart.options; + + // Update Scale(s) with options + if (newOptions.scale) { + chart.scale.options = newOptions.scale; + } else if (newOptions.scales) { + newOptions.scales.xAxes.concat(newOptions.scales.yAxes).forEach(function(scaleOptions) { + chart.scales[scaleOptions.id].options = scaleOptions; + }); + } - this.buildScale(data.labels); + // Tooltip + chart.tooltip._options = newOptions.tooltips; + } - this.BarClass.prototype.base = this.scale.endPoint; + function positionIsHorizontal(position) { + return position === 'top' || position === 'bottom'; + } - this.eachBars(function(bar, index, datasetIndex){ - helpers.extend(bar, { - width : this.scale.calculateBarWidth(this.datasets.length), - x: this.scale.calculateBarX(this.datasets.length, datasetIndex, index), - y: this.scale.endPoint - }); - bar.save(); - }, this); + helpers.extend(Chart.prototype, /** @lends Chart */ { + /** + * @private + */ + construct: function(item, config) { + var me = this; + + config = initConfig(config); + + var context = platform.acquireContext(item, config); + var canvas = context && context.canvas; + var height = canvas && canvas.height; + var width = canvas && canvas.width; + + me.id = helpers.uid(); + me.ctx = context; + me.canvas = canvas; + me.config = config; + me.width = width; + me.height = height; + me.aspectRatio = height ? width / height : null; + me.options = config.options; + me._bufferedRender = false; + + /** + * Provided for backward compatibility, Chart and Chart.Controller have been merged, + * the "instance" still need to be defined since it might be called from plugins. + * @prop Chart#chart + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ + me.chart = me; + me.controller = me; // chart.chart.controller #inception - this.render(); - }, - update : function(){ - this.scale.update(); - // Reset any highlight colours before updating. - helpers.each(this.activeElements, function(activeElement){ - activeElement.restore(['fillColor', 'strokeColor']); - }); + // Add the chart instance to the global namespace + Chart.instances[me.id] = me; - this.eachBars(function(bar){ - bar.save(); - }); - this.render(); - }, - eachBars : function(callback){ - helpers.each(this.datasets,function(dataset, datasetIndex){ - helpers.each(dataset.bars, callback, this, datasetIndex); - },this); - }, - getBarsAtEvent : function(e){ - var barsArray = [], - eventPosition = helpers.getRelativePosition(e), - datasetIterator = function(dataset){ - barsArray.push(dataset.bars[barIndex]); + // Define alias to the config data: `chart.data === chart.config.data` + Object.defineProperty(me, 'data', { + get: function() { + return me.config.data; }, - barIndex; - - for (var datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) { - for (barIndex = 0; barIndex < this.datasets[datasetIndex].bars.length; barIndex++) { - if (this.datasets[datasetIndex].bars[barIndex].inRange(eventPosition.x,eventPosition.y)){ - helpers.each(this.datasets, datasetIterator); - return barsArray; - } + set: function(value) { + me.config.data = value; } + }); + + if (!context || !canvas) { + // The given item is not a compatible context2d element, let's return before finalizing + // the chart initialization but after setting basic chart / controller properties that + // can help to figure out that the chart is not valid (e.g chart.canvas !== null); + // https://github.com/chartjs/Chart.js/issues/2807 + console.error("Failed to create chart: can't acquire context from the given item"); + return; } - return barsArray; + me.initialize(); + me.update(); }, - buildScale : function(labels){ - var self = this; - - var dataTotal = function(){ - var values = []; - self.eachBars(function(bar){ - values.push(bar.value); - }); - return values; - }; - - var scaleOptions = { - templateString : this.options.scaleLabel, - height : this.chart.height, - width : this.chart.width, - ctx : this.chart.ctx, - textColor : this.options.scaleFontColor, - fontSize : this.options.scaleFontSize, - fontStyle : this.options.scaleFontStyle, - fontFamily : this.options.scaleFontFamily, - valuesCount : labels.length, - beginAtZero : this.options.scaleBeginAtZero, - integersOnly : this.options.scaleIntegersOnly, - calculateYRange: function(currentHeight){ - var updatedRanges = helpers.calculateScaleRange( - dataTotal(), - currentHeight, - this.fontSize, - this.beginAtZero, - this.integersOnly - ); - helpers.extend(this, updatedRanges); - }, - xLabels : labels, - font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), - lineWidth : this.options.scaleLineWidth, - lineColor : this.options.scaleLineColor, - showHorizontalLines : this.options.scaleShowHorizontalLines, - showVerticalLines : this.options.scaleShowVerticalLines, - gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, - gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", - padding : (this.options.showScale) ? 0 : (this.options.barShowStroke) ? this.options.barStrokeWidth : 0, - showLabels : this.options.scaleShowLabels, - display : this.options.showScale - }; - if (this.options.scaleOverride){ - helpers.extend(scaleOptions, { - calculateYRange: helpers.noop, - steps: this.options.scaleSteps, - stepValue: this.options.scaleStepWidth, - min: this.options.scaleStartValue, - max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) - }); - } + /** + * @private + */ + initialize: function() { + var me = this; - this.scale = new this.ScaleClass(scaleOptions); - }, - addData : function(valuesArray,label){ - //Map the values array for each of the datasets - helpers.each(valuesArray,function(value,datasetIndex){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].bars.push(new this.BarClass({ - value : value, - label : label, - x: this.scale.calculateBarX(this.datasets.length, datasetIndex, this.scale.valuesCount+1), - y: this.scale.endPoint, - width : this.scale.calculateBarWidth(this.datasets.length), - base : this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].strokeColor, - fillColor : this.datasets[datasetIndex].fillColor - })); - },this); - - this.scale.addXLabel(label); - //Then re-render the chart. - this.update(); - }, - removeData : function(){ - this.scale.removeXLabel(); - //Then re-render the chart. - helpers.each(this.datasets,function(dataset){ - dataset.bars.shift(); - },this); - this.update(); - }, - reflow : function(){ - helpers.extend(this.BarClass.prototype,{ - y: this.scale.endPoint, - base : this.scale.endPoint - }); - var newScaleProps = helpers.extend({ - height : this.chart.height, - width : this.chart.width - }); - this.scale.update(newScaleProps); - }, - draw : function(ease){ - var easingDecimal = ease || 1; - this.clear(); - - var ctx = this.chart.ctx; - - this.scale.draw(easingDecimal); - - //Draw all the bars for each dataset - helpers.each(this.datasets,function(dataset,datasetIndex){ - helpers.each(dataset.bars,function(bar,index){ - if (bar.hasValue()){ - bar.base = this.scale.endPoint; - //Transition then draw - bar.transition({ - x : this.scale.calculateBarX(this.datasets.length, datasetIndex, index), - y : this.scale.calculateY(bar.value), - width : this.scale.calculateBarWidth(this.datasets.length) - }, easingDecimal).draw(); - } - },this); + // Before init plugin notification + plugins.notify(me, 'beforeInit'); - },this); - } - }); + helpers.retinaScale(me, me.options.devicePixelRatio); + me.bindEvents(); -}).call(this); + if (me.options.responsive) { + // Initial resize before chart draws (must be silent to preserve initial animations). + me.resize(true); + } -(function(){ - "use strict"; + // Make sure scales have IDs and are built before we build any controllers. + me.ensureScalesHaveIDs(); + me.buildScales(); + me.initToolTip(); - var root = this, - Chart = root.Chart, - //Cache a local reference to Chart.helpers - helpers = Chart.helpers; + // After init plugin notification + plugins.notify(me, 'afterInit'); - var defaultConfig = { - //Boolean - Whether we should show a stroke on each segment - segmentShowStroke : true, + return me; + }, - //String - The colour of each segment stroke - segmentStrokeColor : "#fff", + clear: function() { + helpers.canvas.clear(this); + return this; + }, - //Number - The width of each segment stroke - segmentStrokeWidth : 2, + stop: function() { + // Stops any current animation loop occurring + Chart.animationService.cancelAnimation(this); + return this; + }, - //The percentage of the chart that we cut out of the middle. - percentageInnerCutout : 50, + resize: function(silent) { + var me = this; + var options = me.options; + var canvas = me.canvas; + var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null; - //Number - Amount of animation steps - animationSteps : 100, + // the canvas render width and height will be casted to integers so make sure that + // the canvas display style uses the same integer values to avoid blurring effect. - //String - Animation easing effect - animationEasing : "easeOutBounce", + // Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collased + var newWidth = Math.max(0, Math.floor(helpers.getMaximumWidth(canvas))); + var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas))); - //Boolean - Whether we animate the rotation of the Doughnut - animateRotate : true, + if (me.width === newWidth && me.height === newHeight) { + return; + } - //Boolean - Whether we animate scaling the Doughnut from the centre - animateScale : false, + canvas.width = me.width = newWidth; + canvas.height = me.height = newHeight; + canvas.style.width = newWidth + 'px'; + canvas.style.height = newHeight + 'px'; - //String - A legend template - legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
" + helpers.retinaScale(me, options.devicePixelRatio); - }; + if (!silent) { + // Notify any plugins about the resize + var newSize = {width: newWidth, height: newHeight}; + plugins.notify(me, 'resize', [newSize]); + // Notify of resize + if (me.options.onResize) { + me.options.onResize(me, newSize); + } - Chart.Type.extend({ - //Passing in a name registers this chart in the Chart namespace - name: "Doughnut", - //Providing a defaults will also register the deafults in the chart namespace - defaults : defaultConfig, - //Initialize is fired when the chart is initialized - Data is passed in as a parameter - //Config is automatically merged by the core of Chart.js, and is available at this.options - initialize: function(data){ + me.stop(); + me.update(me.options.responsiveAnimationDuration); + } + }, - //Declare segments as a static property to prevent inheriting across the Chart type prototype - this.segments = []; - this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2; + ensureScalesHaveIDs: function() { + var options = this.options; + var scalesOptions = options.scales || {}; + var scaleOptions = options.scale; - this.SegmentArc = Chart.Arc.extend({ - ctx : this.chart.ctx, - x : this.chart.width/2, - y : this.chart.height/2 + helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) { + xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); }); - //Set up tooltip events on the chart - if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : []; - - helpers.each(this.segments,function(segment){ - segment.restore(["fillColor"]); - }); - helpers.each(activeSegments,function(activeSegment){ - activeSegment.fillColor = activeSegment.highlightColor; - }); - this.showTooltip(activeSegments); - }); - } - this.calculateTotal(data); - - helpers.each(data,function(datapoint, index){ - this.addData(datapoint, index, true); - },this); - - this.render(); - }, - getSegmentsAtEvent : function(e){ - var segmentsArray = []; - - var location = helpers.getRelativePosition(e); - - helpers.each(this.segments,function(segment){ - if (segment.inRange(location.x,location.y)) segmentsArray.push(segment); - },this); - return segmentsArray; - }, - addData : function(segment, atIndex, silent){ - var index = atIndex || this.segments.length; - this.segments.splice(index, 0, new this.SegmentArc({ - value : segment.value, - outerRadius : (this.options.animateScale) ? 0 : this.outerRadius, - innerRadius : (this.options.animateScale) ? 0 : (this.outerRadius/100) * this.options.percentageInnerCutout, - fillColor : segment.color, - highlightColor : segment.highlight || segment.color, - showStroke : this.options.segmentShowStroke, - strokeWidth : this.options.segmentStrokeWidth, - strokeColor : this.options.segmentStrokeColor, - startAngle : Math.PI * 1.5, - circumference : (this.options.animateRotate) ? 0 : this.calculateCircumference(segment.value), - label : segment.label - })); - if (!silent){ - this.reflow(); - this.update(); - } - }, - calculateCircumference : function(value){ - return (Math.PI*2)*(Math.abs(value) / this.total); - }, - calculateTotal : function(data){ - this.total = 0; - helpers.each(data,function(segment){ - this.total += Math.abs(segment.value); - },this); - }, - update : function(){ - this.calculateTotal(this.segments); - - // Reset any highlight colours before updating. - helpers.each(this.activeElements, function(activeElement){ - activeElement.restore(['fillColor']); + helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) { + yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); }); - helpers.each(this.segments,function(segment){ - segment.save(); - }); - this.render(); + if (scaleOptions) { + scaleOptions.id = scaleOptions.id || 'scale'; + } }, - removeData: function(atIndex){ - var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1; - this.segments.splice(indexToDelete, 1); - this.reflow(); - this.update(); - }, + /** + * Builds a map of scale ID to scale object for future lookup. + */ + buildScales: function() { + var me = this; + var options = me.options; + var scales = me.scales = {}; + var items = []; + + if (options.scales) { + items = items.concat( + (options.scales.xAxes || []).map(function(xAxisOptions) { + return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'}; + }), + (options.scales.yAxes || []).map(function(yAxisOptions) { + return {options: yAxisOptions, dtype: 'linear', dposition: 'left'}; + }) + ); + } - reflow : function(){ - helpers.extend(this.SegmentArc.prototype,{ - x : this.chart.width/2, - y : this.chart.height/2 - }); - this.outerRadius = (helpers.min([this.chart.width,this.chart.height]) - this.options.segmentStrokeWidth/2)/2; - helpers.each(this.segments, function(segment){ - segment.update({ - outerRadius : this.outerRadius, - innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout + if (options.scale) { + items.push({ + options: options.scale, + dtype: 'radialLinear', + isDefault: true, + dposition: 'chartArea' }); - }, this); - }, - draw : function(easeDecimal){ - var animDecimal = (easeDecimal) ? easeDecimal : 1; - this.clear(); - helpers.each(this.segments,function(segment,index){ - segment.transition({ - circumference : this.calculateCircumference(segment.value), - outerRadius : this.outerRadius, - innerRadius : (this.outerRadius/100) * this.options.percentageInnerCutout - },animDecimal); - - segment.endAngle = segment.startAngle + segment.circumference; + } - segment.draw(); - if (index === 0){ - segment.startAngle = Math.PI * 1.5; + helpers.each(items, function(item) { + var scaleOptions = item.options; + var scaleType = helpers.valueOrDefault(scaleOptions.type, item.dtype); + var scaleClass = Chart.scaleService.getScaleConstructor(scaleType); + if (!scaleClass) { + return; } - //Check to see if it's the last segment, if not get the next and update the start angle - if (index < this.segments.length-1){ - this.segments[index+1].startAngle = segment.endAngle; - } - },this); - } - }); + if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) { + scaleOptions.position = item.dposition; + } - Chart.types.Doughnut.extend({ - name : "Pie", - defaults : helpers.merge(defaultConfig,{percentageInnerCutout : 0}) - }); + var scale = new scaleClass({ + id: scaleOptions.id, + options: scaleOptions, + ctx: me.ctx, + chart: me + }); -}).call(this); -(function(){ - "use strict"; + scales[scale.id] = scale; + scale.mergeTicksOptions(); - var root = this, - Chart = root.Chart, - helpers = Chart.helpers; + // TODO(SB): I think we should be able to remove this custom case (options.scale) + // and consider it as a regular scale part of the "scales"" map only! This would + // make the logic easier and remove some useless? custom code. + if (item.isDefault) { + me.scale = scale; + } + }); - var defaultConfig = { + Chart.scaleService.addScalesToLayout(this); + }, - ///Boolean - Whether grid lines are shown across the chart - scaleShowGridLines : true, + buildOrUpdateControllers: function() { + var me = this; + var types = []; + var newControllers = []; - //String - Colour of the grid lines - scaleGridLineColor : "rgba(0,0,0,.05)", + helpers.each(me.data.datasets, function(dataset, datasetIndex) { + var meta = me.getDatasetMeta(datasetIndex); + var type = dataset.type || me.config.type; - //Number - Width of the grid lines - scaleGridLineWidth : 1, + if (meta.type && meta.type !== type) { + me.destroyDatasetMeta(datasetIndex); + meta = me.getDatasetMeta(datasetIndex); + } + meta.type = type; - //Boolean - Whether to show horizontal lines (except X axis) - scaleShowHorizontalLines: true, + types.push(meta.type); - //Boolean - Whether to show vertical lines (except Y axis) - scaleShowVerticalLines: true, + if (meta.controller) { + meta.controller.updateIndex(datasetIndex); + } else { + var ControllerClass = Chart.controllers[meta.type]; + if (ControllerClass === undefined) { + throw new Error('"' + meta.type + '" is not a chart type.'); + } - //Boolean - Whether the line is curved between points - bezierCurve : true, + meta.controller = new ControllerClass(me, datasetIndex); + newControllers.push(meta.controller); + } + }, me); - //Number - Tension of the bezier curve between points - bezierCurveTension : 0.4, + return newControllers; + }, - //Boolean - Whether to show a dot for each point - pointDot : true, + /** + * Reset the elements of all datasets + * @private + */ + resetElements: function() { + var me = this; + helpers.each(me.data.datasets, function(dataset, datasetIndex) { + me.getDatasetMeta(datasetIndex).controller.reset(); + }, me); + }, - //Number - Radius of each point dot in pixels - pointDotRadius : 4, + /** + * Resets the chart back to it's state before the initial animation + */ + reset: function() { + this.resetElements(); + this.tooltip.initialize(); + }, - //Number - Pixel width of point dot stroke - pointDotStrokeWidth : 1, + update: function(config) { + var me = this; - //Number - amount extra to add to the radius to cater for hit detection outside the drawn point - pointHitDetectionRadius : 20, + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } - //Boolean - Whether to show a stroke for datasets - datasetStroke : true, + updateConfig(me); - //Number - Pixel width of dataset stroke - datasetStrokeWidth : 2, + if (plugins.notify(me, 'beforeUpdate') === false) { + return; + } - //Boolean - Whether to fill the dataset with a colour - datasetFill : true, + // In case the entire data object changed + me.tooltip._data = me.data; - //String - A legend template - legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + // Make sure dataset controllers are updated and new controllers are reset + var newControllers = me.buildOrUpdateControllers(); - }; + // Make sure all dataset controllers have correct meta data counts + helpers.each(me.data.datasets, function(dataset, datasetIndex) { + me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); + }, me); + me.updateLayout(); - Chart.Type.extend({ - name: "Line", - defaults : defaultConfig, - initialize: function(data){ - //Declare the extension of the default point, to cater for the options passed in to the constructor - this.PointClass = Chart.Point.extend({ - strokeWidth : this.options.pointDotStrokeWidth, - radius : this.options.pointDotRadius, - display: this.options.pointDot, - hitDetectionRadius : this.options.pointHitDetectionRadius, - ctx : this.chart.ctx, - inRange : function(mouseX){ - return (Math.pow(mouseX-this.x, 2) < Math.pow(this.radius + this.hitDetectionRadius,2)); - } + // Can only reset the new controllers after the scales have been updated + helpers.each(newControllers, function(controller) { + controller.reset(); }); - this.datasets = []; - - //Set up tooltip events on the chart - if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activePoints = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : []; - this.eachPoints(function(point){ - point.restore(['fillColor', 'strokeColor']); - }); - helpers.each(activePoints, function(activePoint){ - activePoint.fillColor = activePoint.highlightFill; - activePoint.strokeColor = activePoint.highlightStroke; - }); - this.showTooltip(activePoints); - }); - } + me.updateDatasets(); - //Iterate through each of the datasets, and build this into a property of the chart - helpers.each(data.datasets,function(dataset){ + // Do this before render so that any plugins that need final scale updates can use it + plugins.notify(me, 'afterUpdate'); - var datasetObject = { - label : dataset.label || null, - fillColor : dataset.fillColor, - strokeColor : dataset.strokeColor, - pointColor : dataset.pointColor, - pointStrokeColor : dataset.pointStrokeColor, - points : [] + if (me._bufferedRender) { + me._bufferedRequest = { + duration: config.duration, + easing: config.easing, + lazy: config.lazy }; + } else { + me.render(config); + } + }, - this.datasets.push(datasetObject); - + /** + * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` + * hook, in which case, plugins will not be called on `afterLayout`. + * @private + */ + updateLayout: function() { + var me = this; - helpers.each(dataset.data,function(dataPoint,index){ - //Add a new point for each piece of data, passing any required data to draw. - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); - },this); + if (plugins.notify(me, 'beforeLayout') === false) { + return; + } - this.buildScale(data.labels); + Chart.layoutService.update(this, this.width, this.height); + /** + * Provided for backward compatibility, use `afterLayout` instead. + * @method IPlugin#afterScaleUpdate + * @deprecated since version 2.5.0 + * @todo remove at version 3 + * @private + */ + plugins.notify(me, 'afterScaleUpdate'); + plugins.notify(me, 'afterLayout'); + }, - this.eachPoints(function(point, index){ - helpers.extend(point, { - x: this.scale.calculateX(index), - y: this.scale.endPoint - }); - point.save(); - }, this); + /** + * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` + * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. + * @private + */ + updateDatasets: function() { + var me = this; - },this); + if (plugins.notify(me, 'beforeDatasetsUpdate') === false) { + return; + } + for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { + me.updateDataset(i); + } - this.render(); + plugins.notify(me, 'afterDatasetsUpdate'); }, - update : function(){ - this.scale.update(); - // Reset any highlight colours before updating. - helpers.each(this.activeElements, function(activeElement){ - activeElement.restore(['fillColor', 'strokeColor']); - }); - this.eachPoints(function(point){ - point.save(); - }); - this.render(); - }, - eachPoints : function(callback){ - helpers.each(this.datasets,function(dataset){ - helpers.each(dataset.points,callback,this); - },this); - }, - getPointsAtEvent : function(e){ - var pointsArray = [], - eventPosition = helpers.getRelativePosition(e); - helpers.each(this.datasets,function(dataset){ - helpers.each(dataset.points,function(point){ - if (point.inRange(eventPosition.x,eventPosition.y)) pointsArray.push(point); - }); - },this); - return pointsArray; - }, - buildScale : function(labels){ - var self = this; - - var dataTotal = function(){ - var values = []; - self.eachPoints(function(point){ - values.push(point.value); - }); - - return values; - }; - var scaleOptions = { - templateString : this.options.scaleLabel, - height : this.chart.height, - width : this.chart.width, - ctx : this.chart.ctx, - textColor : this.options.scaleFontColor, - fontSize : this.options.scaleFontSize, - fontStyle : this.options.scaleFontStyle, - fontFamily : this.options.scaleFontFamily, - valuesCount : labels.length, - beginAtZero : this.options.scaleBeginAtZero, - integersOnly : this.options.scaleIntegersOnly, - calculateYRange : function(currentHeight){ - var updatedRanges = helpers.calculateScaleRange( - dataTotal(), - currentHeight, - this.fontSize, - this.beginAtZero, - this.integersOnly - ); - helpers.extend(this, updatedRanges); - }, - xLabels : labels, - font : helpers.fontString(this.options.scaleFontSize, this.options.scaleFontStyle, this.options.scaleFontFamily), - lineWidth : this.options.scaleLineWidth, - lineColor : this.options.scaleLineColor, - showHorizontalLines : this.options.scaleShowHorizontalLines, - showVerticalLines : this.options.scaleShowVerticalLines, - gridLineWidth : (this.options.scaleShowGridLines) ? this.options.scaleGridLineWidth : 0, - gridLineColor : (this.options.scaleShowGridLines) ? this.options.scaleGridLineColor : "rgba(0,0,0,0)", - padding: (this.options.showScale) ? 0 : this.options.pointDotRadius + this.options.pointDotStrokeWidth, - showLabels : this.options.scaleShowLabels, - display : this.options.showScale + /** + * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate` + * hook, in which case, plugins will not be called on `afterDatasetUpdate`. + * @private + */ + updateDataset: function(index) { + var me = this; + var meta = me.getDatasetMeta(index); + var args = { + meta: meta, + index: index }; - if (this.options.scaleOverride){ - helpers.extend(scaleOptions, { - calculateYRange: helpers.noop, - steps: this.options.scaleSteps, - stepValue: this.options.scaleStepWidth, - min: this.options.scaleStartValue, - max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) - }); + if (plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) { + return; } + meta.controller.update(); - this.scale = new Chart.Scale(scaleOptions); - }, - addData : function(valuesArray,label){ - //Map the values array for each of the datasets - - helpers.each(valuesArray,function(value,datasetIndex){ - //Add a new point for each piece of data, passing any required data to draw. - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: this.scale.calculateX(this.scale.valuesCount+1), - y: this.scale.endPoint, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - },this); - - this.scale.addXLabel(label); - //Then re-render the chart. - this.update(); - }, - removeData : function(){ - this.scale.removeXLabel(); - //Then re-render the chart. - helpers.each(this.datasets,function(dataset){ - dataset.points.shift(); - },this); - this.update(); - }, - reflow : function(){ - var newScaleProps = helpers.extend({ - height : this.chart.height, - width : this.chart.width - }); - this.scale.update(newScaleProps); + plugins.notify(me, 'afterDatasetUpdate', [args]); }, - draw : function(ease){ - var easingDecimal = ease || 1; - this.clear(); - var ctx = this.chart.ctx; + render: function(config) { + var me = this; - // Some helper methods for getting the next/prev points - var hasValue = function(item){ - return item.value !== null; - }, - nextPoint = function(point, collection, index){ - return helpers.findNextWhere(collection, hasValue, index) || point; - }, - previousPoint = function(point, collection, index){ - return helpers.findPreviousWhere(collection, hasValue, index) || point; - }; + if (!config || typeof config !== 'object') { + // backwards compatibility + config = { + duration: config, + lazy: arguments[1] + }; + } - this.scale.draw(easingDecimal); + var duration = config.duration; + var lazy = config.lazy; + if (plugins.notify(me, 'beforeRender') === false) { + return; + } - helpers.each(this.datasets,function(dataset){ - var pointsWithValues = helpers.where(dataset.points, hasValue); + var animationOptions = me.options.animation; + var onComplete = function(animation) { + plugins.notify(me, 'afterRender'); + helpers.callback(animationOptions && animationOptions.onComplete, [animation], me); + }; - //Transition each point first so that the line and point drawing isn't out of sync - //We can use this extra loop to calculate the control points of this dataset also in this loop + if (animationOptions && ((typeof duration !== 'undefined' && duration !== 0) || (typeof duration === 'undefined' && animationOptions.duration !== 0))) { + var animation = new Chart.Animation({ + numSteps: (duration || animationOptions.duration) / 16.66, // 60 fps + easing: config.easing || animationOptions.easing, - helpers.each(dataset.points, function(point, index){ - if (point.hasValue()){ - point.transition({ - y : this.scale.calculateY(point.value), - x : this.scale.calculateX(index) - }, easingDecimal); - } - },this); - - - // Control points need to be calculated in a seperate loop, because we need to know the current x/y of the point - // This would cause issues when there is no animation, because the y of the next point would be 0, so beziers would be skewed - if (this.options.bezierCurve){ - helpers.each(pointsWithValues, function(point, index){ - var tension = (index > 0 && index < pointsWithValues.length - 1) ? this.options.bezierCurveTension : 0; - point.controlPoints = helpers.splineCurve( - previousPoint(point, pointsWithValues, index), - point, - nextPoint(point, pointsWithValues, index), - tension - ); + render: function(chart, animationObject) { + var easingFunction = helpers.easing.effects[animationObject.easing]; + var currentStep = animationObject.currentStep; + var stepDecimal = currentStep / animationObject.numSteps; - // Prevent the bezier going outside of the bounds of the graph + chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep); + }, - // Cap puter bezier handles to the upper/lower scale bounds - if (point.controlPoints.outer.y > this.scale.endPoint){ - point.controlPoints.outer.y = this.scale.endPoint; - } - else if (point.controlPoints.outer.y < this.scale.startPoint){ - point.controlPoints.outer.y = this.scale.startPoint; - } + onAnimationProgress: animationOptions.onProgress, + onAnimationComplete: onComplete + }); - // Cap inner bezier handles to the upper/lower scale bounds - if (point.controlPoints.inner.y > this.scale.endPoint){ - point.controlPoints.inner.y = this.scale.endPoint; - } - else if (point.controlPoints.inner.y < this.scale.startPoint){ - point.controlPoints.inner.y = this.scale.startPoint; - } - },this); - } + Chart.animationService.addAnimation(me, animation, duration, lazy); + } else { + me.draw(); + // See https://github.com/chartjs/Chart.js/issues/3781 + onComplete(new Chart.Animation({numSteps: 0, chart: me})); + } - //Draw the line between all the points - ctx.lineWidth = this.options.datasetStrokeWidth; - ctx.strokeStyle = dataset.strokeColor; - ctx.beginPath(); + return me; + }, - helpers.each(pointsWithValues, function(point, index){ - if (index === 0){ - ctx.moveTo(point.x, point.y); - } - else{ - if(this.options.bezierCurve){ - var previous = previousPoint(point, pointsWithValues, index); - - ctx.bezierCurveTo( - previous.controlPoints.outer.x, - previous.controlPoints.outer.y, - point.controlPoints.inner.x, - point.controlPoints.inner.y, - point.x, - point.y - ); - } - else{ - ctx.lineTo(point.x,point.y); - } - } - }, this); + draw: function(easingValue) { + var me = this; - ctx.stroke(); + me.clear(); - if (this.options.datasetFill && pointsWithValues.length > 0){ - //Round off the line by going to the base of the chart, back to the start, then fill. - ctx.lineTo(pointsWithValues[pointsWithValues.length - 1].x, this.scale.endPoint); - ctx.lineTo(pointsWithValues[0].x, this.scale.endPoint); - ctx.fillStyle = dataset.fillColor; - ctx.closePath(); - ctx.fill(); - } + if (helpers.isNullOrUndef(easingValue)) { + easingValue = 1; + } - //Now draw the points over the line - //A little inefficient double looping, but better than the line - //lagging behind the point positions - helpers.each(pointsWithValues,function(point){ - point.draw(); - }); - },this); - } - }); + me.transition(easingValue); + if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) { + return; + } -}).call(this); + // Draw all the scales + helpers.each(me.boxes, function(box) { + box.draw(me.chartArea); + }, me); -(function(){ - "use strict"; + if (me.scale) { + me.scale.draw(); + } - var root = this, - Chart = root.Chart, - //Cache a local reference to Chart.helpers - helpers = Chart.helpers; + me.drawDatasets(easingValue); - var defaultConfig = { - //Boolean - Show a backdrop to the scale label - scaleShowLabelBackdrop : true, + // Finally draw the tooltip + me.tooltip.draw(); - //String - The colour of the label backdrop - scaleBackdropColor : "rgba(255,255,255,0.75)", + plugins.notify(me, 'afterDraw', [easingValue]); + }, - // Boolean - Whether the scale should begin at zero - scaleBeginAtZero : true, + /** + * @private + */ + transition: function(easingValue) { + var me = this; - //Number - The backdrop padding above & below the label in pixels - scaleBackdropPaddingY : 2, + for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) { + if (me.isDatasetVisible(i)) { + me.getDatasetMeta(i).controller.transition(easingValue); + } + } - //Number - The backdrop padding to the side of the label in pixels - scaleBackdropPaddingX : 2, + me.tooltip.transition(easingValue); + }, - //Boolean - Show line for each value in the scale - scaleShowLine : true, + /** + * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` + * hook, in which case, plugins will not be called on `afterDatasetsDraw`. + * @private + */ + drawDatasets: function(easingValue) { + var me = this; - //Boolean - Stroke a line around each segment in the chart - segmentShowStroke : true, + if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { + return; + } - //String - The colour of the stroke on each segement. - segmentStrokeColor : "#fff", + // Draw datasets reversed to support proper line stacking + for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) { + if (me.isDatasetVisible(i)) { + me.drawDataset(i, easingValue); + } + } - //Number - The width of the stroke value in pixels - segmentStrokeWidth : 2, + plugins.notify(me, 'afterDatasetsDraw', [easingValue]); + }, - //Number - Amount of animation steps - animationSteps : 100, + /** + * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw` + * hook, in which case, plugins will not be called on `afterDatasetDraw`. + * @private + */ + drawDataset: function(index, easingValue) { + var me = this; + var meta = me.getDatasetMeta(index); + var args = { + meta: meta, + index: index, + easingValue: easingValue + }; - //String - Animation easing effect. - animationEasing : "easeOutBounce", + if (plugins.notify(me, 'beforeDatasetDraw', [args]) === false) { + return; + } - //Boolean - Whether to animate the rotation of the chart - animateRotate : true, + meta.controller.draw(easingValue); - //Boolean - Whether to animate scaling the chart from the centre - animateScale : false, + plugins.notify(me, 'afterDatasetDraw', [args]); + }, - //String - A legend template - legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(segments[i].label){%><%=segments[i].label%><%}%>
  • <%}%>
" - }; + // Get the single element that was clicked on + // @return : An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw + getElementAtEvent: function(e) { + return Interaction.modes.single(this, e); + }, + getElementsAtEvent: function(e) { + return Interaction.modes.label(this, e, {intersect: true}); + }, - Chart.Type.extend({ - //Passing in a name registers this chart in the Chart namespace - name: "PolarArea", - //Providing a defaults will also register the deafults in the chart namespace - defaults : defaultConfig, - //Initialize is fired when the chart is initialized - Data is passed in as a parameter - //Config is automatically merged by the core of Chart.js, and is available at this.options - initialize: function(data){ - this.segments = []; - //Declare segment class as a chart instance specific class, so it can share props for this instance - this.SegmentArc = Chart.Arc.extend({ - showStroke : this.options.segmentShowStroke, - strokeWidth : this.options.segmentStrokeWidth, - strokeColor : this.options.segmentStrokeColor, - ctx : this.chart.ctx, - innerRadius : 0, - x : this.chart.width/2, - y : this.chart.height/2 - }); - this.scale = new Chart.RadialScale({ - display: this.options.showScale, - fontStyle: this.options.scaleFontStyle, - fontSize: this.options.scaleFontSize, - fontFamily: this.options.scaleFontFamily, - fontColor: this.options.scaleFontColor, - showLabels: this.options.scaleShowLabels, - showLabelBackdrop: this.options.scaleShowLabelBackdrop, - backdropColor: this.options.scaleBackdropColor, - backdropPaddingY : this.options.scaleBackdropPaddingY, - backdropPaddingX: this.options.scaleBackdropPaddingX, - lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0, - lineColor: this.options.scaleLineColor, - lineArc: true, - width: this.chart.width, - height: this.chart.height, - xCenter: this.chart.width/2, - yCenter: this.chart.height/2, - ctx : this.chart.ctx, - templateString: this.options.scaleLabel, - valuesCount: data.length - }); + getElementsAtXAxis: function(e) { + return Interaction.modes['x-axis'](this, e, {intersect: true}); + }, - this.updateScaleRange(data); + getElementsAtEventForMode: function(e, mode, options) { + var method = Interaction.modes[mode]; + if (typeof method === 'function') { + return method(this, e, options); + } - this.scale.update(); + return []; + }, - helpers.each(data,function(segment,index){ - this.addData(segment,index,true); - },this); + getDatasetAtEvent: function(e) { + return Interaction.modes.dataset(this, e, {intersect: true}); + }, - //Set up tooltip events on the chart - if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : []; - helpers.each(this.segments,function(segment){ - segment.restore(["fillColor"]); - }); - helpers.each(activeSegments,function(activeSegment){ - activeSegment.fillColor = activeSegment.highlightColor; - }); - this.showTooltip(activeSegments); - }); + getDatasetMeta: function(datasetIndex) { + var me = this; + var dataset = me.data.datasets[datasetIndex]; + if (!dataset._meta) { + dataset._meta = {}; + } + + var meta = dataset._meta[me.id]; + if (!meta) { + meta = dataset._meta[me.id] = { + type: null, + data: [], + dataset: null, + controller: null, + hidden: null, // See isDatasetVisible() comment + xAxisID: null, + yAxisID: null + }; } - this.render(); - }, - getSegmentsAtEvent : function(e){ - var segmentsArray = []; - - var location = helpers.getRelativePosition(e); - - helpers.each(this.segments,function(segment){ - if (segment.inRange(location.x,location.y)) segmentsArray.push(segment); - },this); - return segmentsArray; - }, - addData : function(segment, atIndex, silent){ - var index = atIndex || this.segments.length; - - this.segments.splice(index, 0, new this.SegmentArc({ - fillColor: segment.color, - highlightColor: segment.highlight || segment.color, - label: segment.label, - value: segment.value, - outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value), - circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(), - startAngle: Math.PI * 1.5 - })); - if (!silent){ - this.reflow(); - this.update(); - } - }, - removeData: function(atIndex){ - var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1; - this.segments.splice(indexToDelete, 1); - this.reflow(); - this.update(); - }, - calculateTotal: function(data){ - this.total = 0; - helpers.each(data,function(segment){ - this.total += segment.value; - },this); - this.scale.valuesCount = this.segments.length; - }, - updateScaleRange: function(datapoints){ - var valuesArray = []; - helpers.each(datapoints,function(segment){ - valuesArray.push(segment.value); - }); - - var scaleSizes = (this.options.scaleOverride) ? - { - steps: this.options.scaleSteps, - stepValue: this.options.scaleStepWidth, - min: this.options.scaleStartValue, - max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) - } : - helpers.calculateScaleRange( - valuesArray, - helpers.min([this.chart.width, this.chart.height])/2, - this.options.scaleFontSize, - this.options.scaleBeginAtZero, - this.options.scaleIntegersOnly - ); + return meta; + }, - helpers.extend( - this.scale, - scaleSizes, - { - size: helpers.min([this.chart.width, this.chart.height]), - xCenter: this.chart.width/2, - yCenter: this.chart.height/2 + getVisibleDatasetCount: function() { + var count = 0; + for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) { + if (this.isDatasetVisible(i)) { + count++; } - ); - + } + return count; }, - update : function(){ - this.calculateTotal(this.segments); - helpers.each(this.segments,function(segment){ - segment.save(); - }); - - this.reflow(); - this.render(); - }, - reflow : function(){ - helpers.extend(this.SegmentArc.prototype,{ - x : this.chart.width/2, - y : this.chart.height/2 - }); - this.updateScaleRange(this.segments); - this.scale.update(); - - helpers.extend(this.scale,{ - xCenter: this.chart.width/2, - yCenter: this.chart.height/2 - }); + isDatasetVisible: function(datasetIndex) { + var meta = this.getDatasetMeta(datasetIndex); - helpers.each(this.segments, function(segment){ - segment.update({ - outerRadius : this.scale.calculateCenterOffset(segment.value) - }); - }, this); + // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, + // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. + return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden; + }, + generateLegend: function() { + return this.options.legendCallback(this); }, - draw : function(ease){ - var easingDecimal = ease || 1; - //Clear & draw the canvas - this.clear(); - helpers.each(this.segments,function(segment, index){ - segment.transition({ - circumference : this.scale.getCircumference(), - outerRadius : this.scale.calculateCenterOffset(segment.value) - },easingDecimal); - segment.endAngle = segment.startAngle + segment.circumference; + /** + * @private + */ + destroyDatasetMeta: function(datasetIndex) { + var id = this.id; + var dataset = this.data.datasets[datasetIndex]; + var meta = dataset._meta && dataset._meta[id]; - // If we've removed the first segment we need to set the first one to - // start at the top. - if (index === 0){ - segment.startAngle = Math.PI * 1.5; - } + if (meta) { + meta.controller.destroy(); + delete dataset._meta[id]; + } + }, - //Check to see if it's the last segment, if not get the next and update the start angle - if (index < this.segments.length - 1){ - this.segments[index+1].startAngle = segment.endAngle; - } - segment.draw(); - }, this); - this.scale.draw(); - } - }); + destroy: function() { + var me = this; + var canvas = me.canvas; + var i, ilen; -}).call(this); -(function(){ - "use strict"; + me.stop(); + + // dataset controllers need to cleanup associated data + for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { + me.destroyDatasetMeta(i); + } - var root = this, - Chart = root.Chart, - helpers = Chart.helpers; + if (canvas) { + me.unbindEvents(); + helpers.canvas.clear(me); + platform.releaseContext(me.ctx); + me.canvas = null; + me.ctx = null; + } + plugins.notify(me, 'destroy'); + delete Chart.instances[me.id]; + }, - Chart.Type.extend({ - name: "Radar", - defaults:{ - //Boolean - Whether to show lines for each scale point - scaleShowLine : true, + toBase64Image: function() { + return this.canvas.toDataURL.apply(this.canvas, arguments); + }, - //Boolean - Whether we show the angle lines out of the radar - angleShowLineOut : true, + initToolTip: function() { + var me = this; + me.tooltip = new Chart.Tooltip({ + _chart: me, + _chartInstance: me, // deprecated, backward compatibility + _data: me.data, + _options: me.options.tooltips + }, me); + }, - //Boolean - Whether to show labels on the scale - scaleShowLabels : false, + /** + * @private + */ + bindEvents: function() { + var me = this; + var listeners = me._listeners = {}; + var listener = function() { + me.eventHandler.apply(me, arguments); + }; - // Boolean - Whether the scale should begin at zero - scaleBeginAtZero : true, + helpers.each(me.options.events, function(type) { + platform.addEventListener(me, type, listener); + listeners[type] = listener; + }); - //String - Colour of the angle line - angleLineColor : "rgba(0,0,0,.1)", + // Elements used to detect size change should not be injected for non responsive charts. + // See https://github.com/chartjs/Chart.js/issues/2210 + if (me.options.responsive) { + listener = function() { + me.resize(); + }; - //Number - Pixel width of the angle line - angleLineWidth : 1, + platform.addEventListener(me, 'resize', listener); + listeners.resize = listener; + } + }, - //String - Point label font declaration - pointLabelFontFamily : "'Arial'", + /** + * @private + */ + unbindEvents: function() { + var me = this; + var listeners = me._listeners; + if (!listeners) { + return; + } - //String - Point label font weight - pointLabelFontStyle : "normal", + delete me._listeners; + helpers.each(listeners, function(listener, type) { + platform.removeEventListener(me, type, listener); + }); + }, - //Number - Point label font size in pixels - pointLabelFontSize : 10, + updateHoverStyle: function(elements, mode, enabled) { + var method = enabled ? 'setHoverStyle' : 'removeHoverStyle'; + var element, i, ilen; - //String - Point label font colour - pointLabelFontColor : "#666", + for (i = 0, ilen = elements.length; i < ilen; ++i) { + element = elements[i]; + if (element) { + this.getDatasetMeta(element._datasetIndex).controller[method](element); + } + } + }, - //Boolean - Whether to show a dot for each point - pointDot : true, + /** + * @private + */ + eventHandler: function(e) { + var me = this; + var tooltip = me.tooltip; - //Number - Radius of each point dot in pixels - pointDotRadius : 3, + if (plugins.notify(me, 'beforeEvent', [e]) === false) { + return; + } - //Number - Pixel width of point dot stroke - pointDotStrokeWidth : 1, + // Buffer any update calls so that renders do not occur + me._bufferedRender = true; + me._bufferedRequest = null; - //Number - amount extra to add to the radius to cater for hit detection outside the drawn point - pointHitDetectionRadius : 20, + var changed = me.handleEvent(e); + changed |= tooltip && tooltip.handleEvent(e); - //Boolean - Whether to show a stroke for datasets - datasetStroke : true, + plugins.notify(me, 'afterEvent', [e]); - //Number - Pixel width of dataset stroke - datasetStrokeWidth : 2, + var bufferedRequest = me._bufferedRequest; + if (bufferedRequest) { + // If we have an update that was triggered, we need to do a normal render + me.render(bufferedRequest); + } else if (changed && !me.animating) { + // If entering, leaving, or changing elements, animate the change via pivot + me.stop(); - //Boolean - Whether to fill the dataset with a colour - datasetFill : true, + // We only need to render at this point. Updating will cause scales to be + // recomputed generating flicker & using more memory than necessary. + me.render(me.options.hover.animationDuration, true); + } - //String - A legend template - legendTemplate : "
    -legend\"><% for (var i=0; i
  • \"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
  • <%}%>
" + me._bufferedRender = false; + me._bufferedRequest = null; + return me; }, - initialize: function(data){ - this.PointClass = Chart.Point.extend({ - strokeWidth : this.options.pointDotStrokeWidth, - radius : this.options.pointDotRadius, - display: this.options.pointDot, - hitDetectionRadius : this.options.pointHitDetectionRadius, - ctx : this.chart.ctx - }); - - this.datasets = []; + /** + * Handle an event + * @private + * @param {IEvent} event the event to handle + * @return {Boolean} true if the chart needs to re-render + */ + handleEvent: function(e) { + var me = this; + var options = me.options || {}; + var hoverOptions = options.hover; + var changed = false; + + me.lastActive = me.lastActive || []; + + // Find Active Elements for hover and tooltips + if (e.type === 'mouseout') { + me.active = []; + } else { + me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); + } - this.buildScale(data); + // Invoke onHover hook + // Need to call with native event here to not break backwards compatibility + helpers.callback(options.onHover || options.hover.onHover, [e.native, me.active], me); - //Set up tooltip events on the chart - if (this.options.showTooltips){ - helpers.bindEvents(this, this.options.tooltipEvents, function(evt){ - var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : []; + if (e.type === 'mouseup' || e.type === 'click') { + if (options.onClick) { + // Use e.native here for backwards compatibility + options.onClick.call(me, e.native, me.active); + } + } - this.eachPoints(function(point){ - point.restore(['fillColor', 'strokeColor']); - }); - helpers.each(activePointsCollection, function(activePoint){ - activePoint.fillColor = activePoint.highlightFill; - activePoint.strokeColor = activePoint.highlightStroke; - }); + // Remove styling for last active (even if it may still be active) + if (me.lastActive.length) { + me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); + } - this.showTooltip(activePointsCollection); - }); + // Built in hover styling + if (me.active.length && hoverOptions.mode) { + me.updateHoverStyle(me.active, hoverOptions.mode, true); } - //Iterate through each of the datasets, and build this into a property of the chart - helpers.each(data.datasets,function(dataset){ + changed = !helpers.arrayEquals(me.active, me.lastActive); - var datasetObject = { - label: dataset.label || null, - fillColor : dataset.fillColor, - strokeColor : dataset.strokeColor, - pointColor : dataset.pointColor, - pointStrokeColor : dataset.pointStrokeColor, - points : [] - }; + // Remember Last Actives + me.lastActive = me.active; - this.datasets.push(datasetObject); + return changed; + } + }); - helpers.each(dataset.data,function(dataPoint,index){ - //Add a new point for each piece of data, passing any required data to draw. - var pointPosition; - if (!this.scale.animation){ - pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint)); - } - datasetObject.points.push(new this.PointClass({ - value : dataPoint, - label : data.labels[index], - datasetLabel: dataset.label, - x: (this.options.animation) ? this.scale.xCenter : pointPosition.x, - y: (this.options.animation) ? this.scale.yCenter : pointPosition.y, - strokeColor : dataset.pointStrokeColor, - fillColor : dataset.pointColor, - highlightFill : dataset.pointHighlightFill || dataset.pointColor, - highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor - })); - },this); - - },this); - - this.render(); - }, - eachPoints : function(callback){ - helpers.each(this.datasets,function(dataset){ - helpers.each(dataset.points,callback,this); - },this); - }, - - getPointsAtEvent : function(evt){ - var mousePosition = helpers.getRelativePosition(evt), - fromCenter = helpers.getAngleFromPoint({ - x: this.scale.xCenter, - y: this.scale.yCenter - }, mousePosition); - - var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount, - pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex), - activePointsCollection = []; - - // If we're at the top, make the pointIndex 0 to get the first of the array. - if (pointIndex >= this.scale.valuesCount || pointIndex < 0){ - pointIndex = 0; - } - - if (fromCenter.distance <= this.scale.drawingArea){ - helpers.each(this.datasets, function(dataset){ - activePointsCollection.push(dataset.points[pointIndex]); - }); - } + /** + * Provided for backward compatibility, use Chart instead. + * @class Chart.Controller + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ + Chart.Controller = Chart; +}; + })(); +}); - return activePointsCollection; - }, - - buildScale : function(data){ - this.scale = new Chart.RadialScale({ - display: this.options.showScale, - fontStyle: this.options.scaleFontStyle, - fontSize: this.options.scaleFontSize, - fontFamily: this.options.scaleFontFamily, - fontColor: this.options.scaleFontColor, - showLabels: this.options.scaleShowLabels, - showLabelBackdrop: this.options.scaleShowLabelBackdrop, - backdropColor: this.options.scaleBackdropColor, - backdropPaddingY : this.options.scaleBackdropPaddingY, - backdropPaddingX: this.options.scaleBackdropPaddingX, - lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0, - lineColor: this.options.scaleLineColor, - angleLineColor : this.options.angleLineColor, - angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0, - // Point labels at the edge of each line - pointLabelFontColor : this.options.pointLabelFontColor, - pointLabelFontSize : this.options.pointLabelFontSize, - pointLabelFontFamily : this.options.pointLabelFontFamily, - pointLabelFontStyle : this.options.pointLabelFontStyle, - height : this.chart.height, - width: this.chart.width, - xCenter: this.chart.width/2, - yCenter: this.chart.height/2, - ctx : this.chart.ctx, - templateString: this.options.scaleLabel, - labels: data.labels, - valuesCount: data.datasets[0].data.length - }); +require.register("chart.js/src/core/core.datasetController.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - this.scale.setScaleSize(); - this.updateScaleRange(data.datasets); - this.scale.buildYLabels(); - }, - updateScaleRange: function(datasets){ - var valuesArray = (function(){ - var totalDataArray = []; - helpers.each(datasets,function(dataset){ - if (dataset.data){ - totalDataArray = totalDataArray.concat(dataset.data); - } - else { - helpers.each(dataset.points, function(point){ - totalDataArray.push(point.value); - }); - } - }); - return totalDataArray; - })(); +var helpers = require('../helpers/index'); +module.exports = function(Chart) { - var scaleSizes = (this.options.scaleOverride) ? - { - steps: this.options.scaleSteps, - stepValue: this.options.scaleStepWidth, - min: this.options.scaleStartValue, - max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth) - } : - helpers.calculateScaleRange( - valuesArray, - helpers.min([this.chart.width, this.chart.height])/2, - this.options.scaleFontSize, - this.options.scaleBeginAtZero, - this.options.scaleIntegersOnly - ); + var arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift']; - helpers.extend( - this.scale, - scaleSizes - ); + /** + * Hooks the array methods that add or remove values ('push', pop', 'shift', 'splice', + * 'unshift') and notify the listener AFTER the array has been altered. Listeners are + * called on the 'onData*' callbacks (e.g. onDataPush, etc.) with same arguments. + */ + function listenArrayEvents(array, listener) { + if (array._chartjs) { + array._chartjs.listeners.push(listener); + return; + } - }, - addData : function(valuesArray,label){ - //Map the values array for each of the datasets - this.scale.valuesCount++; - helpers.each(valuesArray,function(value,datasetIndex){ - var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value)); - this.datasets[datasetIndex].points.push(new this.PointClass({ - value : value, - label : label, - x: pointPosition.x, - y: pointPosition.y, - strokeColor : this.datasets[datasetIndex].pointStrokeColor, - fillColor : this.datasets[datasetIndex].pointColor - })); - },this); - - this.scale.labels.push(label); - - this.reflow(); - - this.update(); - }, - removeData : function(){ - this.scale.valuesCount--; - this.scale.labels.shift(); - helpers.each(this.datasets,function(dataset){ - dataset.points.shift(); - },this); - this.reflow(); - this.update(); - }, - update : function(){ - this.eachPoints(function(point){ - point.save(); - }); - this.reflow(); - this.render(); - }, - reflow: function(){ - helpers.extend(this.scale, { - width : this.chart.width, - height: this.chart.height, - size : helpers.min([this.chart.width, this.chart.height]), - xCenter: this.chart.width/2, - yCenter: this.chart.height/2 - }); - this.updateScaleRange(this.datasets); - this.scale.setScaleSize(); - this.scale.buildYLabels(); - }, - draw : function(ease){ - var easeDecimal = ease || 1, - ctx = this.chart.ctx; - this.clear(); - this.scale.draw(); - - helpers.each(this.datasets,function(dataset){ - - //Transition each point first so that the line and point drawing isn't out of sync - helpers.each(dataset.points,function(point,index){ - if (point.hasValue()){ - point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal); - } - },this); + Object.defineProperty(array, '_chartjs', { + configurable: true, + enumerable: false, + value: { + listeners: [listener] + } + }); + arrayEvents.forEach(function(key) { + var method = 'onData' + key.charAt(0).toUpperCase() + key.slice(1); + var base = array[key]; + Object.defineProperty(array, key, { + configurable: true, + enumerable: false, + value: function() { + var args = Array.prototype.slice.call(arguments); + var res = base.apply(this, args); - //Draw the line between all the points - ctx.lineWidth = this.options.datasetStrokeWidth; - ctx.strokeStyle = dataset.strokeColor; - ctx.beginPath(); - helpers.each(dataset.points,function(point,index){ - if (index === 0){ - ctx.moveTo(point.x,point.y); - } - else{ - ctx.lineTo(point.x,point.y); - } - },this); - ctx.closePath(); - ctx.stroke(); + helpers.each(array._chartjs.listeners, function(object) { + if (typeof object[method] === 'function') { + object[method].apply(object, args); + } + }); - ctx.fillStyle = dataset.fillColor; - ctx.fill(); + return res; + } + }); + }); + } - //Now draw the points over the line - //A little inefficient double looping, but better than the line - //lagging behind the point positions - helpers.each(dataset.points,function(point){ - if (point.hasValue()){ - point.draw(); - } - }); + /** + * Removes the given array event listener and cleanup extra attached properties (such as + * the _chartjs stub and overridden methods) if array doesn't have any more listeners. + */ + function unlistenArrayEvents(array, listener) { + var stub = array._chartjs; + if (!stub) { + return; + } - },this); + var listeners = stub.listeners; + var index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + if (listeners.length > 0) { + return; } - }); + arrayEvents.forEach(function(key) { + delete array[key]; + }); + delete array._chartjs; + } + // Base class for all dataset controllers (line, bar, etc) + Chart.DatasetController = function(chart, datasetIndex) { + this.initialize(chart, datasetIndex); + }; + helpers.extend(Chart.DatasetController.prototype, { + + /** + * Element type used to generate a meta dataset (e.g. Chart.element.Line). + * @type {Chart.core.element} + */ + datasetElementType: null, + + /** + * Element type used to generate a meta data (e.g. Chart.element.Point). + * @type {Chart.core.element} + */ + dataElementType: null, + + initialize: function(chart, datasetIndex) { + var me = this; + me.chart = chart; + me.index = datasetIndex; + me.linkScales(); + me.addElements(); + }, + updateIndex: function(datasetIndex) { + this.index = datasetIndex; + }, -}).call(this); - })(); -}); + linkScales: function() { + var me = this; + var meta = me.getMeta(); + var dataset = me.getDataset(); -require.register("jquery/dist/jquery.js", function(exports, require, module) { - require = __makeRelativeRequire(require, {}, "jquery"); - (function() { - /*! - * jQuery JavaScript Library v3.2.1 - * https://jquery.com/ - * - * Includes Sizzle.js - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://jquery.org/license - * - * Date: 2017-03-20T18:59Z - */ -( function( global, factory ) { + if (meta.xAxisID === null) { + meta.xAxisID = dataset.xAxisID || me.chart.options.scales.xAxes[0].id; + } + if (meta.yAxisID === null) { + meta.yAxisID = dataset.yAxisID || me.chart.options.scales.yAxes[0].id; + } + }, - "use strict"; + getDataset: function() { + return this.chart.data.datasets[this.index]; + }, - if ( typeof module === "object" && typeof module.exports === "object" ) { + getMeta: function() { + return this.chart.getDatasetMeta(this.index); + }, - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } + getScaleForId: function(scaleID) { + return this.chart.scales[scaleID]; + }, -// Pass this if window is not defined yet -} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + reset: function() { + this.update(true); + }, -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. -"use strict"; + /** + * @private + */ + destroy: function() { + if (this._data) { + unlistenArrayEvents(this._data, this); + } + }, -var arr = []; + createMetaDataset: function() { + var me = this; + var type = me.datasetElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index + }); + }, -var document = window.document; + createMetaData: function(index) { + var me = this; + var type = me.dataElementType; + return type && new type({ + _chart: me.chart, + _datasetIndex: me.index, + _index: index + }); + }, -var getProto = Object.getPrototypeOf; + addElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data || []; + var metaData = meta.data; + var i, ilen; -var slice = arr.slice; + for (i = 0, ilen = data.length; i < ilen; ++i) { + metaData[i] = metaData[i] || me.createMetaData(i); + } -var concat = arr.concat; + meta.dataset = meta.dataset || me.createMetaDataset(); + }, -var push = arr.push; + addElementAndReset: function(index) { + var element = this.createMetaData(index); + this.getMeta().data.splice(index, 0, element); + this.updateElement(element, index, true); + }, -var indexOf = arr.indexOf; + buildOrUpdateElements: function() { + var me = this; + var dataset = me.getDataset(); + var data = dataset.data || (dataset.data = []); + + // In order to correctly handle data addition/deletion animation (an thus simulate + // real-time charts), we need to monitor these data modifications and synchronize + // the internal meta data accordingly. + if (me._data !== data) { + if (me._data) { + // This case happens when the user replaced the data array instance. + unlistenArrayEvents(me._data, me); + } -var class2type = {}; + listenArrayEvents(data, me); + me._data = data; + } -var toString = class2type.toString; + // Re-sync meta data in case the user replaced the data array or if we missed + // any updates and so make sure that we handle number of datapoints changing. + me.resyncElements(); + }, -var hasOwn = class2type.hasOwnProperty; + update: helpers.noop, -var fnToString = hasOwn.toString; + transition: function(easingValue) { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; -var ObjectFunctionString = fnToString.call( Object ); + for (; i < ilen; ++i) { + elements[i].transition(easingValue); + } -var support = {}; + if (meta.dataset) { + meta.dataset.transition(easingValue); + } + }, + draw: function() { + var meta = this.getMeta(); + var elements = meta.data || []; + var ilen = elements.length; + var i = 0; + if (meta.dataset) { + meta.dataset.draw(); + } - function DOMEval( code, doc ) { - doc = doc || document; + for (; i < ilen; ++i) { + elements[i].draw(); + } + }, - var script = doc.createElement( "script" ); + removeHoverStyle: function(element, elementOpts) { + var dataset = this.chart.data.datasets[element._datasetIndex]; + var index = element._index; + var custom = element.custom || {}; + var valueOrDefault = helpers.valueAtIndexOrDefault; + var model = element._model; - script.text = code; - doc.head.appendChild( script ).parentNode.removeChild( script ); - } -/* global Symbol */ -// Defining this global in .eslintrc.json would create a danger of using the global -// unguarded in another place, it seems safer to define global only for this module + model.backgroundColor = custom.backgroundColor ? custom.backgroundColor : valueOrDefault(dataset.backgroundColor, index, elementOpts.backgroundColor); + model.borderColor = custom.borderColor ? custom.borderColor : valueOrDefault(dataset.borderColor, index, elementOpts.borderColor); + model.borderWidth = custom.borderWidth ? custom.borderWidth : valueOrDefault(dataset.borderWidth, index, elementOpts.borderWidth); + }, + setHoverStyle: function(element) { + var dataset = this.chart.data.datasets[element._datasetIndex]; + var index = element._index; + var custom = element.custom || {}; + var valueOrDefault = helpers.valueAtIndexOrDefault; + var getHoverColor = helpers.getHoverColor; + var model = element._model; + + model.backgroundColor = custom.hoverBackgroundColor ? custom.hoverBackgroundColor : valueOrDefault(dataset.hoverBackgroundColor, index, getHoverColor(model.backgroundColor)); + model.borderColor = custom.hoverBorderColor ? custom.hoverBorderColor : valueOrDefault(dataset.hoverBorderColor, index, getHoverColor(model.borderColor)); + model.borderWidth = custom.hoverBorderWidth ? custom.hoverBorderWidth : valueOrDefault(dataset.hoverBorderWidth, index, model.borderWidth); + }, + /** + * @private + */ + resyncElements: function() { + var me = this; + var meta = me.getMeta(); + var data = me.getDataset().data; + var numMeta = meta.data.length; + var numData = data.length; + + if (numData < numMeta) { + meta.data.splice(numData, numMeta - numData); + } else if (numData > numMeta) { + me.insertElements(numMeta, numData - numMeta); + } + }, -var - version = "3.2.1", + /** + * @private + */ + insertElements: function(start, count) { + for (var i = 0; i < count; ++i) { + this.addElementAndReset(start + i); + } + }, - // Define a local copy of jQuery - jQuery = function( selector, context ) { + /** + * @private + */ + onDataPush: function() { + this.insertElements(this.getDataset().data.length - 1, arguments.length); + }, - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, + /** + * @private + */ + onDataPop: function() { + this.getMeta().data.pop(); + }, - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + /** + * @private + */ + onDataShift: function() { + this.getMeta().data.shift(); + }, - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([a-z])/g, + /** + * @private + */ + onDataSplice: function(start, count) { + this.getMeta().data.splice(start, count); + this.insertElements(start, arguments.length - 2); + }, - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; + /** + * @private + */ + onDataUnshift: function() { + this.insertElements(0, arguments.length); + } + }); -jQuery.fn = jQuery.prototype = { + Chart.DatasetController.extend = helpers.inherits; +}; + })(); +}); - // The current version of jQuery being used - jquery: version, +require.register("chart.js/src/core/core.defaults.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - constructor: jQuery, +var helpers = require('../helpers/index'); - // The default length of a jQuery object is 0 - length: 0, +module.exports = { + /** + * @private + */ + _set: function(scope, values) { + return helpers.merge(this[scope] || (this[scope] = {}), values); + } +}; + })(); +}); - toArray: function() { - return slice.call( this ); - }, +require.register("chart.js/src/core/core.element.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { +var color = require('chartjs-color'); +var helpers = require('../helpers/index'); - // Return all the elements in a clean array - if ( num == null ) { - return slice.call( this ); +function interpolate(start, view, model, ease) { + var keys = Object.keys(model); + var i, ilen, key, actual, origin, target, type, c0, c1; + + for (i = 0, ilen = keys.length; i < ilen; ++i) { + key = keys[i]; + + target = model[key]; + + // if a value is added to the model after pivot() has been called, the view + // doesn't contain it, so let's initialize the view to the target value. + if (!view.hasOwnProperty(key)) { + view[key] = target; } - // Return just the one element from the set - return num < 0 ? this[ num + this.length ] : this[ num ]; - }, + actual = view[key]; - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { + if (actual === target || key[0] === '_') { + continue; + } - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); + if (!start.hasOwnProperty(key)) { + start[key] = actual; + } - // Add the old object onto the stack (as a reference) - ret.prevObject = this; + origin = start[key]; - // Return the newly-formed element set - return ret; - }, + type = typeof target; - // Execute a callback for every element in the matched set. - each: function( callback ) { - return jQuery.each( this, callback ); - }, + if (type === typeof origin) { + if (type === 'string') { + c0 = color(origin); + if (c0.valid) { + c1 = color(target); + if (c1.valid) { + view[key] = c1.mix(c0, ease).rgbString(); + continue; + } + } + } else if (type === 'number' && isFinite(origin) && isFinite(target)) { + view[key] = origin + (target - origin) * ease; + continue; + } + } - map: function( callback ) { - return this.pushStack( jQuery.map( this, function( elem, i ) { - return callback.call( elem, i, elem ); - } ) ); - }, + view[key] = target; + } +} - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, +var Element = function(configuration) { + helpers.extend(this, configuration); + this.initialize.apply(this, arguments); +}; - first: function() { - return this.eq( 0 ); - }, +helpers.extend(Element.prototype, { - last: function() { - return this.eq( -1 ); + initialize: function() { + this.hidden = false; }, - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + pivot: function() { + var me = this; + if (!me._view) { + me._view = helpers.clone(me._model); + } + me._start = {}; + return me; }, - end: function() { - return this.prevObject || this.constructor(); - }, + transition: function(ease) { + var me = this; + var model = me._model; + var start = me._start; + var view = me._view; - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; + // No animation -> No Transition + if (!model || ease === 1) { + me._view = model; + me._start = null; + return me; + } -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[ 0 ] || {}, - i = 1, - length = arguments.length, - deep = false; + if (!view) { + view = me._view = {}; + } - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; + if (!start) { + start = me._start = {}; + } - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } + interpolate(start, view, model, ease); - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { - target = {}; - } + return me; + }, - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; + tooltipPosition: function() { + return { + x: this._model.x, + y: this._model.y + }; + }, + + hasValue: function() { + return helpers.isNumber(this._model.x) && helpers.isNumber(this._model.y); } +}); - for ( ; i < length; i++ ) { +Element.extend = helpers.inherits; - // Only deal with non-null/undefined values - if ( ( options = arguments[ i ] ) != null ) { +module.exports = Element; + })(); +}); - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; +require.register("chart.js/src/core/core.helpers.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /* global window: false */ +/* global document: false */ +'use strict'; - // Prevent never-ending loop - if ( target === copy ) { - continue; +var color = require('chartjs-color'); +var defaults = require('./core.defaults'); +var helpers = require('../helpers/index'); + +module.exports = function(Chart) { + + // -- Basic js utility methods + + helpers.extend = function(base) { + var setFn = function(value, key) { + base[key] = value; + }; + for (var i = 1, ilen = arguments.length; i < ilen; i++) { + helpers.each(arguments[i], setFn); + } + return base; + }; + + helpers.configMerge = function(/* objects ... */) { + return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), { + merger: function(key, target, source, options) { + var tval = target[key] || {}; + var sval = source[key]; + + if (key === 'scales') { + // scale config merging is complex. Add our own function here for that + target[key] = helpers.scaleMerge(tval, sval); + } else if (key === 'scale') { + // used in polar area & radar charts since there is only one scale + target[key] = helpers.merge(tval, [Chart.scaleService.getScaleDefaults(sval.type), sval]); + } else { + helpers._merger(key, target, source, options); } + } + }); + }; - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject( copy ) || - ( copyIsArray = Array.isArray( copy ) ) ) ) { + helpers.scaleMerge = function(/* objects ... */) { + return helpers.merge(helpers.clone(arguments[0]), [].slice.call(arguments, 1), { + merger: function(key, target, source, options) { + if (key === 'xAxes' || key === 'yAxes') { + var slen = source[key].length; + var i, type, scale; - if ( copyIsArray ) { - copyIsArray = false; - clone = src && Array.isArray( src ) ? src : []; + if (!target[key]) { + target[key] = []; + } - } else { - clone = src && jQuery.isPlainObject( src ) ? src : {}; + for (i = 0; i < slen; ++i) { + scale = source[key][i]; + type = helpers.valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear'); + + if (i >= target[key].length) { + target[key].push({}); + } + + if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) { + // new/untyped scale or type changed: let's apply the new defaults + // then merge source scale to correctly overwrite the defaults. + helpers.merge(target[key][i], [Chart.scaleService.getScaleDefaults(type), scale]); + } else { + // scales type are the same + helpers.merge(target[key][i], scale); + } } + } else { + helpers._merger(key, target, source, options); + } + } + }); + }; - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); + helpers.where = function(collection, filterCallback) { + if (helpers.isArray(collection) && Array.prototype.filter) { + return collection.filter(filterCallback); + } + var filtered = []; - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; + helpers.each(collection, function(item) { + if (filterCallback(item)) { + filtered.push(item); + } + }); + + return filtered; + }; + helpers.findIndex = Array.prototype.findIndex ? + function(array, callback, scope) { + return array.findIndex(callback, scope); + } : + function(array, callback, scope) { + scope = scope === undefined ? array : scope; + for (var i = 0, ilen = array.length; i < ilen; ++i) { + if (callback.call(scope, array[i], i, array)) { + return i; } } + return -1; + }; + helpers.findNextWhere = function(arrayToSearch, filterCallback, startIndex) { + // Default to start of the array + if (helpers.isNullOrUndef(startIndex)) { + startIndex = -1; + } + for (var i = startIndex + 1; i < arrayToSearch.length; i++) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)) { + return currentItem; + } } - } + }; + helpers.findPreviousWhere = function(arrayToSearch, filterCallback, startIndex) { + // Default to end of the array + if (helpers.isNullOrUndef(startIndex)) { + startIndex = arrayToSearch.length; + } + for (var i = startIndex - 1; i >= 0; i--) { + var currentItem = arrayToSearch[i]; + if (filterCallback(currentItem)) { + return currentItem; + } + } + }; + helpers.inherits = function(extensions) { + // Basic javascript inheritance based on the model created in Backbone.js + var me = this; + var ChartElement = (extensions && extensions.hasOwnProperty('constructor')) ? extensions.constructor : function() { + return me.apply(this, arguments); + }; - // Return the modified object - return target; -}; + var Surrogate = function() { + this.constructor = ChartElement; + }; + Surrogate.prototype = me.prototype; + ChartElement.prototype = new Surrogate(); -jQuery.extend( { + ChartElement.extend = helpers.inherits; - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + if (extensions) { + helpers.extend(ChartElement.prototype, extensions); + } - // Assume jQuery is ready without the ready module - isReady: true, + ChartElement.__super__ = me.prototype; - error: function( msg ) { - throw new Error( msg ); - }, + return ChartElement; + }; + // -- Math methods + helpers.isNumber = function(n) { + return !isNaN(parseFloat(n)) && isFinite(n); + }; + helpers.almostEquals = function(x, y, epsilon) { + return Math.abs(x - y) < epsilon; + }; + helpers.almostWhole = function(x, epsilon) { + var rounded = Math.round(x); + return (((rounded - epsilon) < x) && ((rounded + epsilon) > x)); + }; + helpers.max = function(array) { + return array.reduce(function(max, value) { + if (!isNaN(value)) { + return Math.max(max, value); + } + return max; + }, Number.NEGATIVE_INFINITY); + }; + helpers.min = function(array) { + return array.reduce(function(min, value) { + if (!isNaN(value)) { + return Math.min(min, value); + } + return min; + }, Number.POSITIVE_INFINITY); + }; + helpers.sign = Math.sign ? + function(x) { + return Math.sign(x); + } : + function(x) { + x = +x; // convert to a number + if (x === 0 || isNaN(x)) { + return x; + } + return x > 0 ? 1 : -1; + }; + helpers.log10 = Math.log10 ? + function(x) { + return Math.log10(x); + } : + function(x) { + return Math.log(x) / Math.LN10; + }; + helpers.toRadians = function(degrees) { + return degrees * (Math.PI / 180); + }; + helpers.toDegrees = function(radians) { + return radians * (180 / Math.PI); + }; + // Gets the angle from vertical upright to the point about a centre. + helpers.getAngleFromPoint = function(centrePoint, anglePoint) { + var distanceFromXCenter = anglePoint.x - centrePoint.x; + var distanceFromYCenter = anglePoint.y - centrePoint.y; + var radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter); - noop: function() {}, + var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter); - isFunction: function( obj ) { - return jQuery.type( obj ) === "function"; - }, + if (angle < (-0.5 * Math.PI)) { + angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2] + } - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, + return { + angle: angle, + distance: radialDistanceFromCenter + }; + }; + helpers.distanceBetweenPoints = function(pt1, pt2) { + return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2)); + }; + helpers.aliasPixel = function(pixelWidth) { + return (pixelWidth % 2 === 0) ? 0 : 0.5; + }; + helpers.splineCurve = function(firstPoint, middlePoint, afterPoint, t) { + // Props to Rob Spencer at scaled innovation for his post on splining between points + // http://scaledinnovation.com/analytics/splines/aboutSplines.html - isNumeric: function( obj ) { + // This function must also respect "skipped" points - // As of jQuery 3.0, isNumeric is limited to - // strings and numbers (primitives or objects) - // that can be coerced to finite numbers (gh-2662) - var type = jQuery.type( obj ); - return ( type === "number" || type === "string" ) && + var previous = firstPoint.skip ? middlePoint : firstPoint; + var current = middlePoint; + var next = afterPoint.skip ? middlePoint : afterPoint; - // parseFloat NaNs numeric-cast false positives ("") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - !isNaN( obj - parseFloat( obj ) ); - }, + var d01 = Math.sqrt(Math.pow(current.x - previous.x, 2) + Math.pow(current.y - previous.y, 2)); + var d12 = Math.sqrt(Math.pow(next.x - current.x, 2) + Math.pow(next.y - current.y, 2)); - isPlainObject: function( obj ) { - var proto, Ctor; + var s01 = d01 / (d01 + d12); + var s12 = d12 / (d01 + d12); - // Detect obvious negatives - // Use toString instead of jQuery.type to catch host objects - if ( !obj || toString.call( obj ) !== "[object Object]" ) { - return false; - } + // If all points are the same, s01 & s02 will be inf + s01 = isNaN(s01) ? 0 : s01; + s12 = isNaN(s12) ? 0 : s12; - proto = getProto( obj ); + var fa = t * s01; // scaling factor for triangle Ta + var fb = t * s12; - // Objects with no prototype (e.g., `Object.create( null )`) are plain - if ( !proto ) { - return true; - } + return { + previous: { + x: current.x - fa * (next.x - previous.x), + y: current.y - fa * (next.y - previous.y) + }, + next: { + x: current.x + fb * (next.x - previous.x), + y: current.y + fb * (next.y - previous.y) + } + }; + }; + helpers.EPSILON = Number.EPSILON || 1e-14; + helpers.splineCurveMonotone = function(points) { + // This function calculates Bézier control points in a similar way than |splineCurve|, + // but preserves monotonicity of the provided data and ensures no local extremums are added + // between the dataset discrete points due to the interpolation. + // See : https://en.wikipedia.org/wiki/Monotone_cubic_interpolation + + var pointsWithTangents = (points || []).map(function(point) { + return { + model: point._model, + deltaK: 0, + mK: 0 + }; + }); - // Objects with prototype are plain iff they were constructed by a global Object function - Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; - return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; - }, + // Calculate slopes (deltaK) and initialize tangents (mK) + var pointsLen = pointsWithTangents.length; + var i, pointBefore, pointCurrent, pointAfter; + for (i = 0; i < pointsLen; ++i) { + pointCurrent = pointsWithTangents[i]; + if (pointCurrent.model.skip) { + continue; + } - isEmptyObject: function( obj ) { + pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; + pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; + if (pointAfter && !pointAfter.model.skip) { + var slopeDeltaX = (pointAfter.model.x - pointCurrent.model.x); - /* eslint-disable no-unused-vars */ - // See https://github.com/eslint/eslint/issues/6125 - var name; + // In the case of two points that appear at the same x pixel, slopeDeltaX is 0 + pointCurrent.deltaK = slopeDeltaX !== 0 ? (pointAfter.model.y - pointCurrent.model.y) / slopeDeltaX : 0; + } - for ( name in obj ) { - return false; + if (!pointBefore || pointBefore.model.skip) { + pointCurrent.mK = pointCurrent.deltaK; + } else if (!pointAfter || pointAfter.model.skip) { + pointCurrent.mK = pointBefore.deltaK; + } else if (this.sign(pointBefore.deltaK) !== this.sign(pointCurrent.deltaK)) { + pointCurrent.mK = 0; + } else { + pointCurrent.mK = (pointBefore.deltaK + pointCurrent.deltaK) / 2; + } } - return true; - }, - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } + // Adjust tangents to ensure monotonic properties + var alphaK, betaK, tauK, squaredMagnitude; + for (i = 0; i < pointsLen - 1; ++i) { + pointCurrent = pointsWithTangents[i]; + pointAfter = pointsWithTangents[i + 1]; + if (pointCurrent.model.skip || pointAfter.model.skip) { + continue; + } - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call( obj ) ] || "object" : - typeof obj; - }, + if (helpers.almostEquals(pointCurrent.deltaK, 0, this.EPSILON)) { + pointCurrent.mK = pointAfter.mK = 0; + continue; + } - // Evaluates a script in a global context - globalEval: function( code ) { - DOMEval( code ); - }, + alphaK = pointCurrent.mK / pointCurrent.deltaK; + betaK = pointAfter.mK / pointCurrent.deltaK; + squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2); + if (squaredMagnitude <= 9) { + continue; + } - // Convert dashed to camelCase; used by the css and data modules - // Support: IE <=9 - 11, Edge 12 - 13 - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, + tauK = 3 / Math.sqrt(squaredMagnitude); + pointCurrent.mK = alphaK * tauK * pointCurrent.deltaK; + pointAfter.mK = betaK * tauK * pointCurrent.deltaK; + } - each: function( obj, callback ) { - var length, i = 0; + // Compute control points + var deltaX; + for (i = 0; i < pointsLen; ++i) { + pointCurrent = pointsWithTangents[i]; + if (pointCurrent.model.skip) { + continue; + } - if ( isArrayLike( obj ) ) { - length = obj.length; - for ( ; i < length; i++ ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } + pointBefore = i > 0 ? pointsWithTangents[i - 1] : null; + pointAfter = i < pointsLen - 1 ? pointsWithTangents[i + 1] : null; + if (pointBefore && !pointBefore.model.skip) { + deltaX = (pointCurrent.model.x - pointBefore.model.x) / 3; + pointCurrent.model.controlPointPreviousX = pointCurrent.model.x - deltaX; + pointCurrent.model.controlPointPreviousY = pointCurrent.model.y - deltaX * pointCurrent.mK; } - } else { - for ( i in obj ) { - if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { - break; - } + if (pointAfter && !pointAfter.model.skip) { + deltaX = (pointAfter.model.x - pointCurrent.model.x) / 3; + pointCurrent.model.controlPointNextX = pointCurrent.model.x + deltaX; + pointCurrent.model.controlPointNextY = pointCurrent.model.y + deltaX * pointCurrent.mK; } } + }; + helpers.nextItem = function(collection, index, loop) { + if (loop) { + return index >= collection.length - 1 ? collection[0] : collection[index + 1]; + } + return index >= collection.length - 1 ? collection[collection.length - 1] : collection[index + 1]; + }; + helpers.previousItem = function(collection, index, loop) { + if (loop) { + return index <= 0 ? collection[collection.length - 1] : collection[index - 1]; + } + return index <= 0 ? collection[0] : collection[index - 1]; + }; + // Implementation of the nice number algorithm used in determining where axis labels will go + helpers.niceNum = function(range, round) { + var exponent = Math.floor(helpers.log10(range)); + var fraction = range / Math.pow(10, exponent); + var niceFraction; + + if (round) { + if (fraction < 1.5) { + niceFraction = 1; + } else if (fraction < 3) { + niceFraction = 2; + } else if (fraction < 7) { + niceFraction = 5; + } else { + niceFraction = 10; + } + } else if (fraction <= 1.0) { + niceFraction = 1; + } else if (fraction <= 2) { + niceFraction = 2; + } else if (fraction <= 5) { + niceFraction = 5; + } else { + niceFraction = 10; + } - return obj; - }, + return niceFraction * Math.pow(10, exponent); + }; + // Request animation polyfill - http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ + helpers.requestAnimFrame = (function() { + if (typeof window === 'undefined') { + return function(callback) { + callback(); + }; + } + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback) { + return window.setTimeout(callback, 1000 / 60); + }; + }()); + // -- DOM methods + helpers.getRelativePosition = function(evt, chart) { + var mouseX, mouseY; + var e = evt.originalEvent || evt; + var canvas = evt.currentTarget || evt.srcElement; + var boundingRect = canvas.getBoundingClientRect(); + + var touches = e.touches; + if (touches && touches.length > 0) { + mouseX = touches[0].clientX; + mouseY = touches[0].clientY; - // Support: Android <=4.0 only - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, + } else { + mouseX = e.clientX; + mouseY = e.clientY; + } - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; + // Scale mouse coordinates into canvas coordinates + // by following the pattern laid out by 'jerryj' in the comments of + // http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/ + var paddingLeft = parseFloat(helpers.getStyle(canvas, 'padding-left')); + var paddingTop = parseFloat(helpers.getStyle(canvas, 'padding-top')); + var paddingRight = parseFloat(helpers.getStyle(canvas, 'padding-right')); + var paddingBottom = parseFloat(helpers.getStyle(canvas, 'padding-bottom')); + var width = boundingRect.right - boundingRect.left - paddingLeft - paddingRight; + var height = boundingRect.bottom - boundingRect.top - paddingTop - paddingBottom; - if ( arr != null ) { - if ( isArrayLike( Object( arr ) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } + // We divide by the current device pixel ratio, because the canvas is scaled up by that amount in each direction. However + // the backend model is in unscaled coordinates. Since we are going to deal with our model coordinates, we go back here + mouseX = Math.round((mouseX - boundingRect.left - paddingLeft) / (width) * canvas.width / chart.currentDevicePixelRatio); + mouseY = Math.round((mouseY - boundingRect.top - paddingTop) / (height) * canvas.height / chart.currentDevicePixelRatio); - return ret; - }, + return { + x: mouseX, + y: mouseY + }; - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, + }; - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; + // Private helper function to convert max-width/max-height values that may be percentages into a number + function parseMaxStyle(styleValue, node, parentProperty) { + var valueInPixels; + if (typeof styleValue === 'string') { + valueInPixels = parseInt(styleValue, 10); - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; + if (styleValue.indexOf('%') !== -1) { + // percentage * size in dimension + valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty]; + } + } else { + valueInPixels = styleValue; } - first.length = i; + return valueInPixels; + } - return first; - }, + /** + * Returns if the given value contains an effective constraint. + * @private + */ + function isConstrainedValue(value) { + return value !== undefined && value !== null && value !== 'none'; + } - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; + // Private helper to get a constraint dimension + // @param domNode : the node to check the constraint on + // @param maxStyle : the style that defines the maximum for the direction we are using (maxWidth / maxHeight) + // @param percentageProperty : property of parent to use when calculating width as a percentage + // @see http://www.nathanaeljones.com/blog/2013/reading-max-width-cross-browser + function getConstraintDimension(domNode, maxStyle, percentageProperty) { + var view = document.defaultView; + var parentNode = domNode.parentNode; + var constrainedNode = view.getComputedStyle(domNode)[maxStyle]; + var constrainedContainer = view.getComputedStyle(parentNode)[maxStyle]; + var hasCNode = isConstrainedValue(constrainedNode); + var hasCContainer = isConstrainedValue(constrainedContainer); + var infinity = Number.POSITIVE_INFINITY; + + if (hasCNode || hasCContainer) { + return Math.min( + hasCNode ? parseMaxStyle(constrainedNode, domNode, percentageProperty) : infinity, + hasCContainer ? parseMaxStyle(constrainedContainer, parentNode, percentageProperty) : infinity); + } + + return 'none'; + } + // returns Number or undefined if no constraint + helpers.getConstraintWidth = function(domNode) { + return getConstraintDimension(domNode, 'max-width', 'clientWidth'); + }; + // returns Number or undefined if no constraint + helpers.getConstraintHeight = function(domNode) { + return getConstraintDimension(domNode, 'max-height', 'clientHeight'); + }; + helpers.getMaximumWidth = function(domNode) { + var container = domNode.parentNode; + if (!container) { + return domNode.clientWidth; + } - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } + var paddingLeft = parseInt(helpers.getStyle(container, 'padding-left'), 10); + var paddingRight = parseInt(helpers.getStyle(container, 'padding-right'), 10); + var w = container.clientWidth - paddingLeft - paddingRight; + var cw = helpers.getConstraintWidth(domNode); + return isNaN(cw) ? w : Math.min(w, cw); + }; + helpers.getMaximumHeight = function(domNode) { + var container = domNode.parentNode; + if (!container) { + return domNode.clientHeight; } - return matches; - }, + var paddingTop = parseInt(helpers.getStyle(container, 'padding-top'), 10); + var paddingBottom = parseInt(helpers.getStyle(container, 'padding-bottom'), 10); + var h = container.clientHeight - paddingTop - paddingBottom; + var ch = helpers.getConstraintHeight(domNode); + return isNaN(ch) ? h : Math.min(h, ch); + }; + helpers.getStyle = function(el, property) { + return el.currentStyle ? + el.currentStyle[property] : + document.defaultView.getComputedStyle(el, null).getPropertyValue(property); + }; + helpers.retinaScale = function(chart, forceRatio) { + var pixelRatio = chart.currentDevicePixelRatio = forceRatio || window.devicePixelRatio || 1; + if (pixelRatio === 1) { + return; + } - // arg is for internal usage only - map: function( elems, callback, arg ) { - var length, value, - i = 0, - ret = []; + var canvas = chart.canvas; + var height = chart.height; + var width = chart.width; - // Go through the array, translating each of the items to their new values - if ( isArrayLike( elems ) ) { - length = elems.length; - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); + canvas.height = height * pixelRatio; + canvas.width = width * pixelRatio; + chart.ctx.scale(pixelRatio, pixelRatio); - if ( value != null ) { - ret.push( value ); - } + // If no style has been set on the canvas, the render size is used as display size, + // making the chart visually bigger, so let's enforce it to the "correct" values. + // See https://github.com/chartjs/Chart.js/issues/3575 + canvas.style.height = height + 'px'; + canvas.style.width = width + 'px'; + }; + // -- Canvas methods + helpers.fontString = function(pixelSize, fontStyle, fontFamily) { + return fontStyle + ' ' + pixelSize + 'px ' + fontFamily; + }; + helpers.longestText = function(ctx, font, arrayOfThings, cache) { + cache = cache || {}; + var data = cache.data = cache.data || {}; + var gc = cache.garbageCollect = cache.garbageCollect || []; + + if (cache.font !== font) { + data = cache.data = {}; + gc = cache.garbageCollect = []; + cache.font = font; + } + + ctx.font = font; + var longest = 0; + helpers.each(arrayOfThings, function(thing) { + // Undefined strings and arrays should not be measured + if (thing !== undefined && thing !== null && helpers.isArray(thing) !== true) { + longest = helpers.measureText(ctx, data, gc, longest, thing); + } else if (helpers.isArray(thing)) { + // if it is an array lets measure each element + // to do maybe simplify this function a bit so we can do this more recursively? + helpers.each(thing, function(nestedThing) { + // Undefined strings and arrays should not be measured + if (nestedThing !== undefined && nestedThing !== null && !helpers.isArray(nestedThing)) { + longest = helpers.measureText(ctx, data, gc, longest, nestedThing); + } + }); } + }); - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } + var gcLen = gc.length / 2; + if (gcLen > arrayOfThings.length) { + for (var i = 0; i < gcLen; i++) { + delete data[gc[i]]; } + gc.splice(0, gcLen); } + return longest; + }; + helpers.measureText = function(ctx, data, gc, longest, string) { + var textWidth = data[string]; + if (!textWidth) { + textWidth = data[string] = ctx.measureText(string).width; + gc.push(string); + } + if (textWidth > longest) { + longest = textWidth; + } + return longest; + }; + helpers.numberOfLabelLines = function(arrayOfThings) { + var numberOfLines = 1; + helpers.each(arrayOfThings, function(thing) { + if (helpers.isArray(thing)) { + if (thing.length > numberOfLines) { + numberOfLines = thing.length; + } + } + }); + return numberOfLines; + }; - // Flatten any nested arrays - return concat.apply( [], ret ); - }, + helpers.color = !color ? + function(value) { + console.error('Color.js not found!'); + return value; + } : + function(value) { + /* global CanvasGradient */ + if (value instanceof CanvasGradient) { + value = defaults.global.defaultColor; + } - // A global GUID counter for objects - guid: 1, + return color(value); + }; - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; + helpers.getHoverColor = function(colorValue) { + /* global CanvasPattern */ + return (colorValue instanceof CanvasPattern) ? + colorValue : + helpers.color(colorValue).saturate(0.5).darken(0.1).rgbString(); + }; +}; + })(); +}); - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } +require.register("chart.js/src/core/core.interaction.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } +var helpers = require('../helpers/index'); - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); +/** + * Helper function to get relative position for an event + * @param {Event|IEvent} event - The event to get the position for + * @param {Chart} chart - The chart + * @returns {Point} the event position + */ +function getRelativePosition(e, chart) { + if (e.native) { + return { + x: e.x, + y: e.y }; + } - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, + return helpers.getRelativePosition(e, chart); +} - now: Date.now, +/** + * Helper function to traverse all of the visible elements in the chart + * @param chart {chart} the chart + * @param handler {Function} the callback to execute for each visible item + */ +function parseVisibleItems(chart, handler) { + var datasets = chart.data.datasets; + var meta, i, j, ilen, jlen; - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -} ); + for (i = 0, ilen = datasets.length; i < ilen; ++i) { + if (!chart.isDatasetVisible(i)) { + continue; + } -if ( typeof Symbol === "function" ) { - jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; + meta = chart.getDatasetMeta(i); + for (j = 0, jlen = meta.data.length; j < jlen; ++j) { + var element = meta.data[j]; + if (!element._view.skip) { + handler(element); + } + } + } } -// Populate the class2type map -jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), -function( i, name ) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -} ); +/** + * Helper function to get the items that intersect the event position + * @param items {ChartElement[]} elements to filter + * @param position {Point} the point to be nearest to + * @return {ChartElement[]} the nearest items + */ +function getIntersectItems(chart, position) { + var elements = []; -function isArrayLike( obj ) { + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + } + }); - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, - type = jQuery.type( obj ); + return elements; +} - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } +/** + * Helper function to get the items nearest to the event position considering all visible items in teh chart + * @param chart {Chart} the chart to look at elements from + * @param position {Point} the point to be nearest to + * @param intersect {Boolean} if true, only consider items that intersect the position + * @param distanceMetric {Function} function to provide the distance between points + * @return {ChartElement[]} the nearest items + */ +function getNearestItems(chart, position, intersect, distanceMetric) { + var minDistance = Number.POSITIVE_INFINITY; + var nearestItems = []; - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; + parseVisibleItems(chart, function(element) { + if (intersect && !element.inRange(position.x, position.y)) { + return; + } + + var center = element.getCenterPoint(); + var distance = distanceMetric(position, center); + + if (distance < minDistance) { + nearestItems = [element]; + minDistance = distance; + } else if (distance === minDistance) { + // Can have multiple items at the same distance in which case we sort by size + nearestItems.push(element); + } + }); + + return nearestItems; } -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.3 - * https://sizzlejs.com/ - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2016-08-08 + +/** + * Get a distance metric function for two points based on the + * axis mode setting + * @param {String} axis the axis mode. x|y|xy */ -(function( window ) { +function getDistanceMetricForAxis(axis) { + var useX = axis.indexOf('x') !== -1; + var useY = axis.indexOf('y') !== -1; + + return function(pt1, pt2) { + var deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0; + var deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0; + return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2)); + }; +} -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, +function indexMode(chart, e, options) { + var position = getRelativePosition(e, chart); + // Default axis for index mode is 'x' to match old behaviour + options.axis = options.axis || 'x'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + var elements = []; - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, + if (!items.length) { + return []; + } - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, + chart.data.datasets.forEach(function(dataset, datasetIndex) { + if (chart.isDatasetVisible(datasetIndex)) { + var meta = chart.getDatasetMeta(datasetIndex); + var element = meta.data[items[0]._index]; - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; + // don't count items that are skipped (null data) + if (element && !element._view.skip) { + elements.push(element); } } - return -1; - }, + }); - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + return elements; +} - // Regular expressions +/** + * @interface IInteractionOptions + */ +/** + * If true, only consider items that intersect the point + * @name IInterfaceOptions#boolean + * @type Boolean + */ - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", +/** + * Contains interaction related functions + * @namespace Chart.Interaction + */ +module.exports = { + // Helper function for different modes + modes: { + single: function(chart, e) { + var position = getRelativePosition(e, chart); + var elements = []; + + parseVisibleItems(chart, function(element) { + if (element.inRange(position.x, position.y)) { + elements.push(element); + return elements; + } + }); - // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + return elements.slice(0, 1); + }, - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", + /** + * @function Chart.Interaction.modes.label + * @deprecated since version 2.4.0 + * @todo remove at version 3 + * @private + */ + label: indexMode, + + /** + * Returns items at the same index. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect mode is false, we find the nearest item and return the items at the same index as that item + * @function Chart.Interaction.modes.index + * @since v2.4.0 + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @param options {IInteractionOptions} options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + index: indexMode, + + /** + * Returns items in the same dataset. If the options.intersect parameter is true, we only return items if we intersect something + * If the options.intersect is false, we find the nearest item and return the items in that dataset + * @function Chart.Interaction.modes.dataset + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @param options {IInteractionOptions} options to use during interaction + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + dataset: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric); + + if (items.length > 0) { + items = chart.getDatasetMeta(items[0]._datasetIndex).data; + } + + return items; + }, - pseudos = ":(" + identifier + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", + /** + * @function Chart.Interaction.modes.x-axis + * @deprecated since version 2.4.0. Use index mode and intersect == true + * @todo remove at version 3 + * @private + */ + 'x-axis': function(chart, e) { + return indexMode(chart, e, {intersect: true}); + }, - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + /** + * Point mode returns all elements that hit test based on the event position + * of the event + * @function Chart.Interaction.modes.intersect + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + point: function(chart, e) { + var position = getRelativePosition(e, chart); + return getIntersectItems(chart, position); + }, - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + /** + * nearest mode returns the element closest to the point + * @function Chart.Interaction.modes.intersect + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @param options {IInteractionOptions} options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + nearest: function(chart, e, options) { + var position = getRelativePosition(e, chart); + options.axis = options.axis || 'xy'; + var distanceMetric = getDistanceMetricForAxis(options.axis); + var nearestItems = getNearestItems(chart, position, options.intersect, distanceMetric); + + // We have multiple items at the same distance from the event. Now sort by smallest + if (nearestItems.length > 1) { + nearestItems.sort(function(a, b) { + var sizeA = a.getArea(); + var sizeB = b.getArea(); + var ret = sizeA - sizeB; + + if (ret === 0) { + // if equal sort by dataset index + ret = a._datasetIndex - b._datasetIndex; + } - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + return ret; + }); + } - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), + // Return only 1 item + return nearestItems.slice(0, 1); + }, - matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, + /** + * x mode returns the elements that hit-test at the current x coordinate + * @function Chart.Interaction.modes.x + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @param options {IInteractionOptions} options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + x: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inXRange(position.x)) { + items.push(element); + } - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); - rnative = /^[^{]+\{\s*\[native \w/, + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + }, - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + /** + * y mode returns the elements that hit-test at the current y coordinate + * @function Chart.Interaction.modes.y + * @param chart {chart} the chart we are returning items from + * @param e {Event} the event we are find things at + * @param options {IInteractionOptions} options to use + * @return {Chart.Element[]} Array of elements that are under the point. If none are found, an empty array is returned + */ + y: function(chart, e, options) { + var position = getRelativePosition(e, chart); + var items = []; + var intersectsItem = false; + + parseVisibleItems(chart, function(element) { + if (element.inYRange(position.y)) { + items.push(element); + } - rsibling = /[+~]/, + if (element.inRange(position.x, position.y)) { + intersectsItem = true; + } + }); - // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + // If we want to trigger on an intersect and we don't have any items + // that intersect the position, return nothing + if (options.intersect && !intersectsItem) { + items = []; + } + return items; + } + } +}; + })(); +}); + +require.register("chart.js/src/core/core.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('./core.defaults'); + +defaults._set('global', { + responsive: true, + responsiveAnimationDuration: 0, + maintainAspectRatio: true, + events: ['mousemove', 'mouseout', 'click', 'touchstart', 'touchmove'], + hover: { + onHover: null, + mode: 'nearest', + intersect: true, + animationDuration: 400 }, + onClick: null, + defaultColor: 'rgba(0,0,0,0.1)', + defaultFontColor: '#666', + defaultFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif", + defaultFontSize: 12, + defaultFontStyle: 'normal', + showLines: true, + + // Element defaults defined in element extensions + elements: {}, + + // Layout options such as padding + layout: { + padding: { + top: 0, + right: 0, + bottom: 0, + left: 0 + } + } +}); - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { +module.exports = function() { - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } + // Occupy the global variable of Chart, and create a simple base class + var Chart = function(item, config) { + this.construct(item, config); + return this; + }; - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; - } + Chart.Chart = Chart; - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; - }, + return Chart; +}; + })(); +}); - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }, +require.register("chart.js/src/core/core.layoutService.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - disabledAncestor = addCombinator( - function( elem ) { - return elem.disabled === true && ("form" in elem || "label" in elem); - }, - { dir: "parentNode", next: "legend" } - ); +var helpers = require('../helpers/index'); -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? +module.exports = function(Chart) { - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : + function filterByPosition(array, position) { + return helpers.where(array, function(v) { + return v.position === position; + }); + } - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} + function sortByWeight(array, reverse) { + array.forEach(function(v, i) { + v._tmpIndex_ = i; + return v; + }); + array.sort(function(a, b) { + var v0 = reverse ? b : a; + var v1 = reverse ? a : b; + return v0.weight === v1.weight ? + v0._tmpIndex_ - v1._tmpIndex_ : + v0.weight - v1.weight; + }); + array.forEach(function(v) { + delete v._tmpIndex_; + }); + } -function Sizzle( selector, context, results, seed ) { - var m, i, elem, nid, match, groups, newSelector, - newContext = context && context.ownerDocument, + /** + * @interface ILayoutItem + * @prop {String} position - The position of the item in the chart layout. Possible values are + * 'left', 'top', 'right', 'bottom', and 'chartArea' + * @prop {Number} weight - The weight used to sort the item. Higher weights are further away from the chart area + * @prop {Boolean} fullWidth - if true, and the item is horizontal, then push vertical boxes down + * @prop {Function} isHorizontal - returns true if the layout item is horizontal (ie. top or bottom) + * @prop {Function} update - Takes two parameters: width and height. Returns size of item + * @prop {Function} getPadding - Returns an object with padding on the edges + * @prop {Number} width - Width of item. Must be valid after update() + * @prop {Number} height - Height of item. Must be valid after update() + * @prop {Number} left - Left edge of the item. Set by layout system and cannot be used in update + * @prop {Number} top - Top edge of the item. Set by layout system and cannot be used in update + * @prop {Number} right - Right edge of the item. Set by layout system and cannot be used in update + * @prop {Number} bottom - Bottom edge of the item. Set by layout system and cannot be used in update + */ - // nodeType defaults to 9, since context defaults to document - nodeType = context ? context.nodeType : 9; + // The layout service is very self explanatory. It's responsible for the layout within a chart. + // Scales, Legends and Plugins all rely on the layout service and can easily register to be placed anywhere they need + // It is this service's responsibility of carrying out that layout. + Chart.layoutService = { + defaults: {}, + + /** + * Register a box to a chart. + * A box is simply a reference to an object that requires layout. eg. Scales, Legend, Title. + * @param {Chart} chart - the chart to use + * @param {ILayoutItem} item - the item to add to be layed out + */ + addBox: function(chart, item) { + if (!chart.boxes) { + chart.boxes = []; + } + + // initialize item with default values + item.fullWidth = item.fullWidth || false; + item.position = item.position || 'top'; + item.weight = item.weight || 0; + + chart.boxes.push(item); + }, - results = results || []; + /** + * Remove a layoutItem from a chart + * @param {Chart} chart - the chart to remove the box from + * @param {Object} layoutItem - the item to remove from the layout + */ + removeBox: function(chart, layoutItem) { + var index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1; + if (index !== -1) { + chart.boxes.splice(index, 1); + } + }, - // Return early from calls with invalid selector or context - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + /** + * Sets (or updates) options on the given `item`. + * @param {Chart} chart - the chart in which the item lives (or will be added to) + * @param {Object} item - the item to configure with the given options + * @param {Object} options - the new item options. + */ + configure: function(chart, item, options) { + var props = ['fullWidth', 'position', 'weight']; + var ilen = props.length; + var i = 0; + var prop; - return results; - } + for (; i < ilen; ++i) { + prop = props[i]; + if (options.hasOwnProperty(prop)) { + item[prop] = options[prop]; + } + } + }, - // Try to shortcut find operations (as opposed to filters) in HTML documents - if ( !seed ) { + /** + * Fits boxes of the given chart into the given size by having each box measure itself + * then running a fitting algorithm + * @param {Chart} chart - the chart + * @param {Number} width - the width to fit into + * @param {Number} height - the height to fit into + */ + update: function(chart, width, height) { + if (!chart) { + return; + } - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - context = context || document; + var layoutOptions = chart.options.layout || {}; + var padding = helpers.options.toPadding(layoutOptions.padding); + var leftPadding = padding.left; + var rightPadding = padding.right; + var topPadding = padding.top; + var bottomPadding = padding.bottom; + + var leftBoxes = filterByPosition(chart.boxes, 'left'); + var rightBoxes = filterByPosition(chart.boxes, 'right'); + var topBoxes = filterByPosition(chart.boxes, 'top'); + var bottomBoxes = filterByPosition(chart.boxes, 'bottom'); + var chartAreaBoxes = filterByPosition(chart.boxes, 'chartArea'); + + // Sort boxes by weight. A higher weight is further away from the chart area + sortByWeight(leftBoxes, true); + sortByWeight(rightBoxes, false); + sortByWeight(topBoxes, true); + sortByWeight(bottomBoxes, false); + + // Essentially we now have any number of boxes on each of the 4 sides. + // Our canvas looks like the following. + // The areas L1 and L2 are the left axes. R1 is the right axis, T1 is the top axis and + // B1 is the bottom axis + // There are also 4 quadrant-like locations (left to right instead of clockwise) reserved for chart overlays + // These locations are single-box locations only, when trying to register a chartArea location that is already taken, + // an error will be thrown. + // + // |----------------------------------------------------| + // | T1 (Full Width) | + // |----------------------------------------------------| + // | | | T2 | | + // | |----|-------------------------------------|----| + // | | | C1 | | C2 | | + // | | |----| |----| | + // | | | | | + // | L1 | L2 | ChartArea (C0) | R1 | + // | | | | | + // | | |----| |----| | + // | | | C3 | | C4 | | + // | |----|-------------------------------------|----| + // | | | B1 | | + // |----------------------------------------------------| + // | B2 (Full Width) | + // |----------------------------------------------------| + // + // What we do to find the best sizing, we do the following + // 1. Determine the minimum size of the chart area. + // 2. Split the remaining width equally between each vertical axis + // 3. Split the remaining height equally between each horizontal axis + // 4. Give each layout the maximum size it can be. The layout will return it's minimum size + // 5. Adjust the sizes of each axis based on it's minimum reported size. + // 6. Refit each axis + // 7. Position each axis in the final location + // 8. Tell the chart the final location of the chart area + // 9. Tell any axes that overlay the chart area the positions of the chart area + + // Step 1 + var chartWidth = width - leftPadding - rightPadding; + var chartHeight = height - topPadding - bottomPadding; + var chartAreaWidth = chartWidth / 2; // min 50% + var chartAreaHeight = chartHeight / 2; // min 50% + + // Step 2 + var verticalBoxWidth = (width - chartAreaWidth) / (leftBoxes.length + rightBoxes.length); + + // Step 3 + var horizontalBoxHeight = (height - chartAreaHeight) / (topBoxes.length + bottomBoxes.length); + + // Step 4 + var maxChartAreaWidth = chartWidth; + var maxChartAreaHeight = chartHeight; + var minBoxSizes = []; + + function getMinimumBoxSize(box) { + var minSize; + var isHorizontal = box.isHorizontal(); + + if (isHorizontal) { + minSize = box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, horizontalBoxHeight); + maxChartAreaHeight -= minSize.height; + } else { + minSize = box.update(verticalBoxWidth, chartAreaHeight); + maxChartAreaWidth -= minSize.width; + } - if ( documentIsHTML ) { + minBoxSizes.push({ + horizontal: isHorizontal, + minSize: minSize, + box: box, + }); + } - // If the selector is sufficiently simple, try using a "get*By*" DOM method - // (excepting DocumentFragment context, where the methods don't exist) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + helpers.each(leftBoxes.concat(rightBoxes, topBoxes, bottomBoxes), getMinimumBoxSize); - // ID selector - if ( (m = match[1]) ) { + // If a horizontal box has padding, we move the left boxes over to avoid ugly charts (see issue #2478) + var maxHorizontalLeftPadding = 0; + var maxHorizontalRightPadding = 0; + var maxVerticalTopPadding = 0; + var maxVerticalBottomPadding = 0; - // Document context - if ( nodeType === 9 ) { - if ( (elem = context.getElementById( m )) ) { + helpers.each(topBoxes.concat(bottomBoxes), function(horizontalBox) { + if (horizontalBox.getPadding) { + var boxPadding = horizontalBox.getPadding(); + maxHorizontalLeftPadding = Math.max(maxHorizontalLeftPadding, boxPadding.left); + maxHorizontalRightPadding = Math.max(maxHorizontalRightPadding, boxPadding.right); + } + }); - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } + helpers.each(leftBoxes.concat(rightBoxes), function(verticalBox) { + if (verticalBox.getPadding) { + var boxPadding = verticalBox.getPadding(); + maxVerticalTopPadding = Math.max(maxVerticalTopPadding, boxPadding.top); + maxVerticalBottomPadding = Math.max(maxVerticalBottomPadding, boxPadding.bottom); + } + }); - // Element context - } else { + // At this point, maxChartAreaHeight and maxChartAreaWidth are the size the chart area could + // be if the axes are drawn at their minimum sizes. + // Steps 5 & 6 + var totalLeftBoxesWidth = leftPadding; + var totalRightBoxesWidth = rightPadding; + var totalTopBoxesHeight = topPadding; + var totalBottomBoxesHeight = bottomPadding; + + // Function to fit a box + function fitBox(box) { + var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minBox) { + return minBox.box === box; + }); - // Support: IE, Opera, Webkit - // TODO: identify versions - // getElementById can match elements by name instead of ID - if ( newContext && (elem = newContext.getElementById( m )) && - contains( context, elem ) && - elem.id === m ) { + if (minBoxSize) { + if (box.isHorizontal()) { + var scaleMargin = { + left: Math.max(totalLeftBoxesWidth, maxHorizontalLeftPadding), + right: Math.max(totalRightBoxesWidth, maxHorizontalRightPadding), + top: 0, + bottom: 0 + }; - results.push( elem ); - return results; - } + // Don't use min size here because of label rotation. When the labels are rotated, their rotation highly depends + // on the margin. Sometimes they need to increase in size slightly + box.update(box.fullWidth ? chartWidth : maxChartAreaWidth, chartHeight / 2, scaleMargin); + } else { + box.update(minBoxSize.minSize.width, maxChartAreaHeight); } + } + } - // Type selector - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; + // Update, and calculate the left and right margins for the horizontal boxes + helpers.each(leftBoxes.concat(rightBoxes), fitBox); - // Class selector - } else if ( (m = match[3]) && support.getElementsByClassName && - context.getElementsByClassName ) { + helpers.each(leftBoxes, function(box) { + totalLeftBoxesWidth += box.width; + }); - push.apply( results, context.getElementsByClassName( m ) ); - return results; + helpers.each(rightBoxes, function(box) { + totalRightBoxesWidth += box.width; + }); + + // Set the Left and Right margins for the horizontal boxes + helpers.each(topBoxes.concat(bottomBoxes), fitBox); + + // Figure out how much margin is on the top and bottom of the vertical boxes + helpers.each(topBoxes, function(box) { + totalTopBoxesHeight += box.height; + }); + + helpers.each(bottomBoxes, function(box) { + totalBottomBoxesHeight += box.height; + }); + + function finalFitVerticalBox(box) { + var minBoxSize = helpers.findNextWhere(minBoxSizes, function(minSize) { + return minSize.box === box; + }); + + var scaleMargin = { + left: 0, + right: 0, + top: totalTopBoxesHeight, + bottom: totalBottomBoxesHeight + }; + + if (minBoxSize) { + box.update(minBoxSize.minSize.width, maxChartAreaHeight, scaleMargin); } } - // Take advantage of querySelectorAll - if ( support.qsa && - !compilerCache[ selector + " " ] && - (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + // Let the left layout know the final margin + helpers.each(leftBoxes.concat(rightBoxes), finalFitVerticalBox); - if ( nodeType !== 1 ) { - newContext = context; - newSelector = selector; + // Recalculate because the size of each layout might have changed slightly due to the margins (label rotation for instance) + totalLeftBoxesWidth = leftPadding; + totalRightBoxesWidth = rightPadding; + totalTopBoxesHeight = topPadding; + totalBottomBoxesHeight = bottomPadding; - // qSA looks outside Element context, which is not what we want - // Thanks to Andrew Dupont for this workaround technique - // Support: IE <=8 - // Exclude object elements - } else if ( context.nodeName.toLowerCase() !== "object" ) { + helpers.each(leftBoxes, function(box) { + totalLeftBoxesWidth += box.width; + }); - // Capture the context ID, setting it first if necessary - if ( (nid = context.getAttribute( "id" )) ) { - nid = nid.replace( rcssescape, fcssescape ); - } else { - context.setAttribute( "id", (nid = expando) ); - } + helpers.each(rightBoxes, function(box) { + totalRightBoxesWidth += box.width; + }); - // Prefix every selector in the list - groups = tokenize( selector ); - i = groups.length; - while ( i-- ) { - groups[i] = "#" + nid + " " + toSelector( groups[i] ); - } - newSelector = groups.join( "," ); + helpers.each(topBoxes, function(box) { + totalTopBoxesHeight += box.height; + }); + helpers.each(bottomBoxes, function(box) { + totalBottomBoxesHeight += box.height; + }); - // Expand context for sibling selectors - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || - context; - } + // We may be adding some padding to account for rotated x axis labels + var leftPaddingAddition = Math.max(maxHorizontalLeftPadding - totalLeftBoxesWidth, 0); + totalLeftBoxesWidth += leftPaddingAddition; + totalRightBoxesWidth += Math.max(maxHorizontalRightPadding - totalRightBoxesWidth, 0); - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch ( qsaError ) { - } finally { - if ( nid === expando ) { - context.removeAttribute( "id" ); - } + var topPaddingAddition = Math.max(maxVerticalTopPadding - totalTopBoxesHeight, 0); + totalTopBoxesHeight += topPaddingAddition; + totalBottomBoxesHeight += Math.max(maxVerticalBottomPadding - totalBottomBoxesHeight, 0); + + // Figure out if our chart area changed. This would occur if the dataset layout label rotation + // changed due to the application of the margins in step 6. Since we can only get bigger, this is safe to do + // without calling `fit` again + var newMaxChartAreaHeight = height - totalTopBoxesHeight - totalBottomBoxesHeight; + var newMaxChartAreaWidth = width - totalLeftBoxesWidth - totalRightBoxesWidth; + + if (newMaxChartAreaWidth !== maxChartAreaWidth || newMaxChartAreaHeight !== maxChartAreaHeight) { + helpers.each(leftBoxes, function(box) { + box.height = newMaxChartAreaHeight; + }); + + helpers.each(rightBoxes, function(box) { + box.height = newMaxChartAreaHeight; + }); + + helpers.each(topBoxes, function(box) { + if (!box.fullWidth) { + box.width = newMaxChartAreaWidth; } - } + }); + + helpers.each(bottomBoxes, function(box) { + if (!box.fullWidth) { + box.width = newMaxChartAreaWidth; + } + }); + + maxChartAreaHeight = newMaxChartAreaHeight; + maxChartAreaWidth = newMaxChartAreaWidth; } - } - } - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} + // Step 7 - Position the boxes + var left = leftPadding + leftPaddingAddition; + var top = topPadding + topPaddingAddition; -/** - * Create key-value caches of limited size - * @returns {function(string, object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; + function placeBox(box) { + if (box.isHorizontal()) { + box.left = box.fullWidth ? leftPadding : totalLeftBoxesWidth; + box.right = box.fullWidth ? width - rightPadding : totalLeftBoxesWidth + maxChartAreaWidth; + box.top = top; + box.bottom = top + box.height; - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} + // Move to next point + top = box.bottom; -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} + } else { -/** - * Support testing using an element - * @param {Function} fn Passed the created element and returns a boolean result - */ -function assert( fn ) { - var el = document.createElement("fieldset"); + box.left = left; + box.right = left + box.width; + box.top = totalTopBoxesHeight; + box.bottom = totalTopBoxesHeight + maxChartAreaHeight; - try { - return !!fn( el ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( el.parentNode ) { - el.parentNode.removeChild( el ); - } - // release memory in IE - el = null; - } -} + // Move to next point + left = box.right; + } + } -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = arr.length; + helpers.each(leftBoxes.concat(topBoxes), placeBox); - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} + // Account for chart width and height + left += maxChartAreaWidth; + top += maxChartAreaHeight; -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; + helpers.each(rightBoxes, placeBox); + helpers.each(bottomBoxes, placeBox); - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } + // Step 8 + chart.chartArea = { + left: totalLeftBoxesWidth, + top: totalTopBoxesHeight, + right: totalLeftBoxesWidth + maxChartAreaWidth, + bottom: totalTopBoxesHeight + maxChartAreaHeight + }; - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } + // Step 9 + helpers.each(chartAreaBoxes, function(box) { + box.left = chart.chartArea.left; + box.top = chart.chartArea.top; + box.right = chart.chartArea.right; + box.bottom = chart.chartArea.bottom; + + box.update(maxChartAreaWidth, maxChartAreaHeight); + }); } - } + }; +}; + })(); +}); - return a ? 1 : -1; -} +require.register("chart.js/src/core/core.plugin.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} +var defaults = require('./core.defaults'); +var Element = require('./core.element'); +var helpers = require('../helpers/index'); -/** - * Returns a function to use in pseudos for :enabled/:disabled - * @param {Boolean} disabled true for :disabled; false for :enabled - */ -function createDisabledPseudo( disabled ) { +defaults._set('global', { + plugins: {} +}); - // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable - return function( elem ) { +module.exports = function(Chart) { - // Only certain elements can match :enabled or :disabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled - // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled - if ( "form" in elem ) { + /** + * The plugin service singleton + * @namespace Chart.plugins + * @since 2.1.0 + */ + Chart.plugins = { + /** + * Globally registered plugins. + * @private + */ + _plugins: [], + + /** + * This identifier is used to invalidate the descriptors cache attached to each chart + * when a global plugin is registered or unregistered. In this case, the cache ID is + * incremented and descriptors are regenerated during following API calls. + * @private + */ + _cacheId: 0, + + /** + * Registers the given plugin(s) if not already registered. + * @param {Array|Object} plugins plugin instance(s). + */ + register: function(plugins) { + var p = this._plugins; + ([]).concat(plugins).forEach(function(plugin) { + if (p.indexOf(plugin) === -1) { + p.push(plugin); + } + }); - // Check for inherited disabledness on relevant non-disabled elements: - // * listed form-associated elements in a disabled fieldset - // https://html.spec.whatwg.org/multipage/forms.html#category-listed - // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled - // * option elements in a disabled optgroup - // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled - // All such elements have a "form" property. - if ( elem.parentNode && elem.disabled === false ) { + this._cacheId++; + }, - // Option elements defer to a parent optgroup if present - if ( "label" in elem ) { - if ( "label" in elem.parentNode ) { - return elem.parentNode.disabled === disabled; - } else { - return elem.disabled === disabled; - } + /** + * Unregisters the given plugin(s) only if registered. + * @param {Array|Object} plugins plugin instance(s). + */ + unregister: function(plugins) { + var p = this._plugins; + ([]).concat(plugins).forEach(function(plugin) { + var idx = p.indexOf(plugin); + if (idx !== -1) { + p.splice(idx, 1); } + }); - // Support: IE 6 - 11 - // Use the isDisabled shortcut property to check for disabled fieldset ancestors - return elem.isDisabled === disabled || + this._cacheId++; + }, - // Where there is no isDisabled, check manually - /* jshint -W018 */ - elem.isDisabled !== !disabled && - disabledAncestor( elem ) === disabled; - } + /** + * Remove all registered plugins. + * @since 2.1.5 + */ + clear: function() { + this._plugins = []; + this._cacheId++; + }, - return elem.disabled === disabled; + /** + * Returns the number of registered plugins? + * @returns {Number} + * @since 2.1.5 + */ + count: function() { + return this._plugins.length; + }, - // Try to winnow out elements that can't be disabled before trusting the disabled property. - // Some victims get caught in our net (label, legend, menu, track), but it shouldn't - // even exist on them, let alone have a boolean value. - } else if ( "label" in elem ) { - return elem.disabled === disabled; - } + /** + * Returns all registered plugin instances. + * @returns {Array} array of plugin objects. + * @since 2.1.5 + */ + getAll: function() { + return this._plugins; + }, - // Remaining elements are neither :enabled nor :disabled - return false; - }; -} + /** + * Calls enabled plugins for `chart` on the specified hook and with the given args. + * This method immediately returns as soon as a plugin explicitly returns false. The + * returned value can be used, for instance, to interrupt the current action. + * @param {Object} chart - The chart instance for which plugins should be called. + * @param {String} hook - The name of the plugin method to call (e.g. 'beforeUpdate'). + * @param {Array} [args] - Extra arguments to apply to the hook call. + * @returns {Boolean} false if any of the plugins return false, else returns true. + */ + notify: function(chart, hook, args) { + var descriptors = this.descriptors(chart); + var ilen = descriptors.length; + var i, descriptor, plugin, params, method; + + for (i = 0; i < ilen; ++i) { + descriptor = descriptors[i]; + plugin = descriptor.plugin; + method = plugin[hook]; + if (typeof method === 'function') { + params = [chart].concat(args || []); + params.push(descriptor.options); + if (method.apply(plugin, params) === false) { + return false; + } + } + } -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; + return true; + }, - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); + /** + * Returns descriptors of enabled plugins for the given chart. + * @returns {Array} [{ plugin, options }] + * @private + */ + descriptors: function(chart) { + var cache = chart._plugins || (chart._plugins = {}); + if (cache.id === this._cacheId) { + return cache.descriptors; + } + + var plugins = []; + var descriptors = []; + var config = (chart && chart.config) || {}; + var options = (config.options && config.options.plugins) || {}; + + this._plugins.concat(config.plugins || []).forEach(function(plugin) { + var idx = plugins.indexOf(plugin); + if (idx !== -1) { + return; } - } - }); - }); -} -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} + var id = plugin.id; + var opts = options[id]; + if (opts === false) { + return; + } -// Expose support vars for convenience -support = Sizzle.support = {}; + if (opts === true) { + opts = helpers.clone(defaults.global.plugins[id]); + } -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; + plugins.push(plugin); + descriptors.push({ + plugin: plugin, + options: opts || {} + }); + }); + + cache.descriptors = descriptors; + cache.id = this._cacheId; + return descriptors; + } + }; + + /** + * Plugin extension hooks. + * @interface IPlugin + * @since 2.1.0 + */ + /** + * @method IPlugin#beforeInit + * @desc Called before initializing `chart`. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#afterInit + * @desc Called after `chart` has been initialized and before the first update. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeUpdate + * @desc Called before updating `chart`. If any plugin returns `false`, the update + * is cancelled (and thus subsequent render(s)) until another `update` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart update. + */ + /** + * @method IPlugin#afterUpdate + * @desc Called after `chart` has been updated and before rendering. Note that this + * hook will not be called if the chart update has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeDatasetsUpdate + * @desc Called before updating the `chart` datasets. If any plugin returns `false`, + * the datasets update is cancelled until another `update` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + * @returns {Boolean} false to cancel the datasets update. + * @since version 2.1.5 + */ + /** + * @method IPlugin#afterDatasetsUpdate + * @desc Called after the `chart` datasets have been updated. Note that this hook + * will not be called if the datasets update has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + * @since version 2.1.5 + */ + /** + * @method IPlugin#beforeDatasetUpdate + * @desc Called before updating the `chart` dataset at the given `args.index`. If any plugin + * returns `false`, the datasets update is cancelled until another `update` is triggered. + * @param {Chart} chart - The chart instance. + * @param {Object} args - The call arguments. + * @param {Number} args.index - The dataset index. + * @param {Object} args.meta - The dataset metadata. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart datasets drawing. + */ + /** + * @method IPlugin#afterDatasetUpdate + * @desc Called after the `chart` datasets at the given `args.index` has been updated. Note + * that this hook will not be called if the datasets update has been previously cancelled. + * @param {Chart} chart - The chart instance. + * @param {Object} args - The call arguments. + * @param {Number} args.index - The dataset index. + * @param {Object} args.meta - The dataset metadata. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeLayout + * @desc Called before laying out `chart`. If any plugin returns `false`, + * the layout update is cancelled until another `update` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart layout. + */ + /** + * @method IPlugin#afterLayout + * @desc Called after the `chart` has been layed out. Note that this hook will not + * be called if the layout update has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeRender + * @desc Called before rendering `chart`. If any plugin returns `false`, + * the rendering is cancelled until another `render` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart rendering. + */ + /** + * @method IPlugin#afterRender + * @desc Called after the `chart` has been fully rendered (and animation completed). Note + * that this hook will not be called if the rendering has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeDraw + * @desc Called before drawing `chart` at every animation frame specified by the given + * easing value. If any plugin returns `false`, the frame drawing is cancelled until + * another `render` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart drawing. + */ + /** + * @method IPlugin#afterDraw + * @desc Called after the `chart` has been drawn for the specific easing value. Note + * that this hook will not be called if the drawing has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeDatasetsDraw + * @desc Called before drawing the `chart` datasets. If any plugin returns `false`, + * the datasets drawing is cancelled until another `render` is triggered. + * @param {Chart.Controller} chart - The chart instance. + * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart datasets drawing. + */ + /** + * @method IPlugin#afterDatasetsDraw + * @desc Called after the `chart` datasets have been drawn. Note that this hook + * will not be called if the datasets drawing has been previously cancelled. + * @param {Chart.Controller} chart - The chart instance. + * @param {Number} easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeDatasetDraw + * @desc Called before drawing the `chart` dataset at the given `args.index` (datasets + * are drawn in the reverse order). If any plugin returns `false`, the datasets drawing + * is cancelled until another `render` is triggered. + * @param {Chart} chart - The chart instance. + * @param {Object} args - The call arguments. + * @param {Number} args.index - The dataset index. + * @param {Object} args.meta - The dataset metadata. + * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + * @returns {Boolean} `false` to cancel the chart datasets drawing. + */ + /** + * @method IPlugin#afterDatasetDraw + * @desc Called after the `chart` datasets at the given `args.index` have been drawn + * (datasets are drawn in the reverse order). Note that this hook will not be called + * if the datasets drawing has been previously cancelled. + * @param {Chart} chart - The chart instance. + * @param {Object} args - The call arguments. + * @param {Number} args.index - The dataset index. + * @param {Object} args.meta - The dataset metadata. + * @param {Number} args.easingValue - The current animation value, between 0.0 and 1.0. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#beforeEvent + * @desc Called before processing the specified `event`. If any plugin returns `false`, + * the event will be discarded. + * @param {Chart.Controller} chart - The chart instance. + * @param {IEvent} event - The event object. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#afterEvent + * @desc Called after the `event` has been consumed. Note that this hook + * will not be called if the `event` has been previously discarded. + * @param {Chart.Controller} chart - The chart instance. + * @param {IEvent} event - The event object. + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#resize + * @desc Called after the chart as been resized. + * @param {Chart.Controller} chart - The chart instance. + * @param {Number} size - The new canvas display size (eq. canvas.style width & height). + * @param {Object} options - The plugin options. + */ + /** + * @method IPlugin#destroy + * @desc Called after the chart as been destroyed. + * @param {Chart.Controller} chart - The chart instance. + * @param {Object} options - The plugin options. + */ + + /** + * Provided for backward compatibility, use Chart.plugins instead + * @namespace Chart.pluginService + * @deprecated since version 2.1.5 + * @todo remove at version 3 + * @private + */ + Chart.pluginService = Chart.plugins; + + /** + * Provided for backward compatibility, inheriting from Chart.PlugingBase has no + * effect, instead simply create/register plugins via plain JavaScript objects. + * @interface Chart.PluginBase + * @deprecated since version 2.5.0 + * @todo remove at version 3 + * @private + */ + Chart.PluginBase = Element.extend({}); }; + })(); +}); -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, - doc = node ? node.ownerDocument || node : preferredDoc; +require.register("chart.js/src/core/core.scale.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Return early if doc is invalid or already selected - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } +var defaults = require('./core.defaults'); +var Element = require('./core.element'); +var helpers = require('../helpers/index'); +var Ticks = require('./core.ticks'); - // Update global variables - document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); +defaults._set('scale', { + display: true, + position: 'left', + offset: false, - // Support: IE 9-11, Edge - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - if ( preferredDoc !== document && - (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + // grid line settings + gridLines: { + display: true, + color: 'rgba(0, 0, 0, 0.1)', + lineWidth: 1, + drawBorder: true, + drawOnChartArea: true, + drawTicks: true, + tickMarkLength: 10, + zeroLineWidth: 1, + zeroLineColor: 'rgba(0,0,0,0.25)', + zeroLineBorderDash: [], + zeroLineBorderDashOffset: 0.0, + offsetGridLines: false, + borderDash: [], + borderDashOffset: 0.0 + }, - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); + // scale label + scaleLabel: { + // display property + display: false, - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); + // actual label + labelString: '', + + // line height + lineHeight: 1.2, + + // top/bottom padding + padding: { + top: 4, + bottom: 4 } + }, + + // label settings + ticks: { + beginAtZero: false, + minRotation: 0, + maxRotation: 50, + mirror: false, + padding: 0, + reverse: false, + display: true, + autoSkip: true, + autoSkipPadding: 0, + labelOffset: 0, + // We pass through arrays to be rendered as multiline labels, we convert Others to strings here. + callback: Ticks.formatters.values, + minor: {}, + major: {} } +}); - /* Attributes - ---------------------------------------------------------------------- */ +function labelsFromTicks(ticks) { + var labels = []; + var i, ilen; - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( el ) { - el.className = "i"; - return !el.getAttribute("className"); - }); + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + labels.push(ticks[i].label); + } - /* getElement(s)By* - ---------------------------------------------------------------------- */ + return labels; +} - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( el ) { - el.appendChild( document.createComment("") ); - return !el.getElementsByTagName("*").length; - }); +function getLineValue(scale, index, offsetGridLines) { + var lineValue = scale.getPixelForTick(index); - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + if (offsetGridLines) { + if (index === 0) { + lineValue -= (scale.getPixelForTick(1) - lineValue) / 2; + } else { + lineValue -= (lineValue - scale.getPixelForTick(index - 1)) / 2; + } + } + return lineValue; +} - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; - }); +module.exports = function(Chart) { - // ID filter and find - if ( support.getById ) { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var elem = context.getElementById( id ); - return elem ? [ elem ] : []; - } - }; - } else { - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && - elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; + function computeTextSize(context, tick, font) { + return helpers.isArray(tick) ? + helpers.longestText(context, font, tick) : + context.measureText(tick).width; + } - // Support: IE 6 - 7 only - // getElementById is not reliable as a find shortcut - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var node, i, elems, - elem = context.getElementById( id ); + function parseFontOptions(options) { + var valueOrDefault = helpers.valueOrDefault; + var globalDefaults = defaults.global; + var size = valueOrDefault(options.fontSize, globalDefaults.defaultFontSize); + var style = valueOrDefault(options.fontStyle, globalDefaults.defaultFontStyle); + var family = valueOrDefault(options.fontFamily, globalDefaults.defaultFontFamily); - if ( elem ) { + return { + size: size, + style: style, + family: family, + font: helpers.fontString(size, style, family) + }; + } - // Verify the id attribute - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } + function parseLineHeight(options) { + return helpers.options.toLineHeight( + helpers.valueOrDefault(options.lineHeight, 1.2), + helpers.valueOrDefault(options.fontSize, defaults.global.defaultFontSize)); + } - // Fall back on getElementsByName - elems = context.getElementsByName( id ); - i = 0; - while ( (elem = elems[i++]) ) { - node = elem.getAttributeNode("id"); - if ( node && node.value === id ) { - return [ elem ]; - } + Chart.Scale = Element.extend({ + /** + * Get the padding needed for the scale + * @method getPadding + * @private + * @returns {Padding} the necessary padding + */ + getPadding: function() { + var me = this; + return { + left: me.paddingLeft || 0, + top: me.paddingTop || 0, + right: me.paddingRight || 0, + bottom: me.paddingBottom || 0 + }; + }, + + /** + * Returns the scale tick objects ({label, major}) + * @since 2.7 + */ + getTicks: function() { + return this._ticks; + }, + + // These methods are ordered by lifecyle. Utilities then follow. + // Any function defined here is inherited by all scale types. + // Any function can be extended by the scale type + + mergeTicksOptions: function() { + var ticks = this.options.ticks; + if (ticks.minor === false) { + ticks.minor = { + display: false + }; + } + if (ticks.major === false) { + ticks.major = { + display: false + }; + } + for (var key in ticks) { + if (key !== 'major' && key !== 'minor') { + if (typeof ticks.minor[key] === 'undefined') { + ticks.minor[key] = ticks[key]; + } + if (typeof ticks.major[key] === 'undefined') { + ticks.major[key] = ticks[key]; } } - - return []; } - }; - } + }, + beforeUpdate: function() { + helpers.callback(this.options.beforeUpdate, [this]); + }, + update: function(maxWidth, maxHeight, margins) { + var me = this; + var i, ilen, labels, label, ticks, tick; + + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); + + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = helpers.extend({ + left: 0, + right: 0, + top: 0, + bottom: 0 + }, margins); + me.longestTextCache = me.longestTextCache || {}; + + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + + // Data min/max + me.beforeDataLimits(); + me.determineDataLimits(); + me.afterDataLimits(); + + // Ticks - `this.ticks` is now DEPRECATED! + // Internal ticks are now stored as objects in the PRIVATE `this._ticks` member + // and must not be accessed directly from outside this class. `this.ticks` being + // around for long time and not marked as private, we can't change its structure + // without unexpected breaking changes. If you need to access the scale ticks, + // use scale.getTicks() instead. + + me.beforeBuildTicks(); + + // New implementations should return an array of objects but for BACKWARD COMPAT, + // we still support no return (`this.ticks` internally set by calling this method). + ticks = me.buildTicks() || []; + + me.afterBuildTicks(); + + me.beforeTickToLabelConversion(); + + // New implementations should return the formatted tick labels but for BACKWARD + // COMPAT, we still support no return (`this.ticks` internally changed by calling + // this method and supposed to contain only string values). + labels = me.convertTicksToLabels(ticks) || me.ticks; + + me.afterTickToLabelConversion(); + + me.ticks = labels; // BACKWARD COMPATIBILITY + + // IMPORTANT: from this point, we consider that `this.ticks` will NEVER change! + + // BACKWARD COMPAT: synchronize `_ticks` with labels (so potentially `this.ticks`) + for (i = 0, ilen = labels.length; i < ilen; ++i) { + label = labels[i]; + tick = ticks[i]; + if (!tick) { + ticks.push(tick = { + label: label, + major: false + }); + } else { + tick.label = label; + } + } - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); + me._ticks = ticks; - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : + // Tick Rotation + me.beforeCalculateTickRotation(); + me.calculateTickRotation(); + me.afterCalculateTickRotation(); + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); + return me.minSize; - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } + }, + afterUpdate: function() { + helpers.callback(this.options.afterUpdate, [this]); + }, - return tmp; + // + + beforeSetDimensions: function() { + helpers.callback(this.options.beforeSetDimensions, [this]); + }, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; } - return results; - }; - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; + }, + afterSetDimensions: function() { + helpers.callback(this.options.afterSetDimensions, [this]); + }, - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ + // Data limits + beforeDataLimits: function() { + helpers.callback(this.options.beforeDataLimits, [this]); + }, + determineDataLimits: helpers.noop, + afterDataLimits: function() { + helpers.callback(this.options.afterDataLimits, [this]); + }, - // QSA and matchesSelector support + // + beforeBuildTicks: function() { + helpers.callback(this.options.beforeBuildTicks, [this]); + }, + buildTicks: helpers.noop, + afterBuildTicks: function() { + helpers.callback(this.options.afterBuildTicks, [this]); + }, - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; + beforeTickToLabelConversion: function() { + helpers.callback(this.options.beforeTickToLabelConversion, [this]); + }, + convertTicksToLabels: function() { + var me = this; + // Convert ticks to strings + var tickOpts = me.options.ticks; + me.ticks = me.ticks.map(tickOpts.userCallback || tickOpts.callback, this); + }, + afterTickToLabelConversion: function() { + helpers.callback(this.options.afterTickToLabelConversion, [this]); + }, - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; + // - if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( el ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; + beforeCalculateTickRotation: function() { + helpers.callback(this.options.beforeCalculateTickRotation, [this]); + }, + calculateTickRotation: function() { + var me = this; + var context = me.ctx; + var tickOpts = me.options.ticks; + var labels = labelsFromTicks(me._ticks); + + // Get the width of each grid by calculating the difference + // between x offsets between 0 and 1. + var tickFont = parseFontOptions(tickOpts); + context.font = tickFont.font; + + var labelRotation = tickOpts.minRotation || 0; + + if (labels.length && me.options.display && me.isHorizontal()) { + var originalLabelWidth = helpers.longestText(context, tickFont.font, labels, me.longestTextCache); + var labelWidth = originalLabelWidth; + var cosRotation, sinRotation; + + // Allow 3 pixels x2 padding either side for label readability + var tickWidth = me.getPixelForTick(1) - me.getPixelForTick(0) - 6; + + // Max label rotation can be set or default to 90 - also act as a loop counter + while (labelWidth > tickWidth && labelRotation < tickOpts.maxRotation) { + var angleRadians = helpers.toRadians(labelRotation); + cosRotation = Math.cos(angleRadians); + sinRotation = Math.sin(angleRadians); + + if (sinRotation * originalLabelWidth > me.maxHeight) { + // go back one step + labelRotation--; + break; + } - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + labelRotation++; + labelWidth = cosRotation * originalLabelWidth; + } } - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } + me.labelRotation = labelRotation; + }, + afterCalculateTickRotation: function() { + helpers.callback(this.options.afterCalculateTickRotation, [this]); + }, - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } + // - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } + beforeFit: function() { + helpers.callback(this.options.beforeFit, [this]); + }, + fit: function() { + var me = this; + // Reset + var minSize = me.minSize = { + width: 0, + height: 0 + }; - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); + var labels = labelsFromTicks(me._ticks); - assert(function( el ) { - el.innerHTML = "" + - ""; + var opts = me.options; + var tickOpts = opts.ticks; + var scaleLabelOpts = opts.scaleLabel; + var gridLineOpts = opts.gridLines; + var display = opts.display; + var isHorizontal = me.isHorizontal(); - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement("input"); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); + var tickFont = parseFontOptions(tickOpts); + var tickMarkLength = opts.gridLines.tickMarkLength; - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + // Width + if (isHorizontal) { + // subtract the margins to line up with the chartArea if we are a full width scale + minSize.width = me.isFullWidth() ? me.maxWidth - me.margins.left - me.margins.right : me.maxWidth; + } else { + minSize.width = display && gridLineOpts.drawTicks ? tickMarkLength : 0; } - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll(":enabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); + // height + if (isHorizontal) { + minSize.height = display && gridLineOpts.drawTicks ? tickMarkLength : 0; + } else { + minSize.height = me.maxHeight; // fill all the height } - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll(":disabled").length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); + // Are we showing a title for the scale? + if (scaleLabelOpts.display && display) { + var scaleLabelLineHeight = parseLineHeight(scaleLabelOpts); + var scaleLabelPadding = helpers.options.toPadding(scaleLabelOpts.padding); + var deltaHeight = scaleLabelLineHeight + scaleLabelPadding.height; + + if (isHorizontal) { + minSize.height += deltaHeight; + } else { + minSize.width += deltaHeight; + } } - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } + // Don't bother fitting the ticks if we are not showing them + if (tickOpts.display && display) { + var largestTextWidth = helpers.longestText(me.ctx, tickFont.font, labels, me.longestTextCache); + var tallestLabelHeightInLines = helpers.numberOfLabelLines(labels); + var lineSpace = tickFont.size * 0.5; + var tickPadding = me.options.ticks.padding; - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { + if (isHorizontal) { + // A horizontal axis is more constrained by the height. + me.longestLabelWidth = largestTextWidth; - assert(function( el ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); + var angleRadians = helpers.toRadians(me.labelRotation); + var cosRotation = Math.cos(angleRadians); + var sinRotation = Math.sin(angleRadians); - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } + // TODO - improve this calculation + var labelHeight = (sinRotation * largestTextWidth) + + (tickFont.size * tallestLabelHeightInLines) + + (lineSpace * (tallestLabelHeightInLines - 1)) + + lineSpace; // padding - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + minSize.height = Math.min(me.maxHeight, minSize.height + labelHeight + tickPadding); - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); + me.ctx.font = tickFont.font; + var firstLabelWidth = computeTextSize(me.ctx, labels[0], tickFont.font); + var lastLabelWidth = computeTextSize(me.ctx, labels[labels.length - 1], tickFont.font); - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; + // Ensure that our ticks are always inside the canvas. When rotated, ticks are right aligned + // which means that the right padding is dominated by the font height + if (me.labelRotation !== 0) { + me.paddingLeft = opts.position === 'bottom' ? (cosRotation * firstLabelWidth) + 3 : (cosRotation * lineSpace) + 3; // add 3 px to move away from canvas edges + me.paddingRight = opts.position === 'bottom' ? (cosRotation * lineSpace) + 3 : (cosRotation * lastLabelWidth) + 3; + } else { + me.paddingLeft = firstLabelWidth / 2 + 3; // add 3 px to move away from canvas edges + me.paddingRight = lastLabelWidth / 2 + 3; } + } else { + // A vertical axis is more constrained by the width. Labels are the + // dominant factor here, so get that length first and account for padding + if (tickOpts.mirror) { + largestTextWidth = 0; + } else { + // use lineSpace for consistency with horizontal axis + // tickPadding is not implemented for horizontal + largestTextWidth += tickPadding + lineSpace; + } + + minSize.width = Math.min(me.maxWidth, minSize.width + largestTextWidth); + + me.paddingTop = tickFont.size / 2; + me.paddingBottom = tickFont.size / 2; } } - return false; - }; - /* Sorting - ---------------------------------------------------------------------- */ + me.handleMargins(); - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { + me.width = minSize.width; + me.height = minSize.height; + }, - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } + /** + * Handle margins and padding interactions + * @private + */ + handleMargins: function() { + var me = this; + if (me.margins) { + me.paddingLeft = Math.max(me.paddingLeft - me.margins.left, 0); + me.paddingTop = Math.max(me.paddingTop - me.margins.top, 0); + me.paddingRight = Math.max(me.paddingRight - me.margins.right, 0); + me.paddingBottom = Math.max(me.paddingBottom - me.margins.bottom, 0); + } + }, - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } + afterFit: function() { + helpers.callback(this.options.afterFit, [this]); + }, - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : + // Shared Methods + isHorizontal: function() { + return this.options.position === 'top' || this.options.position === 'bottom'; + }, + isFullWidth: function() { + return (this.options.fullWidth); + }, - // Otherwise we know they are disconnected - 1; + // Get the correct value. NaN bad inputs, If the value type is object get the x or y based on whether we are horizontal or not + getRightValue: function(rawValue) { + // Null and undefined values first + if (helpers.isNullOrUndef(rawValue)) { + return NaN; + } + // isNaN(object) returns true, so make sure NaN is checking for a number; Discard Infinite values + if (typeof rawValue === 'number' && !isFinite(rawValue)) { + return NaN; + } + // If it is in fact an object, dive in one more level + if (rawValue) { + if (this.isHorizontal()) { + if (rawValue.x !== undefined) { + return this.getRightValue(rawValue.x); + } + } else if (rawValue.y !== undefined) { + return this.getRightValue(rawValue.y); + } + } - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + // Value is good, return it + return rawValue; + }, - // Choose the first element that is related to our preferred document - if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; + // Used to get the value to display in the tooltip for the data at the given index + // function getLabelForIndex(index, datasetIndex) + getLabelForIndex: helpers.noop, + + // Used to get data value locations. Value can either be an index or a numerical value + getPixelForValue: helpers.noop, + + // Used to get the data value from a given pixel. This is the inverse of getPixelForValue + getValueForPixel: helpers.noop, + + // Used for tick location, should + getPixelForTick: function(index) { + var me = this; + var offset = me.options.offset; + if (me.isHorizontal()) { + var innerWidth = me.width - (me.paddingLeft + me.paddingRight); + var tickWidth = innerWidth / Math.max((me._ticks.length - (offset ? 0 : 1)), 1); + var pixel = (tickWidth * index) + me.paddingLeft; + + if (offset) { + pixel += tickWidth / 2; + } + + var finalVal = me.left + Math.round(pixel); + finalVal += me.isFullWidth() ? me.margins.left : 0; + return finalVal; } + var innerHeight = me.height - (me.paddingTop + me.paddingBottom); + return me.top + (index * (innerHeight / (me._ticks.length - 1))); + }, - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } + // Utility for getting the pixel location of a percentage of scale + getPixelForDecimal: function(decimal) { + var me = this; + if (me.isHorizontal()) { + var innerWidth = me.width - (me.paddingLeft + me.paddingRight); + var valueOffset = (innerWidth * decimal) + me.paddingLeft; - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } + var finalVal = me.left + Math.round(valueOffset); + finalVal += me.isFullWidth() ? me.margins.left : 0; + return finalVal; + } + return me.top + (decimal * me.height); + }, - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; + getBasePixel: function() { + return this.getPixelForValue(this.getBaseValue()); + }, - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === document ? -1 : - b === document ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + getBaseValue: function() { + var me = this; + var min = me.min; + var max = me.max; + + return me.beginAtZero ? 0 : + min < 0 && max < 0 ? max : + min > 0 && max > 0 ? min : 0; + }, - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } + /** + * Returns a subset of ticks to be plotted to avoid overlapping labels. + * @private + */ + _autoSkip: function(ticks) { + var skipRatio; + var me = this; + var isHorizontal = me.isHorizontal(); + var optionTicks = me.options.ticks.minor; + var tickCount = ticks.length; + var labelRotationRadians = helpers.toRadians(me.labelRotation); + var cosRotation = Math.cos(labelRotationRadians); + var longestRotatedLabel = me.longestLabelWidth * cosRotation; + var result = []; + var i, tick, shouldSkip; + + // figure out the maximum number of gridlines to show + var maxTicks; + if (optionTicks.maxTicksLimit) { + maxTicks = optionTicks.maxTicksLimit; + } + + if (isHorizontal) { + skipRatio = false; + + if ((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount > (me.width - (me.paddingLeft + me.paddingRight))) { + skipRatio = 1 + Math.floor(((longestRotatedLabel + optionTicks.autoSkipPadding) * tickCount) / (me.width - (me.paddingLeft + me.paddingRight))); + } - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } + // if they defined a max number of optionTicks, + // increase skipRatio until that number is met + if (maxTicks && tickCount > maxTicks) { + skipRatio = Math.max(skipRatio, Math.floor(tickCount / maxTicks)); + } + } - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } + for (i = 0; i < tickCount; i++) { + tick = ticks[i]; - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : + // Since we always show the last tick,we need may need to hide the last shown one before + shouldSkip = (skipRatio > 1 && i % skipRatio > 0) || (i % skipRatio === 0 && i + skipRatio >= tickCount); + if (shouldSkip && i !== tickCount - 1 || helpers.isNullOrUndef(tick.label)) { + // leave tick in place but make sure it's not displayed (#4635) + delete tick.label; + } + result.push(tick); + } + return result; + }, - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; + // Actually draw the scale on the canvas + // @param {rectangle} chartArea : the area of the chart to draw full grid lines on + draw: function(chartArea) { + var me = this; + var options = me.options; + if (!options.display) { + return; + } - return document; -}; + var context = me.ctx; + var globalDefaults = defaults.global; + var optionTicks = options.ticks.minor; + var optionMajorTicks = options.ticks.major || optionTicks; + var gridLines = options.gridLines; + var scaleLabel = options.scaleLabel; -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; + var isRotated = me.labelRotation !== 0; + var isHorizontal = me.isHorizontal(); -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } + var ticks = optionTicks.autoSkip ? me._autoSkip(me.getTicks()) : me.getTicks(); + var tickFontColor = helpers.valueOrDefault(optionTicks.fontColor, globalDefaults.defaultFontColor); + var tickFont = parseFontOptions(optionTicks); + var majorTickFontColor = helpers.valueOrDefault(optionMajorTicks.fontColor, globalDefaults.defaultFontColor); + var majorTickFont = parseFontOptions(optionMajorTicks); - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); + var tl = gridLines.drawTicks ? gridLines.tickMarkLength : 0; - if ( support.matchesSelector && documentIsHTML && - !compilerCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + var scaleLabelFontColor = helpers.valueOrDefault(scaleLabel.fontColor, globalDefaults.defaultFontColor); + var scaleLabelFont = parseFontOptions(scaleLabel); + var scaleLabelPadding = helpers.options.toPadding(scaleLabel.padding); + var labelRotationRadians = helpers.toRadians(me.labelRotation); - try { - var ret = matches.call( elem, expr ); + var itemsToDraw = []; - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } + var xTickStart = options.position === 'right' ? me.left : me.right - tl; + var xTickEnd = options.position === 'right' ? me.left + tl : me.right; + var yTickStart = options.position === 'bottom' ? me.top : me.bottom - tl; + var yTickEnd = options.position === 'bottom' ? me.top + tl : me.bottom; - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; + helpers.each(ticks, function(tick, index) { + // autoskipper skipped this tick (#4635) + if (tick.label === undefined) { + return; + } -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; + var label = tick.label; + var lineWidth, lineColor, borderDash, borderDashOffset; + if (index === me.zeroLineIndex && options.offset === gridLines.offsetGridLines) { + // Draw the first index specially + lineWidth = gridLines.zeroLineWidth; + lineColor = gridLines.zeroLineColor; + borderDash = gridLines.zeroLineBorderDash; + borderDashOffset = gridLines.zeroLineBorderDashOffset; + } else { + lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, index); + lineColor = helpers.valueAtIndexOrDefault(gridLines.color, index); + borderDash = helpers.valueOrDefault(gridLines.borderDash, globalDefaults.borderDash); + borderDashOffset = helpers.valueOrDefault(gridLines.borderDashOffset, globalDefaults.borderDashOffset); + } -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } + // Common properties + var tx1, ty1, tx2, ty2, x1, y1, x2, y2, labelX, labelY; + var textAlign = 'middle'; + var textBaseline = 'middle'; + var tickPadding = optionTicks.padding; - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; + if (isHorizontal) { + var labelYOffset = tl + tickPadding; - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; + if (options.position === 'bottom') { + // bottom + textBaseline = !isRotated ? 'top' : 'middle'; + textAlign = !isRotated ? 'center' : 'right'; + labelY = me.top + labelYOffset; + } else { + // top + textBaseline = !isRotated ? 'bottom' : 'middle'; + textAlign = !isRotated ? 'center' : 'left'; + labelY = me.bottom - labelYOffset; + } -Sizzle.escape = function( sel ) { - return (sel + "").replace( rcssescape, fcssescape ); -}; + var xLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1); + if (xLineValue < me.left) { + lineColor = 'rgba(0,0,0,0)'; + } + xLineValue += helpers.aliasPixel(lineWidth); -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; + labelX = me.getPixelForTick(index) + optionTicks.labelOffset; // x values for optionTicks (need to consider offsetLabel option) -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; + tx1 = tx2 = x1 = x2 = xLineValue; + ty1 = yTickStart; + ty2 = yTickEnd; + y1 = chartArea.top; + y2 = chartArea.bottom; + } else { + var isLeft = options.position === 'left'; + var labelXOffset; - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); + if (optionTicks.mirror) { + textAlign = isLeft ? 'left' : 'right'; + labelXOffset = tickPadding; + } else { + textAlign = isLeft ? 'right' : 'left'; + labelXOffset = tl + tickPadding; + } - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } + labelX = isLeft ? me.right - labelXOffset : me.left + labelXOffset; - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; + var yLineValue = getLineValue(me, index, gridLines.offsetGridLines && ticks.length > 1); + if (yLineValue < me.top) { + lineColor = 'rgba(0,0,0,0)'; + } + yLineValue += helpers.aliasPixel(lineWidth); - return results; -}; + labelY = me.getPixelForTick(index) + optionTicks.labelOffset; -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; + tx1 = xTickStart; + tx2 = xTickEnd; + x1 = chartArea.left; + x2 = chartArea.right; + ty1 = ty2 = y1 = y2 = yLineValue; + } - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes + itemsToDraw.push({ + tx1: tx1, + ty1: ty1, + tx2: tx2, + ty2: ty2, + x1: x1, + y1: y1, + x2: x2, + y2: y2, + labelX: labelX, + labelY: labelY, + glWidth: lineWidth, + glColor: lineColor, + glBorderDash: borderDash, + glBorderDashOffset: borderDashOffset, + rotation: -1 * labelRotationRadians, + label: label, + major: tick.major, + textBaseline: textBaseline, + textAlign: textAlign + }); + }); - return ret; -}; + // Draw all of the tick labels, tick marks, and grid lines at the correct places + helpers.each(itemsToDraw, function(itemToDraw) { + if (gridLines.display) { + context.save(); + context.lineWidth = itemToDraw.glWidth; + context.strokeStyle = itemToDraw.glColor; + if (context.setLineDash) { + context.setLineDash(itemToDraw.glBorderDash); + context.lineDashOffset = itemToDraw.glBorderDashOffset; + } -Expr = Sizzle.selectors = { + context.beginPath(); - // Can be adjusted by the user - cacheLength: 50, + if (gridLines.drawTicks) { + context.moveTo(itemToDraw.tx1, itemToDraw.ty1); + context.lineTo(itemToDraw.tx2, itemToDraw.ty2); + } - createPseudo: markFunction, + if (gridLines.drawOnChartArea) { + context.moveTo(itemToDraw.x1, itemToDraw.y1); + context.lineTo(itemToDraw.x2, itemToDraw.y2); + } - match: matchExpr, + context.stroke(); + context.restore(); + } - attrHandle: {}, + if (optionTicks.display) { + // Make sure we draw text in the correct color and font + context.save(); + context.translate(itemToDraw.labelX, itemToDraw.labelY); + context.rotate(itemToDraw.rotation); + context.font = itemToDraw.major ? majorTickFont.font : tickFont.font; + context.fillStyle = itemToDraw.major ? majorTickFontColor : tickFontColor; + context.textBaseline = itemToDraw.textBaseline; + context.textAlign = itemToDraw.textAlign; + + var label = itemToDraw.label; + if (helpers.isArray(label)) { + for (var i = 0, y = 0; i < label.length; ++i) { + // We just make sure the multiline element is a string here.. + context.fillText('' + label[i], 0, y); + // apply same lineSpacing as calculated @ L#320 + y += (tickFont.size * 1.5); + } + } else { + context.fillText(label, 0, 0); + } + context.restore(); + } + }); - find: {}, + if (scaleLabel.display) { + // Draw the scale label + var scaleLabelX; + var scaleLabelY; + var rotation = 0; + var halfLineHeight = parseLineHeight(scaleLabel) / 2; + + if (isHorizontal) { + scaleLabelX = me.left + ((me.right - me.left) / 2); // midpoint of the width + scaleLabelY = options.position === 'bottom' + ? me.bottom - halfLineHeight - scaleLabelPadding.bottom + : me.top + halfLineHeight + scaleLabelPadding.top; + } else { + var isLeft = options.position === 'left'; + scaleLabelX = isLeft + ? me.left + halfLineHeight + scaleLabelPadding.top + : me.right - halfLineHeight - scaleLabelPadding.top; + scaleLabelY = me.top + ((me.bottom - me.top) / 2); + rotation = isLeft ? -0.5 * Math.PI : 0.5 * Math.PI; + } - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, + context.save(); + context.translate(scaleLabelX, scaleLabelY); + context.rotate(rotation); + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillStyle = scaleLabelFontColor; // render in correct colour + context.font = scaleLabelFont.font; + context.fillText(scaleLabel.labelString, 0, 0); + context.restore(); + } + + if (gridLines.drawBorder) { + // Draw the line at the edge of the axis + context.lineWidth = helpers.valueAtIndexOrDefault(gridLines.lineWidth, 0); + context.strokeStyle = helpers.valueAtIndexOrDefault(gridLines.color, 0); + var x1 = me.left; + var x2 = me.right; + var y1 = me.top; + var y2 = me.bottom; + + var aliasPixel = helpers.aliasPixel(context.lineWidth); + if (isHorizontal) { + y1 = y2 = options.position === 'top' ? me.bottom : me.top; + y1 += aliasPixel; + y2 += aliasPixel; + } else { + x1 = x2 = options.position === 'left' ? me.right : me.left; + x1 += aliasPixel; + x2 += aliasPixel; + } - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); + context.beginPath(); + context.moveTo(x1, y1); + context.lineTo(x2, y2); + context.stroke(); + } + } + }); +}; + })(); +}); - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); +require.register("chart.js/src/core/core.scaleService.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } +var defaults = require('./core.defaults'); +var helpers = require('../helpers/index'); - return match.slice( 0, 4 ); - }, +module.exports = function(Chart) { - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); + Chart.scaleService = { + // Scale registration object. Extensions can register new scale types (such as log or DB scales) and then + // use the new chart options to grab the correct scale + constructors: {}, + // Use a registration function so that we can move to an ES6 map when we no longer need to support + // old browsers - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); + // Scale config defaults + defaults: {}, + registerScaleType: function(type, scaleConstructor, scaleDefaults) { + this.constructors[type] = scaleConstructor; + this.defaults[type] = helpers.clone(scaleDefaults); + }, + getScaleConstructor: function(type) { + return this.constructors.hasOwnProperty(type) ? this.constructors[type] : undefined; + }, + getScaleDefaults: function(type) { + // Return the scale defaults merged with the global settings so that we always use the latest ones + return this.defaults.hasOwnProperty(type) ? helpers.merge({}, [defaults.scale, this.defaults[type]]) : {}; + }, + updateScaleDefaults: function(type, additions) { + var me = this; + if (me.defaults.hasOwnProperty(type)) { + me.defaults[type] = helpers.extend(me.defaults[type], additions); + } + }, + addScalesToLayout: function(chart) { + // Adds each scale to the chart.boxes array to be sized accordingly + helpers.each(chart.scales, function(scale) { + // Set ILayoutItem parameters for backwards compatibility + scale.fullWidth = scale.options.fullWidth; + scale.position = scale.options.position; + scale.weight = scale.options.weight; + Chart.layoutService.addBox(chart, scale); + }); + } + }; +}; + })(); +}); + +require.register("chart.js/src/core/core.ticks.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var helpers = require('../helpers/index'); + +/** + * Namespace to hold static tick generation functions + * @namespace Chart.Ticks + */ +module.exports = { + /** + * Namespace to hold generators for different types of ticks + * @namespace Chart.Ticks.generators + */ + generators: { + /** + * Interface for the options provided to the numeric tick generator + * @interface INumericTickGenerationOptions + */ + /** + * The maximum number of ticks to display + * @name INumericTickGenerationOptions#maxTicks + * @type Number + */ + /** + * The distance between each tick. + * @name INumericTickGenerationOptions#stepSize + * @type Number + * @optional + */ + /** + * Forced minimum for the ticks. If not specified, the minimum of the data range is used to calculate the tick minimum + * @name INumericTickGenerationOptions#min + * @type Number + * @optional + */ + /** + * The maximum value of the ticks. If not specified, the maximum of the data range is used to calculate the tick maximum + * @name INumericTickGenerationOptions#max + * @type Number + * @optional + */ + + /** + * Generate a set of linear ticks + * @method Chart.Ticks.generators.linear + * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks + * @param dataRange {IRange} the range of the data + * @returns {Array} array of tick values + */ + linear: function(generationOptions, dataRange) { + var ticks = []; + // To get a "nice" value for the tick spacing, we will use the appropriately named + // "nice number" algorithm. See http://stackoverflow.com/questions/8506881/nice-label-algorithm-for-charts-with-minimum-ticks + // for details. + + var spacing; + if (generationOptions.stepSize && generationOptions.stepSize > 0) { + spacing = generationOptions.stepSize; + } else { + var niceRange = helpers.niceNum(dataRange.max - dataRange.min, false); + spacing = helpers.niceNum(niceRange / (generationOptions.maxTicks - 1), true); + } + var niceMin = Math.floor(dataRange.min / spacing) * spacing; + var niceMax = Math.ceil(dataRange.max / spacing) * spacing; + + // If min, max and stepSize is set and they make an evenly spaced scale use it. + if (generationOptions.min && generationOptions.max && generationOptions.stepSize) { + // If very close to our whole number, use it. + if (helpers.almostWhole((generationOptions.max - generationOptions.min) / generationOptions.stepSize, spacing / 1000)) { + niceMin = generationOptions.min; + niceMax = generationOptions.max; } + } - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + var numSpaces = (niceMax - niceMin) / spacing; + // If very close to our rounded value, use it. + if (helpers.almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) { + numSpaces = Math.round(numSpaces); + } else { + numSpaces = Math.ceil(numSpaces); + } - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); + // Put the values into the ticks array + ticks.push(generationOptions.min !== undefined ? generationOptions.min : niceMin); + for (var j = 1; j < numSpaces; ++j) { + ticks.push(niceMin + (j * spacing)); } + ticks.push(generationOptions.max !== undefined ? generationOptions.max : niceMax); - return match; + return ticks; }, - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; + /** + * Generate a set of logarithmic ticks + * @method Chart.Ticks.generators.logarithmic + * @param generationOptions {INumericTickGenerationOptions} the options used to generate the ticks + * @param dataRange {IRange} the range of the data + * @returns {Array} array of tick values + */ + logarithmic: function(generationOptions, dataRange) { + var ticks = []; + var valueOrDefault = helpers.valueOrDefault; + + // Figure out what the max number of ticks we can support it is based on the size of + // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 + // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on + // the graph + var tickVal = valueOrDefault(generationOptions.min, Math.pow(10, Math.floor(helpers.log10(dataRange.min)))); + + var endExp = Math.floor(helpers.log10(dataRange.max)); + var endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp)); + var exp, significand; + + if (tickVal === 0) { + exp = Math.floor(helpers.log10(dataRange.minNotZero)); + significand = Math.floor(dataRange.minNotZero / Math.pow(10, exp)); + + ticks.push(tickVal); + tickVal = significand * Math.pow(10, exp); + } else { + exp = Math.floor(helpers.log10(tickVal)); + significand = Math.floor(tickVal / Math.pow(10, exp)); } - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; + do { + ticks.push(tickVal); - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + ++significand; + if (significand === 10) { + significand = 1; + ++exp; + } - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } + tickVal = significand * Math.pow(10, exp); + } while (exp < endExp || (exp === endExp && significand < endSignificand)); - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); + var lastTick = valueOrDefault(generationOptions.max, tickVal); + ticks.push(lastTick); + + return ticks; } }, - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; + /** + * Namespace to hold formatters for different types of ticks + * @namespace Chart.Ticks.formatters + */ + formatters: { + /** + * Formatter for value labels + * @method Chart.Ticks.formatters.values + * @param value the value to display + * @return {String|Array} the label to display + */ + values: function(value) { + return helpers.isArray(value) ? value : '' + value; }, - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; + /** + * Formatter for linear numeric ticks + * @method Chart.Ticks.formatters.linear + * @param tickValue {Number} the value to be formatted + * @param index {Number} the position of the tickValue parameter in the ticks array + * @param ticks {Array} the list of ticks being converted + * @return {String} string representation of the tickValue parameter + */ + linear: function(tickValue, index, ticks) { + // If we have lots of ticks, don't use the ones + var delta = ticks.length > 3 ? ticks[2] - ticks[1] : ticks[1] - ticks[0]; + + // If we have a number like 2.5 as the delta, figure out how many decimal places we need + if (Math.abs(delta) > 1) { + if (tickValue !== Math.floor(tickValue)) { + // not an integer + delta = tickValue - Math.floor(tickValue); + } + } - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); + var logDelta = helpers.log10(Math.abs(delta)); + var tickString = ''; + + if (tickValue !== 0) { + var numDecimal = -1 * Math.floor(logDelta); + numDecimal = Math.max(Math.min(numDecimal, 20), 0); // toFixed has a max of 20 decimal places + tickString = tickValue.toFixed(numDecimal); + } else { + tickString = '0'; // never show decimal places for 0 + } + + return tickString; }, - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); + logarithmic: function(tickValue, index, ticks) { + var remain = tickValue / (Math.pow(10, Math.floor(helpers.log10(tickValue)))); - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; + if (tickValue === 0) { + return '0'; + } else if (remain === 1 || remain === 2 || remain === 5 || index === 0 || index === ticks.length - 1) { + return tickValue.toExponential(); + } + return ''; + } + } +}; + })(); +}); + +require.register("chart.js/src/core/core.tooltip.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('./core.defaults'); +var Element = require('./core.element'); +var helpers = require('../helpers/index'); + +defaults._set('global', { + tooltips: { + enabled: true, + custom: null, + mode: 'nearest', + position: 'average', + intersect: true, + backgroundColor: 'rgba(0,0,0,0.8)', + titleFontStyle: 'bold', + titleSpacing: 2, + titleMarginBottom: 6, + titleFontColor: '#fff', + titleAlign: 'left', + bodySpacing: 2, + bodyFontColor: '#fff', + bodyAlign: 'left', + footerFontStyle: 'bold', + footerSpacing: 2, + footerMarginTop: 6, + footerFontColor: '#fff', + footerAlign: 'left', + yPadding: 6, + xPadding: 6, + caretPadding: 2, + caretSize: 5, + cornerRadius: 6, + multiKeyBackground: '#fff', + displayColors: true, + borderColor: 'rgba(0,0,0,0)', + borderWidth: 0, + callbacks: { + // Args are: (tooltipItems, data) + beforeTitle: helpers.noop, + title: function(tooltipItems, data) { + // Pick first xLabel for now + var title = ''; + var labels = data.labels; + var labelCount = labels ? labels.length : 0; + + if (tooltipItems.length > 0) { + var item = tooltipItems[0]; + + if (item.xLabel) { + title = item.xLabel; + } else if (labelCount > 0 && item.index < labelCount) { + title = labels[item.index]; + } } - result += ""; + return title; + }, + afterTitle: helpers.noop, - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, + // Args are: (tooltipItems, data) + beforeBody: helpers.noop, - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; + // Args are: (tooltipItem, data) + beforeLabel: helpers.noop, + label: function(tooltipItem, data) { + var label = data.datasets[tooltipItem.datasetIndex].label || ''; - return first === 1 && last === 0 ? + if (label) { + label += ': '; + } + label += tooltipItem.yLabel; + return label; + }, + labelColor: function(tooltipItem, chart) { + var meta = chart.getDatasetMeta(tooltipItem.datasetIndex); + var activeElement = meta.data[tooltipItem.index]; + var view = activeElement._view; + return { + borderColor: view.borderColor, + backgroundColor: view.backgroundColor + }; + }, + labelTextColor: function() { + return this._options.bodyFontColor; + }, + afterLabel: helpers.noop, - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : + // Args are: (tooltipItems, data) + afterBody: helpers.noop, - function( elem, context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType, - diff = false; + // Args are: (tooltipItems, data) + beforeFooter: helpers.noop, + footer: helpers.noop, + afterFooter: helpers.noop + } + } +}); - if ( parent ) { +module.exports = function(Chart) { - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) { + /** + * Helper method to merge the opacity into a color + */ + function mergeOpacity(colorString, opacity) { + var color = helpers.color(colorString); + return color.alpha(opacity * color.alpha()).rgbaString(); + } - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } + // Helper to push or concat based on if the 2nd parameter is an array or not + function pushOrConcat(base, toPush) { + if (toPush) { + if (helpers.isArray(toPush)) { + // base = base.concat(toPush); + Array.prototype.push.apply(base, toPush); + } else { + base.push(toPush); + } + } - start = [ forward ? parent.firstChild : parent.lastChild ]; + return base; + } - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { + // Private helper to create a tooltip item model + // @param element : the chart element (point, arc, bar) to create the tooltip item for + // @return : new tooltip item + function createTooltipItem(element) { + var xScale = element._xScale; + var yScale = element._yScale || element._scale; // handle radar || polarArea charts + var index = element._index; + var datasetIndex = element._datasetIndex; - // Seek `elem` from a previously-cached index + return { + xLabel: xScale ? xScale.getLabelForIndex(index, datasetIndex) : '', + yLabel: yScale ? yScale.getLabelForIndex(index, datasetIndex) : '', + index: index, + datasetIndex: datasetIndex, + x: element._model.x, + y: element._model.y + }; + } - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || (node[ expando ] = {}); + /** + * Helper to get the reset model for the tooltip + * @param tooltipOpts {Object} the tooltip options + */ + function getBaseModel(tooltipOpts) { + var globalDefaults = defaults.global; + var valueOrDefault = helpers.valueOrDefault; - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + return { + // Positioning + xPadding: tooltipOpts.xPadding, + yPadding: tooltipOpts.yPadding, + xAlign: tooltipOpts.xAlign, + yAlign: tooltipOpts.yAlign, + + // Body + bodyFontColor: tooltipOpts.bodyFontColor, + _bodyFontFamily: valueOrDefault(tooltipOpts.bodyFontFamily, globalDefaults.defaultFontFamily), + _bodyFontStyle: valueOrDefault(tooltipOpts.bodyFontStyle, globalDefaults.defaultFontStyle), + _bodyAlign: tooltipOpts.bodyAlign, + bodyFontSize: valueOrDefault(tooltipOpts.bodyFontSize, globalDefaults.defaultFontSize), + bodySpacing: tooltipOpts.bodySpacing, + + // Title + titleFontColor: tooltipOpts.titleFontColor, + _titleFontFamily: valueOrDefault(tooltipOpts.titleFontFamily, globalDefaults.defaultFontFamily), + _titleFontStyle: valueOrDefault(tooltipOpts.titleFontStyle, globalDefaults.defaultFontStyle), + titleFontSize: valueOrDefault(tooltipOpts.titleFontSize, globalDefaults.defaultFontSize), + _titleAlign: tooltipOpts.titleAlign, + titleSpacing: tooltipOpts.titleSpacing, + titleMarginBottom: tooltipOpts.titleMarginBottom, + + // Footer + footerFontColor: tooltipOpts.footerFontColor, + _footerFontFamily: valueOrDefault(tooltipOpts.footerFontFamily, globalDefaults.defaultFontFamily), + _footerFontStyle: valueOrDefault(tooltipOpts.footerFontStyle, globalDefaults.defaultFontStyle), + footerFontSize: valueOrDefault(tooltipOpts.footerFontSize, globalDefaults.defaultFontSize), + _footerAlign: tooltipOpts.footerAlign, + footerSpacing: tooltipOpts.footerSpacing, + footerMarginTop: tooltipOpts.footerMarginTop, + + // Appearance + caretSize: tooltipOpts.caretSize, + cornerRadius: tooltipOpts.cornerRadius, + backgroundColor: tooltipOpts.backgroundColor, + opacity: 0, + legendColorBackground: tooltipOpts.multiKeyBackground, + displayColors: tooltipOpts.displayColors, + borderColor: tooltipOpts.borderColor, + borderWidth: tooltipOpts.borderWidth + }; + } - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex && cache[ 2 ]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; + /** + * Get the size of the tooltip + */ + function getTooltipSize(tooltip, model) { + var ctx = tooltip._chart.ctx; + + var height = model.yPadding * 2; // Tooltip Padding + var width = 0; + + // Count of all lines in the body + var body = model.body; + var combinedBodyLength = body.reduce(function(count, bodyItem) { + return count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length; + }, 0); + combinedBodyLength += model.beforeBody.length + model.afterBody.length; + + var titleLineCount = model.title.length; + var footerLineCount = model.footer.length; + var titleFontSize = model.titleFontSize; + var bodyFontSize = model.bodyFontSize; + var footerFontSize = model.footerFontSize; + + height += titleLineCount * titleFontSize; // Title Lines + height += titleLineCount ? (titleLineCount - 1) * model.titleSpacing : 0; // Title Line Spacing + height += titleLineCount ? model.titleMarginBottom : 0; // Title's bottom Margin + height += combinedBodyLength * bodyFontSize; // Body Lines + height += combinedBodyLength ? (combinedBodyLength - 1) * model.bodySpacing : 0; // Body Line Spacing + height += footerLineCount ? model.footerMarginTop : 0; // Footer Margin + height += footerLineCount * (footerFontSize); // Footer Lines + height += footerLineCount ? (footerLineCount - 1) * model.footerSpacing : 0; // Footer Line Spacing + + // Title width + var widthPadding = 0; + var maxLineWidth = function(line) { + width = Math.max(width, ctx.measureText(line).width + widthPadding); + }; - while ( (node = ++nodeIndex && node && node[ dir ] || + ctx.font = helpers.fontString(titleFontSize, model._titleFontStyle, model._titleFontFamily); + helpers.each(model.title, maxLineWidth); - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { + // Body width + ctx.font = helpers.fontString(bodyFontSize, model._bodyFontStyle, model._bodyFontFamily); + helpers.each(model.beforeBody.concat(model.afterBody), maxLineWidth); - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } + // Body lines may include some extra width due to the color box + widthPadding = model.displayColors ? (bodyFontSize + 2) : 0; + helpers.each(body, function(bodyItem) { + helpers.each(bodyItem.before, maxLineWidth); + helpers.each(bodyItem.lines, maxLineWidth); + helpers.each(bodyItem.after, maxLineWidth); + }); - } else { - // Use previously-cached element index if available - if ( useCache ) { - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || (node[ expando ] = {}); + // Reset back to 0 + widthPadding = 0; - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + // Footer width + ctx.font = helpers.fontString(footerFontSize, model._footerFontStyle, model._footerFontFamily); + helpers.each(model.footer, maxLineWidth); - cache = uniqueCache[ type ] || []; - nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; - diff = nodeIndex; - } + // Add padding + width += 2 * model.xPadding; - // xml :nth-child(...) - // or :nth-last-child(...) or :nth(-last)?-of-type(...) - if ( diff === false ) { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { + return { + width: width, + height: height + }; + } - if ( ( ofType ? - node.nodeName.toLowerCase() === name : - node.nodeType === 1 ) && - ++diff ) { + /** + * Helper to get the alignment of a tooltip given the size + */ + function determineAlignment(tooltip, size) { + var model = tooltip._model; + var chart = tooltip._chart; + var chartArea = tooltip._chart.chartArea; + var xAlign = 'center'; + var yAlign = 'center'; + + if (model.y < size.height) { + yAlign = 'top'; + } else if (model.y > (chart.height - size.height)) { + yAlign = 'bottom'; + } + + var lf, rf; // functions to determine left, right alignment + var olf, orf; // functions to determine if left/right alignment causes tooltip to go outside chart + var yf; // function to get the y alignment if the tooltip goes outside of the left or right edges + var midX = (chartArea.left + chartArea.right) / 2; + var midY = (chartArea.top + chartArea.bottom) / 2; + + if (yAlign === 'center') { + lf = function(x) { + return x <= midX; + }; + rf = function(x) { + return x > midX; + }; + } else { + lf = function(x) { + return x <= (size.width / 2); + }; + rf = function(x) { + return x >= (chart.width - (size.width / 2)); + }; + } - // Cache the index of each encountered element - if ( useCache ) { - outerCache = node[ expando ] || (node[ expando ] = {}); + olf = function(x) { + return x + size.width > chart.width; + }; + orf = function(x) { + return x - size.width < 0; + }; + yf = function(y) { + return y <= midY ? 'top' : 'bottom'; + }; - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - (outerCache[ node.uniqueID ] = {}); + if (lf(model.x)) { + xAlign = 'left'; - uniqueCache[ type ] = [ dirruns, diff ]; - } + // Is tooltip too wide and goes over the right side of the chart.? + if (olf(model.x)) { + xAlign = 'center'; + yAlign = yf(model.y); + } + } else if (rf(model.x)) { + xAlign = 'right'; - if ( node === elem ) { - break; - } - } - } - } - } + // Is tooltip too wide and goes outside left edge of canvas? + if (orf(model.x)) { + xAlign = 'center'; + yAlign = yf(model.y); + } + } - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, + var opts = tooltip._options; + return { + xAlign: opts.xAlign ? opts.xAlign : xAlign, + yAlign: opts.yAlign ? opts.yAlign : yAlign + }; + } - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); + /** + * @Helper to get the location a tooltip needs to be placed at given the initial position (via the vm) and the size and alignment + */ + function getBackgroundPoint(vm, size, alignment) { + // Background Position + var x = vm.x; + var y = vm.y; + + var caretSize = vm.caretSize; + var caretPadding = vm.caretPadding; + var cornerRadius = vm.cornerRadius; + var xAlign = alignment.xAlign; + var yAlign = alignment.yAlign; + var paddingAndSize = caretSize + caretPadding; + var radiusAndPadding = cornerRadius + caretPadding; + + if (xAlign === 'right') { + x -= size.width; + } else if (xAlign === 'center') { + x -= (size.width / 2); + } + + if (yAlign === 'top') { + y += paddingAndSize; + } else if (yAlign === 'bottom') { + y -= size.height + paddingAndSize; + } else { + y -= (size.height / 2); + } - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); + if (yAlign === 'center') { + if (xAlign === 'left') { + x += paddingAndSize; + } else if (xAlign === 'right') { + x -= paddingAndSize; } + } else if (xAlign === 'left') { + x -= radiusAndPadding; + } else if (xAlign === 'right') { + x += radiusAndPadding; + } - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } + return { + x: x, + y: y + }; + } - return fn; - } - }, + Chart.Tooltip = Element.extend({ + initialize: function() { + this._model = getBaseModel(this._options); + }, - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); + // Get the title + // Args are: (tooltipItem, data) + getTitle: function() { + var me = this; + var opts = me._options; + var callbacks = opts.callbacks; - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; + var beforeTitle = callbacks.beforeTitle.apply(me, arguments); + var title = callbacks.title.apply(me, arguments); + var afterTitle = callbacks.afterTitle.apply(me, arguments); - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), + var lines = []; + lines = pushOrConcat(lines, beforeTitle); + lines = pushOrConcat(lines, title); + lines = pushOrConcat(lines, afterTitle); - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), + return lines; + }, - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), + // Args are: (tooltipItem, data) + getBeforeBody: function() { + var lines = this._options.callbacks.beforeBody.apply(this, arguments); + return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; + }, - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + // Args are: (tooltipItem, data) + getBody: function(tooltipItems, data) { + var me = this; + var callbacks = me._options.callbacks; + var bodyItems = []; + + helpers.each(tooltipItems, function(tooltipItem) { + var bodyItem = { + before: [], + lines: [], + after: [] + }; + pushOrConcat(bodyItem.before, callbacks.beforeLabel.call(me, tooltipItem, data)); + pushOrConcat(bodyItem.lines, callbacks.label.call(me, tooltipItem, data)); + pushOrConcat(bodyItem.after, callbacks.afterLabel.call(me, tooltipItem, data)); - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), + bodyItems.push(bodyItem); + }); - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; + return bodyItems; }, - "root": function( elem ) { - return elem === docElem; + // Args are: (tooltipItem, data) + getAfterBody: function() { + var lines = this._options.callbacks.afterBody.apply(this, arguments); + return helpers.isArray(lines) ? lines : lines !== undefined ? [lines] : []; }, - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, + // Get the footer and beforeFooter and afterFooter lines + // Args are: (tooltipItem, data) + getFooter: function() { + var me = this; + var callbacks = me._options.callbacks; - // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), + var beforeFooter = callbacks.beforeFooter.apply(me, arguments); + var footer = callbacks.footer.apply(me, arguments); + var afterFooter = callbacks.afterFooter.apply(me, arguments); - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + var lines = []; + lines = pushOrConcat(lines, beforeFooter); + lines = pushOrConcat(lines, footer); + lines = pushOrConcat(lines, afterFooter); + + return lines; }, - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; + update: function(changed) { + var me = this; + var opts = me._options; + + // Need to regenerate the model because its faster than using extend and it is necessary due to the optimization in Chart.Element.transition + // that does _view = _model if ease === 1. This causes the 2nd tooltip update to set properties in both the view and model at the same time + // which breaks any animations. + var existingModel = me._model; + var model = me._model = getBaseModel(opts); + var active = me._active; + + var data = me._data; + + // In the case where active.length === 0 we need to keep these at existing values for good animations + var alignment = { + xAlign: existingModel.xAlign, + yAlign: existingModel.yAlign + }; + var backgroundPoint = { + x: existingModel.x, + y: existingModel.y + }; + var tooltipSize = { + width: existingModel.width, + height: existingModel.height + }; + var tooltipPosition = { + x: existingModel.caretX, + y: existingModel.caretY + }; + + var i, len; + + if (active.length) { + model.opacity = 1; + + var labelColors = []; + var labelTextColors = []; + tooltipPosition = Chart.Tooltip.positioners[opts.position](active, me._eventPosition); + + var tooltipItems = []; + for (i = 0, len = active.length; i < len; ++i) { + tooltipItems.push(createTooltipItem(active[i])); + } + + // If the user provided a filter function, use it to modify the tooltip items + if (opts.filter) { + tooltipItems = tooltipItems.filter(function(a) { + return opts.filter(a, data); + }); + } + + // If the user provided a sorting function, use it to modify the tooltip items + if (opts.itemSort) { + tooltipItems = tooltipItems.sort(function(a, b) { + return opts.itemSort(a, b, data); + }); + } + + // Determine colors for boxes + helpers.each(tooltipItems, function(tooltipItem) { + labelColors.push(opts.callbacks.labelColor.call(me, tooltipItem, me._chart)); + labelTextColors.push(opts.callbacks.labelTextColor.call(me, tooltipItem, me._chart)); + }); + + + // Build the Text Lines + model.title = me.getTitle(tooltipItems, data); + model.beforeBody = me.getBeforeBody(tooltipItems, data); + model.body = me.getBody(tooltipItems, data); + model.afterBody = me.getAfterBody(tooltipItems, data); + model.footer = me.getFooter(tooltipItems, data); + + // Initial positioning and colors + model.x = Math.round(tooltipPosition.x); + model.y = Math.round(tooltipPosition.y); + model.caretPadding = opts.caretPadding; + model.labelColors = labelColors; + model.labelTextColors = labelTextColors; + + // data points + model.dataPoints = tooltipItems; + + // We need to determine alignment of the tooltip + tooltipSize = getTooltipSize(this, model); + alignment = determineAlignment(this, tooltipSize); + // Final Size and Position + backgroundPoint = getBackgroundPoint(model, tooltipSize, alignment); + } else { + model.opacity = 0; } - return elem.selected === true; + model.xAlign = alignment.xAlign; + model.yAlign = alignment.yAlign; + model.x = backgroundPoint.x; + model.y = backgroundPoint.y; + model.width = tooltipSize.width; + model.height = tooltipSize.height; + + // Point where the caret on the tooltip points to + model.caretX = tooltipPosition.x; + model.caretY = tooltipPosition.y; + + me._model = model; + + if (changed && opts.custom) { + opts.custom.call(me, model); + } + + return me; }, + drawCaret: function(tooltipPoint, size) { + var ctx = this._chart.ctx; + var vm = this._view; + var caretPosition = this.getCaretPosition(tooltipPoint, size, vm); + + ctx.lineTo(caretPosition.x1, caretPosition.y1); + ctx.lineTo(caretPosition.x2, caretPosition.y2); + ctx.lineTo(caretPosition.x3, caretPosition.y3); + }, + getCaretPosition: function(tooltipPoint, size, vm) { + var x1, x2, x3, y1, y2, y3; + var caretSize = vm.caretSize; + var cornerRadius = vm.cornerRadius; + var xAlign = vm.xAlign; + var yAlign = vm.yAlign; + var ptX = tooltipPoint.x; + var ptY = tooltipPoint.y; + var width = size.width; + var height = size.height; + + if (yAlign === 'center') { + y2 = ptY + (height / 2); + + if (xAlign === 'left') { + x1 = ptX; + x2 = x1 - caretSize; + x3 = x1; + + y1 = y2 + caretSize; + y3 = y2 - caretSize; + } else { + x1 = ptX + width; + x2 = x1 + caretSize; + x3 = x1; - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; + y1 = y2 - caretSize; + y3 = y2 + caretSize; + } + } else { + if (xAlign === 'left') { + x2 = ptX + cornerRadius + (caretSize); + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } else if (xAlign === 'right') { + x2 = ptX + width - cornerRadius - caretSize; + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } else { + x2 = ptX + (width / 2); + x1 = x2 - caretSize; + x3 = x2 + caretSize; + } + if (yAlign === 'top') { + y1 = ptY; + y2 = y1 - caretSize; + y3 = y1; + } else { + y1 = ptY + height; + y2 = y1 + caretSize; + y3 = y1; + // invert drawing order + var tmp = x3; + x3 = x1; + x1 = tmp; } } - return true; + return {x1: x1, x2: x2, x3: x3, y1: y1, y2: y2, y3: y3}; }, + drawTitle: function(pt, vm, ctx, opacity) { + var title = vm.title; - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, + if (title.length) { + ctx.textAlign = vm._titleAlign; + ctx.textBaseline = 'top'; - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, + var titleFontSize = vm.titleFontSize; + var titleSpacing = vm.titleSpacing; - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, + ctx.fillStyle = mergeOpacity(vm.titleFontColor, opacity); + ctx.font = helpers.fontString(titleFontSize, vm._titleFontStyle, vm._titleFontFamily); - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; + var i, len; + for (i = 0, len = title.length; i < len; ++i) { + ctx.fillText(title[i], pt.x, pt.y); + pt.y += titleFontSize + titleSpacing; // Line Height and spacing + + if (i + 1 === title.length) { + pt.y += vm.titleMarginBottom - titleSpacing; // If Last, add margin, remove spacing + } + } + } }, + drawBody: function(pt, vm, ctx, opacity) { + var bodyFontSize = vm.bodyFontSize; + var bodySpacing = vm.bodySpacing; + var body = vm.body; + + ctx.textAlign = vm._bodyAlign; + ctx.textBaseline = 'top'; + ctx.font = helpers.fontString(bodyFontSize, vm._bodyFontStyle, vm._bodyFontFamily); + + // Before Body + var xLinePadding = 0; + var fillLineOfText = function(line) { + ctx.fillText(line, pt.x + xLinePadding, pt.y); + pt.y += bodyFontSize + bodySpacing; + }; - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && + // Before body lines + helpers.each(vm.beforeBody, fillLineOfText); + + var drawColorBoxes = vm.displayColors; + xLinePadding = drawColorBoxes ? (bodyFontSize + 2) : 0; + + // Draw body lines now + helpers.each(body, function(bodyItem, i) { + helpers.each(bodyItem.before, fillLineOfText); + + helpers.each(bodyItem.lines, function(line) { + // Draw Legend-like boxes if needed + if (drawColorBoxes) { + // Fill a white rect so that colours merge nicely if the opacity is < 1 + ctx.fillStyle = mergeOpacity(vm.legendColorBackground, opacity); + ctx.fillRect(pt.x, pt.y, bodyFontSize, bodyFontSize); + + // Border + ctx.lineWidth = 1; + ctx.strokeStyle = mergeOpacity(vm.labelColors[i].borderColor, opacity); + ctx.strokeRect(pt.x, pt.y, bodyFontSize, bodyFontSize); + + // Inner square + ctx.fillStyle = mergeOpacity(vm.labelColors[i].backgroundColor, opacity); + ctx.fillRect(pt.x + 1, pt.y + 1, bodyFontSize - 2, bodyFontSize - 2); + var textColor = mergeOpacity(vm.labelTextColors[i], opacity); + ctx.fillStyle = textColor; + } - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, + fillLineOfText(line); + }); - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), + helpers.each(bodyItem.after, fillLineOfText); + }); - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), + // Reset back to 0 for after body + xLinePadding = 0; - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), + // After body lines + helpers.each(vm.afterBody, fillLineOfText); + pt.y -= bodySpacing; // Remove last body spacing + }, + drawFooter: function(pt, vm, ctx, opacity) { + var footer = vm.footer; - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), + if (footer.length) { + pt.y += vm.footerMarginTop; - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), + ctx.textAlign = vm._footerAlign; + ctx.textBaseline = 'top'; - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); + ctx.fillStyle = mergeOpacity(vm.footerFontColor, opacity); + ctx.font = helpers.fontString(vm.footerFontSize, vm._footerFontStyle, vm._footerFontFamily); + + helpers.each(footer, function(line) { + ctx.fillText(line, pt.x, pt.y); + pt.y += vm.footerFontSize + vm.footerSpacing; + }); } - return matchIndexes; - }), + }, + drawBackground: function(pt, vm, ctx, tooltipSize, opacity) { + ctx.fillStyle = mergeOpacity(vm.backgroundColor, opacity); + ctx.strokeStyle = mergeOpacity(vm.borderColor, opacity); + ctx.lineWidth = vm.borderWidth; + var xAlign = vm.xAlign; + var yAlign = vm.yAlign; + var x = pt.x; + var y = pt.y; + var width = tooltipSize.width; + var height = tooltipSize.height; + var radius = vm.cornerRadius; - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); + ctx.beginPath(); + ctx.moveTo(x + radius, y); + if (yAlign === 'top') { + this.drawCaret(pt, tooltipSize); } - return matchIndexes; - }) - } -}; + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + if (yAlign === 'center' && xAlign === 'right') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + if (yAlign === 'bottom') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + if (yAlign === 'center' && xAlign === 'left') { + this.drawCaret(pt, tooltipSize); + } + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); -Expr.pseudos["nth"] = Expr.pseudos["eq"]; + ctx.fill(); -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} + if (vm.borderWidth > 0) { + ctx.stroke(); + } + }, + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); + if (vm.opacity === 0) { + return; + } -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; + var tooltipSize = { + width: vm.width, + height: vm.height + }; + var pt = { + x: vm.x, + y: vm.y + }; - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } + // IE11/Edge does not like very small opacities, so snap to 0 + var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity; - soFar = selector; - groups = []; - preFilters = Expr.preFilter; + // Truthy/falsey value for empty tooltip + var hasTooltipContent = vm.title.length || vm.beforeBody.length || vm.body.length || vm.afterBody.length || vm.footer.length; - while ( soFar ) { + if (this._options.enabled && hasTooltipContent) { + // Draw Background + this.drawBackground(pt, vm, ctx, tooltipSize, opacity); - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } + // Draw Title, Body, and Footer + pt.x += vm.xPadding; + pt.y += vm.yPadding; - matched = false; + // Titles + this.drawTitle(pt, vm, ctx, opacity); - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } + // Body + this.drawBody(pt, vm, ctx, opacity); - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); + // Footer + this.drawFooter(pt, vm, ctx, opacity); } - } + }, - if ( !matched ) { - break; - } - } + /** + * Handle an event + * @private + * @param {IEvent} event - The event to handle + * @returns {Boolean} true if the tooltip changed + */ + handleEvent: function(e) { + var me = this; + var options = me._options; + var changed = false; + + me._lastActive = me._lastActive || []; + + // Find Active Elements for tooltips + if (e.type === 'mouseout') { + me._active = []; + } else { + me._active = me._chart.getElementsAtEventForMode(e, options.mode, options); + } - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; + // Remember Last Actives + changed = !helpers.arrayEquals(me._active, me._lastActive); -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} + // If tooltip didn't change, do not handle the target event + if (!changed) { + return false; + } -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - skip = combinator.next, - key = skip || dir, - checkNonElements = base && key === "parentNode", - doneName = done++; + me._lastActive = me._active; - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } + if (options.enabled || options.custom) { + me._eventPosition = { + x: e.x, + y: e.y + }; + + var model = me._model; + me.update(true); + me.pivot(); + + // See if our tooltip position changed + changed |= (model.x !== me._model.x) || (model.y !== me._model.y); } - return false; - } : - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, - newCache = [ dirruns, doneName ]; + return changed; + } + }); - // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); + /** + * @namespace Chart.Tooltip.positioners + */ + Chart.Tooltip.positioners = { + /** + * Average mode places the tooltip at the average position of the elements shown + * @function Chart.Tooltip.positioners.average + * @param elements {ChartElement[]} the elements being displayed in the tooltip + * @returns {Point} tooltip position + */ + average: function(elements) { + if (!elements.length) { + return false; + } - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + var i, len; + var x = 0; + var y = 0; + var count = 0; - if ( skip && skip === elem.nodeName.toLowerCase() ) { - elem = elem[ dir ] || elem; - } else if ( (oldCache = uniqueCache[ key ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + for (i = 0, len = elements.length; i < len; ++i) { + var el = elements[i]; + if (el && el.hasValue()) { + var pos = el.tooltipPosition(); + x += pos.x; + y += pos.y; + ++count; + } + } - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; + return { + x: Math.round(x / count), + y: Math.round(y / count) + }; + }, - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } + /** + * Gets the tooltip position nearest of the item nearest to the event position + * @function Chart.Tooltip.positioners.nearest + * @param elements {Chart.Element[]} the tooltip elements + * @param eventPosition {Point} the position of the event in canvas coordinates + * @returns {Point} the tooltip position + */ + nearest: function(elements, eventPosition) { + var x = eventPosition.x; + var y = eventPosition.y; + var minDistance = Number.POSITIVE_INFINITY; + var i, len, nearestElement; + + for (i = 0, len = elements.length; i < len; ++i) { + var el = elements[i]; + if (el && el.hasValue()) { + var center = el.getCenterPoint(); + var d = helpers.distanceBetweenPoints(eventPosition, center); + + if (d < minDistance) { + minDistance = d; + nearestElement = el; } } } - return false; - }; -} -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } + if (nearestElement) { + var tp = nearestElement.tooltipPosition(); + x = tp.x; + y = tp.y; } - return true; - } : - matchers[0]; -} -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} + return { + x: x, + y: y + }; + } + }; +}; + })(); +}); -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; +require.register("chart.js/src/elements/element.arc.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); +var helpers = require('../helpers/index'); + +defaults._set('global', { + elements: { + arc: { + backgroundColor: defaults.global.defaultColor, + borderColor: '#fff', + borderWidth: 2 } } +}); - return newUnmatched; -} +module.exports = Element.extend({ + inLabelRange: function(mouseX) { + var vm = this._view; -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, + if (vm) { + return (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hoverRadius, 2)); + } + return false; + }, - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + inRange: function(chartX, chartY) { + var vm = this._view; - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, + if (vm) { + var pointRelativePosition = helpers.getAngleFromPoint(vm, {x: chartX, y: chartY}); + var angle = pointRelativePosition.angle; + var distance = pointRelativePosition.distance; - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + // Sanitise angle range + var startAngle = vm.startAngle; + var endAngle = vm.endAngle; + while (endAngle < startAngle) { + endAngle += 2.0 * Math.PI; + } + while (angle > endAngle) { + angle -= 2.0 * Math.PI; + } + while (angle < startAngle) { + angle += 2.0 * Math.PI; + } - // ...intermediate processing is necessary - [] : + // Check if within the range of the open/close angle + var betweenAngles = (angle >= startAngle && angle <= endAngle); + var withinRadius = (distance >= vm.innerRadius && distance <= vm.outerRadius); - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); + return (betweenAngles && withinRadius); } + return false; + }, - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); + getCenterPoint: function() { + var vm = this._view; + var halfAngle = (vm.startAngle + vm.endAngle) / 2; + var halfRadius = (vm.innerRadius + vm.outerRadius) / 2; + return { + x: vm.x + Math.cos(halfAngle) * halfRadius, + y: vm.y + Math.sin(halfAngle) * halfRadius + }; + }, - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } + getArea: function() { + var vm = this._view; + return Math.PI * ((vm.endAngle - vm.startAngle) / (2 * Math.PI)) * (Math.pow(vm.outerRadius, 2) - Math.pow(vm.innerRadius, 2)); + }, - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } + tooltipPosition: function() { + var vm = this._view; + var centreAngle = vm.startAngle + ((vm.endAngle - vm.startAngle) / 2); + var rangeFromCentre = (vm.outerRadius - vm.innerRadius) / 2 + vm.innerRadius; - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + return { + x: vm.x + (Math.cos(centreAngle) * rangeFromCentre), + y: vm.y + (Math.sin(centreAngle) * rangeFromCentre) + }; + }, - seed[temp] = !(results[temp] = elem); - } - } - } + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var sA = vm.startAngle; + var eA = vm.endAngle; - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} + ctx.beginPath(); -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, + ctx.arc(vm.x, vm.y, vm.outerRadius, sA, eA); + ctx.arc(vm.x, vm.y, vm.innerRadius, eA, sA, true); - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; + ctx.closePath(); + ctx.strokeStyle = vm.borderColor; + ctx.lineWidth = vm.borderWidth; - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + ctx.fillStyle = vm.backgroundColor; - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); + ctx.fill(); + ctx.lineJoin = 'bevel'; + + if (vm.borderWidth) { + ctx.stroke(); } } +}); + })(); +}); - return elementMatcher( matchers ); -} +require.register("chart.js/src/elements/element.line.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); +var helpers = require('../helpers/index'); + +var globalDefaults = defaults.global; + +defaults._set('global', { + elements: { + line: { + tension: 0.4, + backgroundColor: globalDefaults.defaultColor, + borderWidth: 3, + borderColor: globalDefaults.defaultColor, + borderCapStyle: 'butt', + borderDash: [], + borderDashOffset: 0.0, + borderJoinStyle: 'miter', + capBezierPoints: true, + fill: true, // do we fill in the area between the line and its base axis + } + } +}); -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; +module.exports = Element.extend({ + draw: function() { + var me = this; + var vm = me._view; + var ctx = me._chart.ctx; + var spanGaps = vm.spanGaps; + var points = me._children.slice(); // clone array + var globalOptionLineElements = globalDefaults.elements.line; + var lastDrawnIndex = -1; + var index, current, previous, currentVM; - if ( outermost ) { - outermostContext = context === document || context || outermost; - } + // If we are looping, adding the first point again + if (me._loop && points.length) { + points.push(points[0]); + } - // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - if ( !context && elem.ownerDocument !== document ) { - setDocument( elem ); - xml = !documentIsHTML; - } - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context || document, xml) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } + ctx.save(); - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } + // Stroke Line Options + ctx.lineCap = vm.borderCapStyle || globalOptionLineElements.borderCapStyle; - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } + // IE 9 and 10 do not support line dash + if (ctx.setLineDash) { + ctx.setLineDash(vm.borderDash || globalOptionLineElements.borderDash); + } - // `i` is now the count of elements visited above, and adding it to `matchedCount` - // makes the latter nonnegative. - matchedCount += i; + ctx.lineDashOffset = vm.borderDashOffset || globalOptionLineElements.borderDashOffset; + ctx.lineJoin = vm.borderJoinStyle || globalOptionLineElements.borderJoinStyle; + ctx.lineWidth = vm.borderWidth || globalOptionLineElements.borderWidth; + ctx.strokeStyle = vm.borderColor || globalDefaults.defaultColor; - // Apply set filters to unmatched elements - // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` - // equals `i`), unless we didn't visit _any_ elements in the above loop because we have - // no element matchers and no seed. - // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that - // case, which will result in a "00" `matchedCount` that differs from `i` but is also - // numerically zero. - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } + // Stroke Line + ctx.beginPath(); + lastDrawnIndex = -1; - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } + for (index = 0; index < points.length; ++index) { + current = points[index]; + previous = helpers.previousItem(points, index); + currentVM = current._view; - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); + // First point moves to it's starting position no matter what + if (index === 0) { + if (!currentVM.skip) { + ctx.moveTo(currentVM.x, currentVM.y); + lastDrawnIndex = index; } + } else { + previous = lastDrawnIndex === -1 ? previous : points[lastDrawnIndex]; - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); + if (!currentVM.skip) { + if ((lastDrawnIndex !== (index - 1) && !spanGaps) || lastDrawnIndex === -1) { + // There was a gap and this is the first point after the gap + ctx.moveTo(currentVM.x, currentVM.y); + } else { + // Line to next point + helpers.canvas.lineTo(ctx, previous._view, current._view); + } + lastDrawnIndex = index; } } + } - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } + ctx.stroke(); + ctx.restore(); + } +}); + })(); +}); - return unmatched; - }; +require.register("chart.js/src/elements/element.point.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); +var helpers = require('../helpers/index'); + +var defaultColor = defaults.global.defaultColor; + +defaults._set('global', { + elements: { + point: { + radius: 3, + pointStyle: 'circle', + backgroundColor: defaultColor, + borderColor: defaultColor, + borderWidth: 1, + // Hover + hitRadius: 1, + hoverRadius: 4, + hoverBorderWidth: 1 + } + } +}); - return bySet ? - markFunction( superMatcher ) : - superMatcher; +function xRange(mouseX) { + var vm = this._view; + return vm ? (Math.pow(mouseX - vm.x, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; } -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; +function yRange(mouseY) { + var vm = this._view; + return vm ? (Math.pow(mouseY - vm.y, 2) < Math.pow(vm.radius + vm.hitRadius, 2)) : false; +} - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } +module.exports = Element.extend({ + inRange: function(mouseX, mouseY) { + var vm = this._view; + return vm ? ((Math.pow(mouseX - vm.x, 2) + Math.pow(mouseY - vm.y, 2)) < Math.pow(vm.hitRadius + vm.radius, 2)) : false; + }, - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + inLabelRange: xRange, + inXRange: xRange, + inYRange: yRange, - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); + getCenterPoint: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; + }, - results = results || []; + getArea: function() { + return Math.PI * Math.pow(this._view.radius, 2); + }, - // Try to minimize operations if there is only one selector in the list and no seed - // (the latter of which guarantees us context) - if ( match.length === 1 ) { + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y, + padding: vm.radius + vm.borderWidth + }; + }, - // Reduce context if the leading compound selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + draw: function(chartArea) { + var vm = this._view; + var model = this._model; + var ctx = this._chart.ctx; + var pointStyle = vm.pointStyle; + var radius = vm.radius; + var x = vm.x; + var y = vm.y; + var color = helpers.color; + var errMargin = 1.01; // 1.01 is margin for Accumulated error. (Especially Edge, IE.) + var ratio = 0; + + if (vm.skip) { + return; + } - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; + ctx.strokeStyle = vm.borderColor || defaultColor; + ctx.lineWidth = helpers.valueOrDefault(vm.borderWidth, defaults.global.elements.point.borderWidth); + ctx.fillStyle = vm.backgroundColor || defaultColor; - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; + // Cliping for Points. + // going out from inner charArea? + if ((chartArea !== undefined) && ((model.x < chartArea.left) || (chartArea.right * errMargin < model.x) || (model.y < chartArea.top) || (chartArea.bottom * errMargin < model.y))) { + // Point fade out + if (model.x < chartArea.left) { + ratio = (x - model.x) / (chartArea.left - model.x); + } else if (chartArea.right * errMargin < model.x) { + ratio = (model.x - x) / (model.x - chartArea.right); + } else if (model.y < chartArea.top) { + ratio = (y - model.y) / (chartArea.top - model.y); + } else if (chartArea.bottom * errMargin < model.y) { + ratio = (model.y - y) / (model.y - chartArea.bottom); } - - selector = selector.slice( tokens.shift().value.length ); + ratio = Math.round(ratio * 100) / 100; + ctx.strokeStyle = color(ctx.strokeStyle).alpha(ratio).rgbString(); + ctx.fillStyle = color(ctx.fillStyle).alpha(ratio).rgbString(); } - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; + helpers.canvas.drawPoint(ctx, pointStyle, radius, x, y); + } +}); + })(); +}); - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { +require.register("chart.js/src/elements/element.rectangle.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); - break; - } - } +defaults._set('global', { + elements: { + rectangle: { + backgroundColor: defaults.global.defaultColor, + borderColor: defaults.global.defaultColor, + borderSkipped: 'bottom', + borderWidth: 0 } } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - !context || rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( el ) { - // Should return 1, but returns 4 (following) - return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; }); -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); +function isVertical(bar) { + return bar._view.width !== undefined; } -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); +/** + * Helper function to get the bounds of the bar regardless of the orientation + * @param bar {Chart.Element.Rectangle} the bar + * @return {Bounds} bounds of the bar + * @private + */ +function getBarBounds(bar) { + var vm = bar._view; + var x1, x2, y1, y2; + + if (isVertical(bar)) { + // vertical + var halfWidth = vm.width / 2; + x1 = vm.x - halfWidth; + x2 = vm.x + halfWidth; + y1 = Math.min(vm.y, vm.base); + y2 = Math.max(vm.y, vm.base); + } else { + // horizontal bar + var halfHeight = vm.height / 2; + x1 = Math.min(vm.x, vm.base); + x2 = Math.max(vm.x, vm.base); + y1 = vm.y - halfHeight; + y2 = vm.y + halfHeight; + } + + return { + left: x1, + top: y1, + right: x2, + bottom: y2 + }; } -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( el ) { - return el.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; +module.exports = Element.extend({ + draw: function() { + var ctx = this._chart.ctx; + var vm = this._view; + var left, right, top, bottom, signX, signY, borderSkipped; + var borderWidth = vm.borderWidth; + + if (!vm.horizontal) { + // bar + left = vm.x - vm.width / 2; + right = vm.x + vm.width / 2; + top = vm.y; + bottom = vm.base; + signX = 1; + signY = bottom > top ? 1 : -1; + borderSkipped = vm.borderSkipped || 'bottom'; + } else { + // horizontal bar + left = vm.base; + right = vm.x; + top = vm.y - vm.height / 2; + bottom = vm.y + vm.height / 2; + signX = right > left ? 1 : -1; + signY = 1; + borderSkipped = vm.borderSkipped || 'left'; + } + + // Canvas doesn't allow us to stroke inside the width so we can + // adjust the sizes to fit if we're setting a stroke on the line + if (borderWidth) { + // borderWidth shold be less than bar width and bar height. + var barSize = Math.min(Math.abs(left - right), Math.abs(top - bottom)); + borderWidth = borderWidth > barSize ? barSize : borderWidth; + var halfStroke = borderWidth / 2; + // Adjust borderWidth when bar top position is near vm.base(zero). + var borderLeft = left + (borderSkipped !== 'left' ? halfStroke * signX : 0); + var borderRight = right + (borderSkipped !== 'right' ? -halfStroke * signX : 0); + var borderTop = top + (borderSkipped !== 'top' ? halfStroke * signY : 0); + var borderBottom = bottom + (borderSkipped !== 'bottom' ? -halfStroke * signY : 0); + // not become a vertical line? + if (borderLeft !== borderRight) { + top = borderTop; + bottom = borderBottom; + } + // not become a horizontal line? + if (borderTop !== borderBottom) { + left = borderLeft; + right = borderRight; + } + } + + ctx.beginPath(); + ctx.fillStyle = vm.backgroundColor; + ctx.strokeStyle = vm.borderColor; + ctx.lineWidth = borderWidth; + + // Corner points, from bottom-left to bottom-right clockwise + // | 1 2 | + // | 0 3 | + var corners = [ + [left, bottom], + [left, top], + [right, top], + [right, bottom] + ]; + + // Find first (starting) corner with fallback to 'bottom' + var borders = ['bottom', 'left', 'top', 'right']; + var startCorner = borders.indexOf(borderSkipped, 0); + if (startCorner === -1) { + startCorner = 0; + } + + function cornerAt(index) { + return corners[(startCorner + index) % 4]; + } + + // Draw rectangle from 'startCorner' + var corner = cornerAt(0); + ctx.moveTo(corner[0], corner[1]); + + for (var i = 1; i < 4; i++) { + corner = cornerAt(i); + ctx.lineTo(corner[0], corner[1]); + } + + ctx.fill(); + if (borderWidth) { + ctx.stroke(); } - }); -} + }, -return Sizzle; + height: function() { + var vm = this._view; + return vm.base - vm.y; + }, -})( window ); + inRange: function(mouseX, mouseY) { + var inRange = false; + if (this._view) { + var bounds = getBarBounds(this); + inRange = mouseX >= bounds.left && mouseX <= bounds.right && mouseY >= bounds.top && mouseY <= bounds.bottom; + } + return inRange; + }, -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; + inLabelRange: function(mouseX, mouseY) { + var me = this; + if (!me._view) { + return false; + } -// Deprecated -jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; + var inRange = false; + var bounds = getBarBounds(me); + if (isVertical(me)) { + inRange = mouseX >= bounds.left && mouseX <= bounds.right; + } else { + inRange = mouseY >= bounds.top && mouseY <= bounds.bottom; + } + return inRange; + }, + inXRange: function(mouseX) { + var bounds = getBarBounds(this); + return mouseX >= bounds.left && mouseX <= bounds.right; + }, -var dir = function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; + inYRange: function(mouseY) { + var bounds = getBarBounds(this); + return mouseY >= bounds.top && mouseY <= bounds.bottom; + }, - while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); + getCenterPoint: function() { + var vm = this._view; + var x, y; + if (isVertical(this)) { + x = vm.x; + y = (vm.y + vm.base) / 2; + } else { + x = (vm.x + vm.base) / 2; + y = vm.y; } - } - return matched; -}; + return {x: x, y: y}; + }, -var siblings = function( n, elem ) { - var matched = []; + getArea: function() { + var vm = this._view; + return vm.width * Math.abs(vm.y - vm.base); + }, - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } + tooltipPosition: function() { + var vm = this._view; + return { + x: vm.x, + y: vm.y + }; } +}); + })(); +}); - return matched; -}; - - -var rneedsContext = jQuery.expr.match.needsContext; - - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); +require.register("chart.js/src/elements/index.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; -}; -var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); +module.exports = {}; +module.exports.Arc = require('./element.arc'); +module.exports.Line = require('./element.line'); +module.exports.Point = require('./element.point'); +module.exports.Rectangle = require('./element.rectangle'); + })(); +}); +require.register("chart.js/src/helpers/helpers.canvas.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; +var helpers = require('./helpers.core'); -var risSimple = /^.[^:#\[\.,]*$/; +/** + * @namespace Chart.helpers.canvas + */ +var exports = module.exports = { + /** + * Clears the entire canvas associated to the given `chart`. + * @param {Chart} chart - The chart for which to clear the canvas. + */ + clear: function(chart) { + chart.ctx.clearRect(0, 0, chart.width, chart.height); + }, -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - return !!qualifier.call( elem, i, elem ) !== not; - } ); - } + /** + * Creates a "path" for a rectangle with rounded corners at position (x, y) with a + * given size (width, height) and the same `radius` for all corners. + * @param {CanvasRenderingContext2D} ctx - The canvas 2D Context. + * @param {Number} x - The x axis of the coordinate for the rectangle starting point. + * @param {Number} y - The y axis of the coordinate for the rectangle starting point. + * @param {Number} width - The rectangle's width. + * @param {Number} height - The rectangle's height. + * @param {Number} radius - The rounded amount (in pixels) for the four corners. + * @todo handle `radius` as top-left, top-right, bottom-right, bottom-left array/object? + */ + roundedRect: function(ctx, x, y, width, height, radius) { + if (radius) { + var rx = Math.min(radius, width / 2); + var ry = Math.min(radius, height / 2); + + ctx.moveTo(x + rx, y); + ctx.lineTo(x + width - rx, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + ry); + ctx.lineTo(x + width, y + height - ry); + ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height); + ctx.lineTo(x + rx, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - ry); + ctx.lineTo(x, y + ry); + ctx.quadraticCurveTo(x, y, x + rx, y); + } else { + ctx.rect(x, y, width, height); + } + }, - // Single element - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - } ); - } + drawPoint: function(ctx, style, radius, x, y) { + var type, edgeLength, xOffset, yOffset, height, size; - // Arraylike of elements (jQuery, arguments, Array) - if ( typeof qualifier !== "string" ) { - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not; - } ); - } + if (typeof style === 'object') { + type = style.toString(); + if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') { + ctx.drawImage(style, x - style.width / 2, y - style.height / 2, style.width, style.height); + return; + } + } - // Simple selector that can be filtered directly, removing non-Elements - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } + if (isNaN(radius) || radius <= 0) { + return; + } - // Complex selector, compare the two sets, removing non-Elements - qualifier = jQuery.filter( qualifier, elements ); - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1; - } ); -} + switch (style) { + // Default includes circle + default: + ctx.beginPath(); + ctx.arc(x, y, radius, 0, Math.PI * 2); + ctx.closePath(); + ctx.fill(); + break; + case 'triangle': + ctx.beginPath(); + edgeLength = 3 * radius / Math.sqrt(3); + height = edgeLength * Math.sqrt(3) / 2; + ctx.moveTo(x - edgeLength / 2, y + height / 3); + ctx.lineTo(x + edgeLength / 2, y + height / 3); + ctx.lineTo(x, y - 2 * height / 3); + ctx.closePath(); + ctx.fill(); + break; + case 'rect': + size = 1 / Math.SQRT2 * radius; + ctx.beginPath(); + ctx.fillRect(x - size, y - size, 2 * size, 2 * size); + ctx.strokeRect(x - size, y - size, 2 * size, 2 * size); + break; + case 'rectRounded': + var offset = radius / Math.SQRT2; + var leftX = x - offset; + var topY = y - offset; + var sideSize = Math.SQRT2 * radius; + ctx.beginPath(); + this.roundedRect(ctx, leftX, topY, sideSize, sideSize, radius / 2); + ctx.closePath(); + ctx.fill(); + break; + case 'rectRot': + size = 1 / Math.SQRT2 * radius; + ctx.beginPath(); + ctx.moveTo(x - size, y); + ctx.lineTo(x, y + size); + ctx.lineTo(x + size, y); + ctx.lineTo(x, y - size); + ctx.closePath(); + ctx.fill(); + break; + case 'cross': + ctx.beginPath(); + ctx.moveTo(x, y + radius); + ctx.lineTo(x, y - radius); + ctx.moveTo(x - radius, y); + ctx.lineTo(x + radius, y); + ctx.closePath(); + break; + case 'crossRot': + ctx.beginPath(); + xOffset = Math.cos(Math.PI / 4) * radius; + yOffset = Math.sin(Math.PI / 4) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x - xOffset, y + yOffset); + ctx.lineTo(x + xOffset, y - yOffset); + ctx.closePath(); + break; + case 'star': + ctx.beginPath(); + ctx.moveTo(x, y + radius); + ctx.lineTo(x, y - radius); + ctx.moveTo(x - radius, y); + ctx.lineTo(x + radius, y); + xOffset = Math.cos(Math.PI / 4) * radius; + yOffset = Math.sin(Math.PI / 4) * radius; + ctx.moveTo(x - xOffset, y - yOffset); + ctx.lineTo(x + xOffset, y + yOffset); + ctx.moveTo(x - xOffset, y + yOffset); + ctx.lineTo(x + xOffset, y - yOffset); + ctx.closePath(); + break; + case 'line': + ctx.beginPath(); + ctx.moveTo(x - radius, y); + ctx.lineTo(x + radius, y); + ctx.closePath(); + break; + case 'dash': + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(x + radius, y); + ctx.closePath(); + break; + } -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; + ctx.stroke(); + }, - if ( not ) { - expr = ":not(" + expr + ")"; - } + clipArea: function(ctx, area) { + ctx.save(); + ctx.beginPath(); + ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top); + ctx.clip(); + }, - if ( elems.length === 1 && elem.nodeType === 1 ) { - return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; - } + unclipArea: function(ctx) { + ctx.restore(); + }, - return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - } ) ); + lineTo: function(ctx, previous, target, flip) { + if (target.steppedLine) { + if ((target.steppedLine === 'after' && !flip) || (target.steppedLine !== 'after' && flip)) { + ctx.lineTo(previous.x, target.y); + } else { + ctx.lineTo(target.x, previous.y); + } + ctx.lineTo(target.x, target.y); + return; + } + + if (!target.tension) { + ctx.lineTo(target.x, target.y); + return; + } + + ctx.bezierCurveTo( + flip ? previous.controlPointPreviousX : previous.controlPointNextX, + flip ? previous.controlPointPreviousY : previous.controlPointNextY, + flip ? target.controlPointNextX : target.controlPointPreviousX, + flip ? target.controlPointNextY : target.controlPointPreviousY, + target.x, + target.y); + } }; -jQuery.fn.extend( { - find: function( selector ) { - var i, ret, - len = this.length, - self = this; +// DEPRECATIONS - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter( function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - } ) ); - } +/** + * Provided for backward compatibility, use Chart.helpers.canvas.clear instead. + * @namespace Chart.helpers.clear + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.clear = exports.clear; - ret = this.pushStack( [] ); +/** + * Provided for backward compatibility, use Chart.helpers.canvas.roundedRect instead. + * @namespace Chart.helpers.drawRoundedRectangle + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.drawRoundedRectangle = function(ctx) { + ctx.beginPath(); + exports.roundedRect.apply(exports, arguments); + ctx.closePath(); +}; + })(); +}); - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } +require.register("chart.js/src/helpers/helpers.core.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - return len > 1 ? jQuery.uniqueSort( ret ) : ret; - }, - filter: function( selector ) { - return this.pushStack( winnow( this, selector || [], false ) ); - }, - not: function( selector ) { - return this.pushStack( winnow( this, selector || [], true ) ); - }, - is: function( selector ) { - return !!winnow( - this, +/** + * @namespace Chart.helpers + */ +var helpers = { + /** + * An empty function that can be used, for example, for optional callback. + */ + noop: function() {}, - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -} ); + /** + * Returns a unique id, sequentially generated from a global variable. + * @returns {Number} + * @function + */ + uid: (function() { + var id = 0; + return function() { + return id++; + }; + }()), + /** + * Returns true if `value` is neither null nor undefined, else returns false. + * @param {*} value - The value to test. + * @returns {Boolean} + * @since 2.7.0 + */ + isNullOrUndef: function(value) { + return value === null || typeof value === 'undefined'; + }, -// Initialize a jQuery object + /** + * Returns true if `value` is an array, else returns false. + * @param {*} value - The value to test. + * @returns {Boolean} + * @function + */ + isArray: Array.isArray ? Array.isArray : function(value) { + return Object.prototype.toString.call(value) === '[object Array]'; + }, + /** + * Returns true if `value` is an object (excluding null), else returns false. + * @param {*} value - The value to test. + * @returns {Boolean} + * @since 2.7.0 + */ + isObject: function(value) { + return value !== null && Object.prototype.toString.call(value) === '[object Object]'; + }, -// A central reference to the root jQuery(document) -var rootjQuery, + /** + * Returns `value` if defined, else returns `defaultValue`. + * @param {*} value - The value to return if defined. + * @param {*} defaultValue - The value to return if `value` is undefined. + * @returns {*} + */ + valueOrDefault: function(value, defaultValue) { + return typeof value === 'undefined' ? defaultValue : value; + }, - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - // Shortcut simple #id case for speed - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + /** + * Returns value at the given `index` in array if defined, else returns `defaultValue`. + * @param {Array} value - The array to lookup for value at `index`. + * @param {Number} index - The index in `value` to lookup for value. + * @param {*} defaultValue - The value to return if `value[index]` is undefined. + * @returns {*} + */ + valueAtIndexOrDefault: function(value, index, defaultValue) { + return helpers.valueOrDefault(helpers.isArray(value) ? value[index] : value, defaultValue); + }, - init = jQuery.fn.init = function( selector, context, root ) { - var match, elem; + /** + * Calls `fn` with the given `args` in the scope defined by `thisArg` and returns the + * value returned by `fn`. If `fn` is not a function, this method returns undefined. + * @param {Function} fn - The function to call. + * @param {Array|undefined|null} args - The arguments with which `fn` should be called. + * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`. + * @returns {*} + */ + callback: function(fn, args, thisArg) { + if (fn && typeof fn.call === 'function') { + return fn.apply(thisArg, args); + } + }, - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; + /** + * Note(SB) for performance sake, this method should only be used when loopable type + * is unknown or in none intensive code (not called often and small loopable). Else + * it's preferable to use a regular for() loop and save extra function calls. + * @param {Object|Array} loopable - The object or array to be iterated. + * @param {Function} fn - The function to call for each item. + * @param {Object} [thisArg] - The value of `this` provided for the call to `fn`. + * @param {Boolean} [reverse] - If true, iterates backward on the loopable. + */ + each: function(loopable, fn, thisArg, reverse) { + var i, len, keys; + if (helpers.isArray(loopable)) { + len = loopable.length; + if (reverse) { + for (i = len - 1; i >= 0; i--) { + fn.call(thisArg, loopable[i], i); + } + } else { + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[i], i); + } + } + } else if (helpers.isObject(loopable)) { + keys = Object.keys(loopable); + len = keys.length; + for (i = 0; i < len; i++) { + fn.call(thisArg, loopable[keys[i]], keys[i]); + } } + }, - // Method init() accepts an alternate rootjQuery - // so migrate can support jQuery.sub (gh-2101) - root = root || rootjQuery; + /** + * Returns true if the `a0` and `a1` arrays have the same content, else returns false. + * @see http://stackoverflow.com/a/14853974 + * @param {Array} a0 - The array to compare + * @param {Array} a1 - The array to compare + * @returns {Boolean} + */ + arrayEquals: function(a0, a1) { + var i, ilen, v0, v1; - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[ 0 ] === "<" && - selector[ selector.length - 1 ] === ">" && - selector.length >= 3 ) { + if (!a0 || !a1 || a0.length !== a1.length) { + return false; + } - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; + for (i = 0, ilen = a0.length; i < ilen; ++i) { + v0 = a0[i]; + v1 = a1[i]; - } else { - match = rquickExpr.exec( selector ); + if (v0 instanceof Array && v1 instanceof Array) { + if (!helpers.arrayEquals(v0, v1)) { + return false; + } + } else if (v0 !== v1) { + // NOTE: two different object instances will never be equal: {x:20} != {x:20} + return false; } + } - // Match html or make sure no context is specified for #id - if ( match && ( match[ 1 ] || !context ) ) { + return true; + }, - // HANDLE: $(html) -> $(array) - if ( match[ 1 ] ) { - context = context instanceof jQuery ? context[ 0 ] : context; + /** + * Returns a deep copy of `source` without keeping references on objects and arrays. + * @param {*} source - The value to clone. + * @returns {*} + */ + clone: function(source) { + if (helpers.isArray(source)) { + return source.map(helpers.clone); + } - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[ 1 ], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); + if (helpers.isObject(source)) { + var target = {}; + var keys = Object.keys(source); + var klen = keys.length; + var k = 0; - // HANDLE: $(html, props) - if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { + for (; k < klen; ++k) { + target[keys[k]] = helpers.clone(source[keys[k]]); + } - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); + return target; + } - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } + return source; + }, - return this; + /** + * The default merger when Chart.helpers.merge is called without merger option. + * Note(SB): this method is also used by configMerge and scaleMerge as fallback. + * @private + */ + _merger: function(key, target, source, options) { + var tval = target[key]; + var sval = source[key]; - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[ 2 ] ); + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.merge(tval, sval, options); + } else { + target[key] = helpers.clone(sval); + } + }, - if ( elem ) { + /** + * Merges source[key] in target[key] only if target[key] is undefined. + * @private + */ + _mergerIf: function(key, target, source) { + var tval = target[key]; + var sval = source[key]; - // Inject the element directly into the jQuery object - this[ 0 ] = elem; - this.length = 1; - } - return this; - } + if (helpers.isObject(tval) && helpers.isObject(sval)) { + helpers.mergeIf(tval, sval); + } else if (!target.hasOwnProperty(key)) { + target[key] = helpers.clone(sval); + } + }, - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || root ).find( selector ); + /** + * Recursively deep copies `source` properties into `target` with the given `options`. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {Object} target - The target object in which all sources are merged into. + * @param {Object|Array(Object)} source - Object(s) to merge into `target`. + * @param {Object} [options] - Merging options: + * @param {Function} [options.merger] - The merge method (key, target, source, options) + * @returns {Object} The `target` object. + */ + merge: function(target, source, options) { + var sources = helpers.isArray(source) ? source : [source]; + var ilen = sources.length; + var merge, i, keys, klen, k; - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } + if (!helpers.isObject(target)) { + return target; + } - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this[ 0 ] = selector; - this.length = 1; - return this; + options = options || {}; + merge = options.merger || helpers._merger; - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return root.ready !== undefined ? - root.ready( selector ) : + for (i = 0; i < ilen; ++i) { + source = sources[i]; + if (!helpers.isObject(source)) { + continue; + } - // Execute immediately if ready is not present - selector( jQuery ); + keys = Object.keys(source); + for (k = 0, klen = keys.length; k < klen; ++k) { + merge(keys[k], target, source, options); + } } - return jQuery.makeArray( selector, this ); - }; + return target; + }, -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; + /** + * Recursively deep copies `source` properties into `target` *only* if not defined in target. + * IMPORTANT: `target` is not cloned and will be updated with `source` properties. + * @param {Object} target - The target object in which all sources are merged into. + * @param {Object|Array(Object)} source - Object(s) to merge into `target`. + * @returns {Object} The `target` object. + */ + mergeIf: function(target, source) { + return helpers.merge(target, source, {merger: helpers._mergerIf}); + } +}; -// Initialize central reference -rootjQuery = jQuery( document ); +module.exports = helpers; +// DEPRECATIONS -var rparentsprev = /^(?:parents|prev(?:Until|All))/, +/** + * Provided for backward compatibility, use Chart.helpers.callback instead. + * @function Chart.helpers.callCallback + * @deprecated since version 2.6.0 + * @todo remove at version 3 + * @private + */ +helpers.callCallback = helpers.callback; - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; +/** + * Provided for backward compatibility, use Array.prototype.indexOf instead. + * Array.prototype.indexOf compatibility: Chrome, Opera, Safari, FF1.5+, IE9+ + * @function Chart.helpers.indexOf + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.indexOf = function(array, item, fromIndex) { + return Array.prototype.indexOf.call(array, item, fromIndex); +}; -jQuery.fn.extend( { - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; +/** + * Provided for backward compatibility, use Chart.helpers.valueOrDefault instead. + * @function Chart.helpers.getValueOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueOrDefault = helpers.valueOrDefault; - return this.filter( function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[ i ] ) ) { - return true; - } - } - } ); +/** + * Provided for backward compatibility, use Chart.helpers.valueAtIndexOrDefault instead. + * @function Chart.helpers.getValueAtIndexOrDefault + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.getValueAtIndexOrDefault = helpers.valueAtIndexOrDefault; + })(); +}); + +require.register("chart.js/src/helpers/helpers.easing.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var helpers = require('./helpers.core'); + +/** + * Easing functions adapted from Robert Penner's easing equations. + * @namespace Chart.helpers.easingEffects + * @see http://www.robertpenner.com/easing/ + */ +var effects = { + linear: function(t) { + return t; }, - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - targets = typeof selectors !== "string" && jQuery( selectors ); + easeInQuad: function(t) { + return t * t; + }, - // Positional selectors never match, since there's no _selection_ context - if ( !rneedsContext.test( selectors ) ) { - for ( ; i < l; i++ ) { - for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + easeOutQuad: function(t) { + return -t * (t - 2); + }, - // Always skip document fragments - if ( cur.nodeType < 11 && ( targets ? - targets.index( cur ) > -1 : + easeInOutQuad: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t; + } + return -0.5 * ((--t) * (t - 2) - 1); + }, - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector( cur, selectors ) ) ) { + easeInCubic: function(t) { + return t * t * t; + }, - matched.push( cur ); - break; - } - } - } + easeOutCubic: function(t) { + return (t = t - 1) * t * t + 1; + }, + + easeInOutCubic: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t; } + return 0.5 * ((t -= 2) * t * t + 2); + }, - return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + easeInQuart: function(t) { + return t * t * t * t; }, - // Determine the position of an element within the set - index: function( elem ) { + easeOutQuart: function(t) { + return -((t = t - 1) * t * t * t - 1); + }, - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + easeInOutQuart: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t; } + return -0.5 * ((t -= 2) * t * t * t - 2); + }, - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); + easeInQuint: function(t) { + return t * t * t * t * t; + }, + + easeOutQuint: function(t) { + return (t = t - 1) * t * t * t * t + 1; + }, + + easeInOutQuint: function(t) { + if ((t /= 0.5) < 1) { + return 0.5 * t * t * t * t * t; } + return 0.5 * ((t -= 2) * t * t * t * t + 2); + }, - // Locate the position of the desired element - return indexOf.call( this, + easeInSine: function(t) { + return -Math.cos(t * (Math.PI / 2)) + 1; + }, - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); + easeOutSine: function(t) { + return Math.sin(t * (Math.PI / 2)); }, - add: function( selector, context ) { - return this.pushStack( - jQuery.uniqueSort( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); + easeInOutSine: function(t) { + return -0.5 * (Math.cos(Math.PI * t) - 1); }, - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter( selector ) - ); - } -} ); + easeInExpo: function(t) { + return (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)); + }, -function sibling( cur, dir ) { - while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} - return cur; -} + easeOutExpo: function(t) { + return (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1; + }, -jQuery.each( { - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; + easeInOutExpo: function(t) { + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if ((t /= 0.5) < 1) { + return 0.5 * Math.pow(2, 10 * (t - 1)); + } + return 0.5 * (-Math.pow(2, -10 * --t) + 2); }, - parents: function( elem ) { - return dir( elem, "parentNode" ); + + easeInCirc: function(t) { + if (t >= 1) { + return t; + } + return -(Math.sqrt(1 - t * t) - 1); }, - parentsUntil: function( elem, i, until ) { - return dir( elem, "parentNode", until ); + + easeOutCirc: function(t) { + return Math.sqrt(1 - (t = t - 1) * t); }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); + + easeInOutCirc: function(t) { + if ((t /= 0.5) < 1) { + return -0.5 * (Math.sqrt(1 - t * t) - 1); + } + return 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1); }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); + + easeInElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); }, - nextAll: function( elem ) { - return dir( elem, "nextSibling" ); + + easeOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if (t === 1) { + return 1; + } + if (!p) { + p = 0.3; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + return a * Math.pow(2, -10 * t) * Math.sin((t - s) * (2 * Math.PI) / p) + 1; }, - prevAll: function( elem ) { - return dir( elem, "previousSibling" ); + + easeInOutElastic: function(t) { + var s = 1.70158; + var p = 0; + var a = 1; + if (t === 0) { + return 0; + } + if ((t /= 0.5) === 2) { + return 1; + } + if (!p) { + p = 0.45; + } + if (a < 1) { + a = 1; + s = p / 4; + } else { + s = p / (2 * Math.PI) * Math.asin(1 / a); + } + if (t < 1) { + return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); + } + return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p) * 0.5 + 1; }, - nextUntil: function( elem, i, until ) { - return dir( elem, "nextSibling", until ); + easeInBack: function(t) { + var s = 1.70158; + return t * t * ((s + 1) * t - s); }, - prevUntil: function( elem, i, until ) { - return dir( elem, "previousSibling", until ); + + easeOutBack: function(t) { + var s = 1.70158; + return (t = t - 1) * t * ((s + 1) * t + s) + 1; }, - siblings: function( elem ) { - return siblings( ( elem.parentNode || {} ).firstChild, elem ); + + easeInOutBack: function(t) { + var s = 1.70158; + if ((t /= 0.5) < 1) { + return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s)); + } + return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2); }, - children: function( elem ) { - return siblings( elem.firstChild ); + + easeInBounce: function(t) { + return 1 - effects.easeOutBounce(1 - t); }, - contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } + easeOutBounce: function(t) { + if (t < (1 / 2.75)) { + return 7.5625 * t * t; + } + if (t < (2 / 2.75)) { + return 7.5625 * (t -= (1.5 / 2.75)) * t + 0.75; + } + if (t < (2.5 / 2.75)) { + return 7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375; + } + return 7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375; + }, - return jQuery.merge( [], elem.childNodes ); + easeInOutBounce: function(t) { + if (t < 0.5) { + return effects.easeInBounce(t * 2) * 0.5; + } + return effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5; } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); +}; - if ( name.slice( -5 ) !== "Until" ) { - selector = until; +module.exports = { + effects: effects +}; + +// DEPRECATIONS + +/** + * Provided for backward compatibility, use Chart.helpers.easing.effects instead. + * @function Chart.helpers.easingEffects + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.easingEffects = effects; + })(); +}); + +require.register("chart.js/src/helpers/helpers.options.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var helpers = require('./helpers.core'); + +/** + * @alias Chart.helpers.options + * @namespace + */ +module.exports = { + /** + * Converts the given line height `value` in pixels for a specific font `size`. + * @param {Number|String} value - The lineHeight to parse (eg. 1.6, '14px', '75%', '1.6em'). + * @param {Number} size - The font size (in pixels) used to resolve relative `value`. + * @returns {Number} The effective line height in pixels (size * 1.2 if value is invalid). + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/line-height + * @since 2.7.0 + */ + toLineHeight: function(value, size) { + var matches = ('' + value).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/); + if (!matches || matches[1] === 'normal') { + return size * 1.2; } - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); + value = +matches[2]; + + switch (matches[3]) { + case 'px': + return value; + case '%': + value /= 100; + break; + default: + break; } - if ( this.length > 1 ) { + return size * value; + }, - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.uniqueSort( matched ); - } + /** + * Converts the given value into a padding object with pre-computed width/height. + * @param {Number|Object} value - If a number, set the value to all TRBL component, + * else, if and object, use defined properties and sets undefined ones to 0. + * @returns {Object} The padding values (top, right, bottom, left, width, height) + * @since 2.7.0 + */ + toPadding: function(value) { + var t, r, b, l; + + if (helpers.isObject(value)) { + t = +value.top || 0; + r = +value.right || 0; + b = +value.bottom || 0; + l = +value.left || 0; + } else { + t = r = b = l = +value || 0; + } - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); + return { + top: t, + right: r, + bottom: b, + left: l, + height: t + b, + width: l + r + }; + }, + + /** + * Evaluates the given `inputs` sequentially and returns the first defined value. + * @param {Array[]} inputs - An array of values, falling back to the last value. + * @param {Object} [context] - If defined and the current value is a function, the value + * is called with `context` as first argument and the result becomes the new input. + * @param {Number} [index] - If defined and the current value is an array, the value + * at `index` become the new input. + * @since 2.7.0 + */ + resolve: function(inputs, context, index) { + var i, ilen, value; + + for (i = 0, ilen = inputs.length; i < ilen; ++i) { + value = inputs[i]; + if (value === undefined) { + continue; + } + if (context !== undefined && typeof value === 'function') { + value = value(context); + } + if (index !== undefined && helpers.isArray(value)) { + value = value[index]; + } + if (value !== undefined) { + return value; } } + } +}; + })(); +}); - return this.pushStack( matched ); - }; -} ); -var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); +require.register("chart.js/src/helpers/index.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; +module.exports = require('./helpers.core'); +module.exports.easing = require('./helpers.easing'); +module.exports.canvas = require('./helpers.canvas'); +module.exports.options = require('./helpers.options'); + })(); +}); +require.register("chart.js/src/platforms/platform.basic.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /** + * Platform fallback implementation (minimal). + * @see https://github.com/chartjs/Chart.js/pull/4591#issuecomment-319575939 + */ -// Convert String-formatted options into Object-formatted ones -function createOptions( options ) { - var object = {}; - jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { - object[ flag ] = true; - } ); - return object; -} +module.exports = { + acquireContext: function(item) { + if (item && item.canvas) { + // Support for any object associated to a canvas (including a context2d) + item = item.canvas; + } -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * + return item && item.getContext('2d') || null; + } +}; + })(); +}); + +require.register("chart.js/src/platforms/platform.dom.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /** + * Chart.Platform implementation for targeting a web browser */ -jQuery.Callbacks = function( options ) { - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - createOptions( options ) : - jQuery.extend( {}, options ); +'use strict'; - var // Flag to know if list is currently firing - firing, +var helpers = require('../helpers/index'); - // Last fire value for non-forgettable lists - memory, +var EXPANDO_KEY = '$chartjs'; +var CSS_PREFIX = 'chartjs-'; +var CSS_RENDER_MONITOR = CSS_PREFIX + 'render-monitor'; +var CSS_RENDER_ANIMATION = CSS_PREFIX + 'render-animation'; +var ANIMATION_START_EVENTS = ['animationstart', 'webkitAnimationStart']; - // Flag to know if list was already fired - fired, +/** + * DOM event types -> Chart.js event types. + * Note: only events with different types are mapped. + * @see https://developer.mozilla.org/en-US/docs/Web/Events + */ +var EVENT_TYPES = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup', + pointerenter: 'mouseenter', + pointerdown: 'mousedown', + pointermove: 'mousemove', + pointerup: 'mouseup', + pointerleave: 'mouseout', + pointerout: 'mouseout' +}; - // Flag to prevent firing - locked, +/** + * The "used" size is the final value of a dimension property after all calculations have + * been performed. This method uses the computed style of `element` but returns undefined + * if the computed style is not expressed in pixels. That can happen in some cases where + * `element` has a size relative to its parent and this last one is not yet displayed, + * for example because of `display: none` on a parent node. + * @see https://developer.mozilla.org/en-US/docs/Web/CSS/used_value + * @returns {Number} Size in pixels or undefined if unknown. + */ +function readUsedSize(element, property) { + var value = helpers.getStyle(element, property); + var matches = value && value.match(/^(\d+)(\.\d+)?px$/); + return matches ? Number(matches[1]) : undefined; +} - // Actual callback list - list = [], +/** + * Initializes the canvas style and render size without modifying the canvas display size, + * since responsiveness is handled by the controller.resize() method. The config is used + * to determine the aspect ratio to apply in case no explicit height has been specified. + */ +function initCanvas(canvas, config) { + var style = canvas.style; - // Queue of execution data for repeatable lists - queue = [], + // NOTE(SB) canvas.getAttribute('width') !== canvas.width: in the first case it + // returns null or '' if no explicit value has been set to the canvas attribute. + var renderHeight = canvas.getAttribute('height'); + var renderWidth = canvas.getAttribute('width'); - // Index of currently firing callback (modified by add/remove as needed) - firingIndex = -1, + // Chart.js modifies some canvas values that we want to restore on destroy + canvas[EXPANDO_KEY] = { + initial: { + height: renderHeight, + width: renderWidth, + style: { + display: style.display, + height: style.height, + width: style.width + } + } + }; - // Fire callbacks - fire = function() { + // Force canvas to display as block to avoid extra space caused by inline + // elements, which would interfere with the responsive resize process. + // https://github.com/chartjs/Chart.js/issues/2538 + style.display = style.display || 'block'; - // Enforce single-firing - locked = locked || options.once; + if (renderWidth === null || renderWidth === '') { + var displayWidth = readUsedSize(canvas, 'width'); + if (displayWidth !== undefined) { + canvas.width = displayWidth; + } + } - // Execute callbacks for all pending executions, - // respecting firingIndex overrides and runtime changes - fired = firing = true; - for ( ; queue.length; firingIndex = -1 ) { - memory = queue.shift(); - while ( ++firingIndex < list.length ) { + if (renderHeight === null || renderHeight === '') { + if (canvas.style.height === '') { + // If no explicit render height and style height, let's apply the aspect ratio, + // which one can be specified by the user but also by charts as default option + // (i.e. options.aspectRatio). If not specified, use canvas aspect ratio of 2. + canvas.height = canvas.width / (config.options.aspectRatio || 2); + } else { + var displayHeight = readUsedSize(canvas, 'height'); + if (displayWidth !== undefined) { + canvas.height = displayHeight; + } + } + } - // Run callback and check for early termination - if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && - options.stopOnFalse ) { + return canvas; +} - // Jump to end and forget the data so .add doesn't re-fire - firingIndex = list.length; - memory = false; - } - } +/** + * Detects support for options object argument in addEventListener. + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Safely_detecting_option_support + * @private + */ +var supportsEventListenerOptions = (function() { + var supports = false; + try { + var options = Object.defineProperty({}, 'passive', { + get: function() { + supports = true; } + }); + window.addEventListener('e', null, options); + } catch (e) { + // continue regardless of error + } + return supports; +}()); - // Forget the data if we're done with it - if ( !options.memory ) { - memory = false; - } +// Default passive to true as expected by Chrome for 'touchstart' and 'touchend' events. +// https://github.com/chartjs/Chart.js/issues/4287 +var eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false; - firing = false; +function addEventListener(node, type, listener) { + node.addEventListener(type, listener, eventListenerOptions); +} - // Clean up if we're done firing for good - if ( locked ) { +function removeEventListener(node, type, listener) { + node.removeEventListener(type, listener, eventListenerOptions); +} - // Keep an empty list if we have data for future add calls - if ( memory ) { - list = []; +function createEvent(type, chart, x, y, nativeEvent) { + return { + type: type, + chart: chart, + native: nativeEvent || null, + x: x !== undefined ? x : null, + y: y !== undefined ? y : null, + }; +} - // Otherwise, this object is spent - } else { - list = ""; - } - } - }, +function fromNativeEvent(event, chart) { + var type = EVENT_TYPES[event.type] || event.type; + var pos = helpers.getRelativePosition(event, chart); + return createEvent(type, chart, pos.x, pos.y, event); +} - // Actual Callbacks object - self = { +function throttled(fn, thisArg) { + var ticking = false; + var args = []; - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { + return function() { + args = Array.prototype.slice.call(arguments); + thisArg = thisArg || this; - // If we have memory from a past run, we should fire after adding - if ( memory && !firing ) { - firingIndex = list.length - 1; - queue.push( memory ); - } + if (!ticking) { + ticking = true; + helpers.requestAnimFrame.call(window, function() { + ticking = false; + fn.apply(thisArg, args); + }); + } + }; +} - ( function add( args ) { - jQuery.each( args, function( _, arg ) { - if ( jQuery.isFunction( arg ) ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { +// Implementation based on https://github.com/marcj/css-element-queries +function createResizer(handler) { + var resizer = document.createElement('div'); + var cls = CSS_PREFIX + 'size-monitor'; + var maxSize = 1000000; + var style = + 'position:absolute;' + + 'left:0;' + + 'top:0;' + + 'right:0;' + + 'bottom:0;' + + 'overflow:hidden;' + + 'pointer-events:none;' + + 'visibility:hidden;' + + 'z-index:-1;'; + + resizer.style.cssText = style; + resizer.className = cls; + resizer.innerHTML = + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
'; + + var expand = resizer.childNodes[0]; + var shrink = resizer.childNodes[1]; + + resizer._reset = function() { + expand.scrollLeft = maxSize; + expand.scrollTop = maxSize; + shrink.scrollLeft = maxSize; + shrink.scrollTop = maxSize; + }; + var onScroll = function() { + resizer._reset(); + handler(); + }; - // Inspect recursively - add( arg ); - } - } ); - } )( arguments ); + addEventListener(expand, 'scroll', onScroll.bind(expand, 'expand')); + addEventListener(shrink, 'scroll', onScroll.bind(shrink, 'shrink')); - if ( memory && !firing ) { - fire(); - } - } - return this; - }, + return resizer; +} - // Remove a callback from the list - remove: function() { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); +// https://davidwalsh.name/detect-node-insertion +function watchForRender(node, handler) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); + var proxy = expando.renderProxy = function(e) { + if (e.animationName === CSS_RENDER_ANIMATION) { + handler(); + } + }; - // Handle firing indexes - if ( index <= firingIndex ) { - firingIndex--; - } - } - } ); - return this; - }, + helpers.each(ANIMATION_START_EVENTS, function(type) { + addEventListener(node, type, proxy); + }); - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? - jQuery.inArray( fn, list ) > -1 : - list.length > 0; - }, + node.classList.add(CSS_RENDER_MONITOR); +} - // Remove all callbacks from the list - empty: function() { - if ( list ) { - list = []; - } - return this; - }, +function unwatchForRender(node) { + var expando = node[EXPANDO_KEY] || {}; + var proxy = expando.renderProxy; - // Disable .fire and .add - // Abort any current/pending executions - // Clear all callbacks and values - disable: function() { - locked = queue = []; - list = memory = ""; - return this; - }, - disabled: function() { - return !list; - }, + if (proxy) { + helpers.each(ANIMATION_START_EVENTS, function(type) { + removeEventListener(node, type, proxy); + }); - // Disable .fire - // Also disable .add unless we have memory (since it would have no effect) - // Abort any pending executions - lock: function() { - locked = queue = []; - if ( !memory && !firing ) { - list = memory = ""; - } - return this; - }, - locked: function() { - return !!locked; - }, + delete expando.renderProxy; + } - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( !locked ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - queue.push( args ); - if ( !firing ) { - fire(); - } - } - return this; - }, + node.classList.remove(CSS_RENDER_MONITOR); +} - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, +function addResizeListener(node, listener, chart) { + var expando = node[EXPANDO_KEY] || (node[EXPANDO_KEY] = {}); - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; + // Let's keep track of this added resizer and thus avoid DOM query when removing it. + var resizer = expando.resizer = createResizer(throttled(function() { + if (expando.resizer) { + return listener(createEvent('resize', chart)); + } + })); + + // The resizer needs to be attached to the node parent, so we first need to be + // sure that `node` is attached to the DOM before injecting the resizer element. + watchForRender(node, function() { + if (expando.resizer) { + var container = node.parentNode; + if (container && container !== resizer.parentNode) { + container.insertBefore(resizer, container.firstChild); } - }; - return self; -}; + // The container size might have changed, let's reset the resizer state. + resizer._reset(); + } + }); +} +function removeResizeListener(node) { + var expando = node[EXPANDO_KEY] || {}; + var resizer = expando.resizer; -function Identity( v ) { - return v; + delete expando.resizer; + unwatchForRender(node); + + if (resizer && resizer.parentNode) { + resizer.parentNode.removeChild(resizer); + } } -function Thrower( ex ) { - throw ex; + +function injectCSS(platform, css) { + // http://stackoverflow.com/q/3922139 + var style = platform._style || document.createElement('style'); + if (!platform._style) { + platform._style = style; + css = '/* Chart.js */\n' + css; + style.setAttribute('type', 'text/css'); + document.getElementsByTagName('head')[0].appendChild(style); + } + + style.appendChild(document.createTextNode(css)); } -function adoptValue( value, resolve, reject, noValue ) { - var method; +module.exports = { + /** + * This property holds whether this platform is enabled for the current environment. + * Currently used by platform.js to select the proper implementation. + * @private + */ + _enabled: typeof window !== 'undefined' && typeof document !== 'undefined', + + initialize: function() { + var keyframes = 'from{opacity:0.99}to{opacity:1}'; + + injectCSS(this, + // DOM rendering detection + // https://davidwalsh.name/detect-node-insertion + '@-webkit-keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' + + '@keyframes ' + CSS_RENDER_ANIMATION + '{' + keyframes + '}' + + '.' + CSS_RENDER_MONITOR + '{' + + '-webkit-animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' + + 'animation:' + CSS_RENDER_ANIMATION + ' 0.001s;' + + '}' + ); + }, - try { + acquireContext: function(item, config) { + if (typeof item === 'string') { + item = document.getElementById(item); + } else if (item.length) { + // Support for array based queries (such as jQuery) + item = item[0]; + } - // Check for promise aspect first to privilege synchronous behavior - if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { - method.call( value ).done( resolve ).fail( reject ); + if (item && item.canvas) { + // Support for any object associated to a canvas (including a context2d) + item = item.canvas; + } - // Other thenables - } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { - method.call( value, resolve, reject ); + // To prevent canvas fingerprinting, some add-ons undefine the getContext + // method, for example: https://github.com/kkapsner/CanvasBlocker + // https://github.com/chartjs/Chart.js/issues/2807 + var context = item && item.getContext && item.getContext('2d'); - // Other non-thenables - } else { + // `instanceof HTMLCanvasElement/CanvasRenderingContext2D` fails when the item is + // inside an iframe or when running in a protected environment. We could guess the + // types from their toString() value but let's keep things flexible and assume it's + // a sufficient condition if the item has a context2D which has item as `canvas`. + // https://github.com/chartjs/Chart.js/issues/3887 + // https://github.com/chartjs/Chart.js/issues/4102 + // https://github.com/chartjs/Chart.js/issues/4152 + if (context && context.canvas === item) { + initCanvas(item, config); + return context; + } - // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: - // * false: [ value ].slice( 0 ) => resolve( value ) - // * true: [ value ].slice( 1 ) => resolve() - resolve.apply( undefined, [ value ].slice( noValue ) ); + return null; + }, + + releaseContext: function(context) { + var canvas = context.canvas; + if (!canvas[EXPANDO_KEY]) { + return; } - // For Promises/A+, convert exceptions into rejections - // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in - // Deferred#then to conditionally suppress rejection. - } catch ( value ) { + var initial = canvas[EXPANDO_KEY].initial; + ['height', 'width'].forEach(function(prop) { + var value = initial[prop]; + if (helpers.isNullOrUndef(value)) { + canvas.removeAttribute(prop); + } else { + canvas.setAttribute(prop, value); + } + }); - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); - } -} + helpers.each(initial.style || {}, function(value, key) { + canvas.style[key] = value; + }); -jQuery.extend( { + // The canvas render size might have been changed (and thus the state stack discarded), + // we can't use save() and restore() to restore the initial state. So make sure that at + // least the canvas context is reset to the default state by setting the canvas width. + // https://www.w3.org/TR/2011/WD-html5-20110525/the-canvas-element.html + canvas.width = canvas.width; - Deferred: function( func ) { - var tuples = [ + delete canvas[EXPANDO_KEY]; + }, - // action, add listener, callbacks, - // ... .then handlers, argument index, [final state] - [ "notify", "progress", jQuery.Callbacks( "memory" ), - jQuery.Callbacks( "memory" ), 2 ], - [ "resolve", "done", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 0, "resolved" ], - [ "reject", "fail", jQuery.Callbacks( "once memory" ), - jQuery.Callbacks( "once memory" ), 1, "rejected" ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - "catch": function( fn ) { - return promise.then( null, fn ); - }, + addEventListener: function(chart, type, listener) { + var canvas = chart.canvas; + if (type === 'resize') { + // Note: the resize event is not supported on all browsers. + addResizeListener(canvas, listener, chart); + return; + } - // Keep pipe for back-compat - pipe: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; + var expando = listener[EXPANDO_KEY] || (listener[EXPANDO_KEY] = {}); + var proxies = expando.proxies || (expando.proxies = {}); + var proxy = proxies[chart.id + '_' + type] = function(event) { + listener(fromNativeEvent(event, chart)); + }; - return jQuery.Deferred( function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { + addEventListener(canvas, type, proxy); + }, - // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + removeEventListener: function(chart, type, listener) { + var canvas = chart.canvas; + if (type === 'resize') { + // Note: the resize event is not supported on all browsers. + removeResizeListener(canvas, listener); + return; + } - // deferred.progress(function() { bind to newDefer or newDefer.notify }) - // deferred.done(function() { bind to newDefer or newDefer.resolve }) - // deferred.fail(function() { bind to newDefer or newDefer.reject }) - deferred[ tuple[ 1 ] ]( function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .progress( newDefer.notify ) - .done( newDefer.resolve ) - .fail( newDefer.reject ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( - this, - fn ? [ returned ] : arguments - ); - } - } ); - } ); - fns = null; - } ).promise(); - }, - then: function( onFulfilled, onRejected, onProgress ) { - var maxDepth = 0; - function resolve( depth, deferred, handler, special ) { - return function() { - var that = this, - args = arguments, - mightThrow = function() { - var returned, then; + var expando = listener[EXPANDO_KEY] || {}; + var proxies = expando.proxies || {}; + var proxy = proxies[chart.id + '_' + type]; + if (!proxy) { + return; + } - // Support: Promises/A+ section 2.3.3.3.3 - // https://promisesaplus.com/#point-59 - // Ignore double-resolution attempts - if ( depth < maxDepth ) { - return; - } + removeEventListener(canvas, type, proxy); + } +}; - returned = handler.apply( that, args ); +// DEPRECATIONS - // Support: Promises/A+ section 2.3.1 - // https://promisesaplus.com/#point-48 - if ( returned === deferred.promise() ) { - throw new TypeError( "Thenable self-resolution" ); - } +/** + * Provided for backward compatibility, use EventTarget.addEventListener instead. + * EventTarget.addEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ + * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener + * @function Chart.helpers.addEvent + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.addEvent = addEventListener; - // Support: Promises/A+ sections 2.3.3.1, 3.5 - // https://promisesaplus.com/#point-54 - // https://promisesaplus.com/#point-75 - // Retrieve `then` only once - then = returned && +/** + * Provided for backward compatibility, use EventTarget.removeEventListener instead. + * EventTarget.removeEventListener compatibility: Chrome, Opera 7, Safari, FF1.5+, IE9+ + * @see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener + * @function Chart.helpers.removeEvent + * @deprecated since version 2.7.0 + * @todo remove at version 3 + * @private + */ +helpers.removeEvent = removeEventListener; + })(); +}); - // Support: Promises/A+ section 2.3.4 - // https://promisesaplus.com/#point-64 - // Only check objects and functions for thenability - ( typeof returned === "object" || - typeof returned === "function" ) && - returned.then; +require.register("chart.js/src/platforms/platform.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Handle a returned thenable - if ( jQuery.isFunction( then ) ) { +var helpers = require('../helpers/index'); +var basic = require('./platform.basic'); +var dom = require('./platform.dom'); - // Special processors (notify) just wait for resolution - if ( special ) { - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ) - ); +// @TODO Make possible to select another platform at build time. +var implementation = dom._enabled ? dom : basic; - // Normal processors (resolve) also hook into progress - } else { +/** + * @namespace Chart.platform + * @see https://chartjs.gitbooks.io/proposals/content/Platform.html + * @since 2.4.0 + */ +module.exports = helpers.extend({ + /** + * @since 2.7.0 + */ + initialize: function() {}, + + /** + * Called at chart construction time, returns a context2d instance implementing + * the [W3C Canvas 2D Context API standard]{@link https://www.w3.org/TR/2dcontext/}. + * @param {*} item - The native item from which to acquire context (platform specific) + * @param {Object} options - The chart options + * @returns {CanvasRenderingContext2D} context2d instance + */ + acquireContext: function() {}, - // ...and disregard older resolution values - maxDepth++; + /** + * Called at chart destruction time, releases any resources associated to the context + * previously returned by the acquireContext() method. + * @param {CanvasRenderingContext2D} context - The context2d instance + * @returns {Boolean} true if the method succeeded, else false + */ + releaseContext: function() {}, + + /** + * Registers the specified listener on the given chart. + * @param {Chart} chart - Chart from which to listen for event + * @param {String} type - The ({@link IEvent}) type to listen for + * @param {Function} listener - Receives a notification (an object that implements + * the {@link IEvent} interface) when an event of the specified type occurs. + */ + addEventListener: function() {}, - then.call( - returned, - resolve( maxDepth, deferred, Identity, special ), - resolve( maxDepth, deferred, Thrower, special ), - resolve( maxDepth, deferred, Identity, - deferred.notifyWith ) - ); - } + /** + * Removes the specified listener previously registered with addEventListener. + * @param {Chart} chart -Chart from which to remove the listener + * @param {String} type - The ({@link IEvent}) type to remove + * @param {Function} listener - The listener function to remove from the event target. + */ + removeEventListener: function() {} - // Handle all other returned values - } else { +}, implementation); - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Identity ) { - that = undefined; - args = [ returned ]; - } +/** + * @interface IPlatform + * Allows abstracting platform dependencies away from the chart + * @borrows Chart.platform.acquireContext as acquireContext + * @borrows Chart.platform.releaseContext as releaseContext + * @borrows Chart.platform.addEventListener as addEventListener + * @borrows Chart.platform.removeEventListener as removeEventListener + */ - // Process the value(s) - // Default process is resolve - ( special || deferred.resolveWith )( that, args ); - } - }, +/** + * @interface IEvent + * @prop {String} type - The event type name, possible values are: + * 'contextmenu', 'mouseenter', 'mousedown', 'mousemove', 'mouseup', 'mouseout', + * 'click', 'dblclick', 'keydown', 'keypress', 'keyup' and 'resize' + * @prop {*} native - The original native event (null for emulated events, e.g. 'resize') + * @prop {Number} x - The mouse x position, relative to the canvas (null for incompatible events) + * @prop {Number} y - The mouse y position, relative to the canvas (null for incompatible events) + */ + })(); +}); - // Only normal processors (resolve) catch and reject exceptions - process = special ? - mightThrow : - function() { - try { - mightThrow(); - } catch ( e ) { +require.register("chart.js/src/plugins/plugin.filler.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /** + * Plugin based on discussion from the following Chart.js issues: + * @see https://github.com/chartjs/Chart.js/issues/2380#issuecomment-279961569 + * @see https://github.com/chartjs/Chart.js/issues/2440#issuecomment-256461897 + */ - if ( jQuery.Deferred.exceptionHook ) { - jQuery.Deferred.exceptionHook( e, - process.stackTrace ); - } +'use strict'; - // Support: Promises/A+ section 2.3.3.3.4.1 - // https://promisesaplus.com/#point-61 - // Ignore post-resolution exceptions - if ( depth + 1 >= maxDepth ) { +var defaults = require('../core/core.defaults'); +var elements = require('../elements/index'); +var helpers = require('../helpers/index'); - // Only substitute handlers pass on context - // and multiple values (non-spec behavior) - if ( handler !== Thrower ) { - that = undefined; - args = [ e ]; - } +defaults._set('global', { + plugins: { + filler: { + propagate: true + } + } +}); - deferred.rejectWith( that, args ); - } - } - }; +module.exports = function() { - // Support: Promises/A+ section 2.3.3.3.1 - // https://promisesaplus.com/#point-57 - // Re-resolve promises immediately to dodge false rejection from - // subsequent errors - if ( depth ) { - process(); - } else { + var mappers = { + dataset: function(source) { + var index = source.fill; + var chart = source.chart; + var meta = chart.getDatasetMeta(index); + var visible = meta && chart.isDatasetVisible(index); + var points = (visible && meta.dataset._children) || []; + var length = points.length || 0; - // Call an optional hook to record the stack, in case of exception - // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); - } - window.setTimeout( process ); - } - }; - } + return !length ? null : function(point, i) { + return (i < length && points[i]._view) || null; + }; + }, - return jQuery.Deferred( function( newDefer ) { + boundary: function(source) { + var boundary = source.boundary; + var x = boundary ? boundary.x : null; + var y = boundary ? boundary.y : null; - // progress_handlers.add( ... ) - tuples[ 0 ][ 3 ].add( - resolve( - 0, - newDefer, - jQuery.isFunction( onProgress ) ? - onProgress : - Identity, - newDefer.notifyWith - ) - ); + return function(point) { + return { + x: x === null ? point.x : x, + y: y === null ? point.y : y, + }; + }; + } + }; - // fulfilled_handlers.add( ... ) - tuples[ 1 ][ 3 ].add( - resolve( - 0, - newDefer, - jQuery.isFunction( onFulfilled ) ? - onFulfilled : - Identity - ) - ); + // @todo if (fill[0] === '#') + function decodeFill(el, index, count) { + var model = el._model || {}; + var fill = model.fill; + var target; - // rejected_handlers.add( ... ) - tuples[ 2 ][ 3 ].add( - resolve( - 0, - newDefer, - jQuery.isFunction( onRejected ) ? - onRejected : - Thrower - ) - ); - } ).promise(); - }, - - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; + if (fill === undefined) { + fill = !!model.backgroundColor; + } - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 5 ]; + if (fill === false || fill === null) { + return false; + } - // promise.progress = list.add - // promise.done = list.add - // promise.fail = list.add - promise[ tuple[ 1 ] ] = list.add; + if (fill === true) { + return 'origin'; + } - // Handle state - if ( stateString ) { - list.add( - function() { + target = parseFloat(fill, 10); + if (isFinite(target) && Math.floor(target) === target) { + if (fill[0] === '-' || fill[0] === '+') { + target = index + target; + } - // state = "resolved" (i.e., fulfilled) - // state = "rejected" - state = stateString; - }, + if (target === index || target < 0 || target >= count) { + return false; + } - // rejected_callbacks.disable - // fulfilled_callbacks.disable - tuples[ 3 - i ][ 2 ].disable, + return target; + } + + switch (fill) { + // compatibility + case 'bottom': + return 'start'; + case 'top': + return 'end'; + case 'zero': + return 'origin'; + // supported boundaries + case 'origin': + case 'start': + case 'end': + return fill; + // invalid fill values + default: + return false; + } + } - // progress_callbacks.lock - tuples[ 0 ][ 2 ].lock - ); - } + function computeBoundary(source) { + var model = source.el._model || {}; + var scale = source.el._scale || {}; + var fill = source.fill; + var target = null; + var horizontal; - // progress_handlers.fire - // fulfilled_handlers.fire - // rejected_handlers.fire - list.add( tuple[ 3 ].fire ); + if (isFinite(fill)) { + return null; + } - // deferred.notify = function() { deferred.notifyWith(...) } - // deferred.resolve = function() { deferred.resolveWith(...) } - // deferred.reject = function() { deferred.rejectWith(...) } - deferred[ tuple[ 0 ] ] = function() { - deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); - return this; - }; + // Backward compatibility: until v3, we still need to support boundary values set on + // the model (scaleTop, scaleBottom and scaleZero) because some external plugins and + // controllers might still use it (e.g. the Smith chart). - // deferred.notifyWith = list.fireWith - // deferred.resolveWith = list.fireWith - // deferred.rejectWith = list.fireWith - deferred[ tuple[ 0 ] + "With" ] = list.fireWith; - } ); + if (fill === 'start') { + target = model.scaleBottom === undefined ? scale.bottom : model.scaleBottom; + } else if (fill === 'end') { + target = model.scaleTop === undefined ? scale.top : model.scaleTop; + } else if (model.scaleZero !== undefined) { + target = model.scaleZero; + } else if (scale.getBasePosition) { + target = scale.getBasePosition(); + } else if (scale.getBasePixel) { + target = scale.getBasePixel(); + } - // Make the deferred a promise - promise.promise( deferred ); + if (target !== undefined && target !== null) { + if (target.x !== undefined && target.y !== undefined) { + return target; + } - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); + if (typeof target === 'number' && isFinite(target)) { + horizontal = scale.isHorizontal(); + return { + x: horizontal ? target : null, + y: horizontal ? null : target + }; + } } - // All done! - return deferred; - }, + return null; + } - // Deferred helper - when: function( singleValue ) { - var + function resolveTarget(sources, index, propagate) { + var source = sources[index]; + var fill = source.fill; + var visited = [index]; + var target; - // count of uncompleted subordinates - remaining = arguments.length, + if (!propagate) { + return fill; + } - // count of unprocessed arguments - i = remaining, + while (fill !== false && visited.indexOf(fill) === -1) { + if (!isFinite(fill)) { + return fill; + } - // subordinate fulfillment data - resolveContexts = Array( i ), - resolveValues = slice.call( arguments ), + target = sources[fill]; + if (!target) { + return false; + } - // the master Deferred - master = jQuery.Deferred(), + if (target.visible) { + return fill; + } - // subordinate callback factory - updateFunc = function( i ) { - return function( value ) { - resolveContexts[ i ] = this; - resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( !( --remaining ) ) { - master.resolveWith( resolveContexts, resolveValues ); - } - }; - }; + visited.push(fill); + fill = target.fill; + } - // Single- and empty arguments are adopted like Promise.resolve - if ( remaining <= 1 ) { - adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, - !remaining ); + return false; + } - // Use .then() to unwrap secondary thenables (cf. gh-3000) - if ( master.state() === "pending" || - jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + function createMapper(source) { + var fill = source.fill; + var type = 'dataset'; - return master.then(); - } + if (fill === false) { + return null; } - // Multiple arguments are aggregated like Promise.all array elements - while ( i-- ) { - adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + if (!isFinite(fill)) { + type = 'boundary'; } - return master.promise(); + return mappers[type](source); } -} ); + function isDrawable(point) { + return point && !point.skip; + } -// These usually indicate a programmer mistake during development, -// warn about them ASAP rather than swallowing them by default. -var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + function drawArea(ctx, curve0, curve1, len0, len1) { + var i; -jQuery.Deferred.exceptionHook = function( error, stack ) { + if (!len0 || !len1) { + return; + } - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); - } -}; + // building first area curve (normal) + ctx.moveTo(curve0[0].x, curve0[0].y); + for (i = 1; i < len0; ++i) { + helpers.canvas.lineTo(ctx, curve0[i - 1], curve0[i]); + } + // joining the two area curves + ctx.lineTo(curve1[len1 - 1].x, curve1[len1 - 1].y); + // building opposite area curve (reverse) + for (i = len1 - 1; i > 0; --i) { + helpers.canvas.lineTo(ctx, curve1[i], curve1[i - 1], true); + } + } + function doFill(ctx, points, mapper, view, color, loop) { + var count = points.length; + var span = view.spanGaps; + var curve0 = []; + var curve1 = []; + var len0 = 0; + var len1 = 0; + var i, ilen, index, p0, p1, d0, d1; + + ctx.beginPath(); + + for (i = 0, ilen = (count + !!loop); i < ilen; ++i) { + index = i % count; + p0 = points[index]._view; + p1 = mapper(p0, index, view); + d0 = isDrawable(p0); + d1 = isDrawable(p1); + + if (d0 && d1) { + len0 = curve0.push(p0); + len1 = curve1.push(p1); + } else if (len0 && len1) { + if (!span) { + drawArea(ctx, curve0, curve1, len0, len1); + len0 = len1 = 0; + curve0 = []; + curve1 = []; + } else { + if (d0) { + curve0.push(p0); + } + if (d1) { + curve1.push(p1); + } + } + } + } -jQuery.readyException = function( error ) { - window.setTimeout( function() { - throw error; - } ); -}; + drawArea(ctx, curve0, curve1, len0, len1); + ctx.closePath(); + ctx.fillStyle = color; + ctx.fill(); + } + return { + id: 'filler', + + afterDatasetsUpdate: function(chart, options) { + var count = (chart.data.datasets || []).length; + var propagate = options.propagate; + var sources = []; + var meta, i, el, source; + + for (i = 0; i < count; ++i) { + meta = chart.getDatasetMeta(i); + el = meta.dataset; + source = null; + + if (el && el._model && el instanceof elements.Line) { + source = { + visible: chart.isDatasetVisible(i), + fill: decodeFill(el, i, count), + chart: chart, + el: el + }; + } + meta.$filler = source; + sources.push(source); + } -// The deferred used on DOM ready -var readyList = jQuery.Deferred(); + for (i = 0; i < count; ++i) { + source = sources[i]; + if (!source) { + continue; + } -jQuery.fn.ready = function( fn ) { + source.fill = resolveTarget(sources, i, propagate); + source.boundary = computeBoundary(source); + source.mapper = createMapper(source); + } + }, - readyList - .then( fn ) + beforeDatasetDraw: function(chart, args) { + var meta = args.meta.$filler; + if (!meta) { + return; + } - // Wrap jQuery.readyException in a function so that the lookup - // happens at the time of error handling instead of callback - // registration. - .catch( function( error ) { - jQuery.readyException( error ); - } ); + var ctx = chart.ctx; + var el = meta.el; + var view = el._view; + var points = el._children || []; + var mapper = meta.mapper; + var color = view.backgroundColor || defaults.global.defaultColor; - return this; + if (mapper && color && points.length) { + helpers.canvas.clipArea(ctx, chart.chartArea); + doFill(ctx, points, mapper, view, color, el._loop); + helpers.canvas.unclipArea(ctx); + } + } + }; }; + })(); +}); -jQuery.extend( { +require.register("chart.js/src/plugins/plugin.legend.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); +var helpers = require('../helpers/index'); - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, +defaults._set('global', { + legend: { + display: true, + position: 'top', + fullWidth: true, + reverse: false, + weight: 1000, + + // a callback that will handle + onClick: function(e, legendItem) { + var index = legendItem.datasetIndex; + var ci = this.chart; + var meta = ci.getDatasetMeta(index); + + // See controller.isDatasetVisible comment + meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null; + + // We hid a dataset ... rerender the chart + ci.update(); + }, - // Handle when the DOM is ready - ready: function( wait ) { + onHover: null, + + labels: { + boxWidth: 40, + padding: 10, + // Generates labels shown in the legend + // Valid properties to return: + // text : text to display + // fillStyle : fill of coloured box + // strokeStyle: stroke of coloured box + // hidden : if this legend item refers to a hidden item + // lineCap : cap style for line + // lineDash + // lineDashOffset : + // lineJoin : + // lineWidth : + generateLabels: function(chart) { + var data = chart.data; + return helpers.isArray(data.datasets) ? data.datasets.map(function(dataset, i) { + return { + text: dataset.label, + fillStyle: (!helpers.isArray(dataset.backgroundColor) ? dataset.backgroundColor : dataset.backgroundColor[0]), + hidden: !chart.isDatasetVisible(i), + lineCap: dataset.borderCapStyle, + lineDash: dataset.borderDash, + lineDashOffset: dataset.borderDashOffset, + lineJoin: dataset.borderJoinStyle, + lineWidth: dataset.borderWidth, + strokeStyle: dataset.borderColor, + pointStyle: dataset.pointStyle, + + // Below is extra data used for toggling the datasets + datasetIndex: i + }; + }, this) : []; + } + } + }, - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; + legendCallback: function(chart) { + var text = []; + text.push('
    '); + for (var i = 0; i < chart.data.datasets.length; i++) { + text.push('
  • '); + if (chart.data.datasets[i].label) { + text.push(chart.data.datasets[i].label); + } + text.push('
  • '); } + text.push('
'); + return text.join(''); + } +}); - // Remember that the DOM is ready - jQuery.isReady = true; +module.exports = function(Chart) { - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } + var layout = Chart.layoutService; + var noop = helpers.noop; - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); + /** + * Helper function to get the box width based on the usePointStyle option + * @param labelopts {Object} the label options on the legend + * @param fontSize {Number} the label font size + * @return {Number} width of the color box area + */ + function getBoxWidth(labelOpts, fontSize) { + return labelOpts.usePointStyle ? + fontSize * Math.SQRT2 : + labelOpts.boxWidth; } -} ); -jQuery.ready.then = readyList.then; + Chart.Legend = Element.extend({ -// The ready event handler and self cleanup method -function completed() { - document.removeEventListener( "DOMContentLoaded", completed ); - window.removeEventListener( "load", completed ); - jQuery.ready(); -} + initialize: function(config) { + helpers.extend(this, config); -// Catch cases where $(document).ready() is called -// after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + // Contains hit boxes for each dataset (in dataset order) + this.legendHitBoxes = []; - // Handle it asynchronously to allow scripts the opportunity to delay ready - window.setTimeout( jQuery.ready ); + // Are we in doughnut mode which has a different data type + this.doughnutMode = false; + }, -} else { + // These methods are ordered by lifecycle. Utilities then follow. + // Any function defined here is inherited by all legend types. + // Any function can be extended by the legend type + + beforeUpdate: noop, + update: function(maxWidth, maxHeight, margins) { + var me = this; + + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); + + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = margins; + + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + // Labels + me.beforeBuildLabels(); + me.buildLabels(); + me.afterBuildLabels(); + + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); + + return me.minSize; + }, + afterUpdate: noop, - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed ); + // - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed ); -} + beforeSetDimensions: noop, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; + } + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; + // Reset minSize + me.minSize = { + width: 0, + height: 0 + }; + }, + afterSetDimensions: noop, -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; + // - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - access( elems, fn, i, key[ i ], true, emptyGet, raw ); - } + beforeBuildLabels: noop, + buildLabels: function() { + var me = this; + var labelOpts = me.options.labels || {}; + var legendItems = helpers.callback(labelOpts.generateLabels, [me.chart], me) || []; - // Sets one value - } else if ( value !== undefined ) { - chainable = true; + if (labelOpts.filter) { + legendItems = legendItems.filter(function(item) { + return labelOpts.filter(item, me.chart.data); + }); + } - if ( !jQuery.isFunction( value ) ) { - raw = true; - } + if (me.options.reverse) { + legendItems.reverse(); + } - if ( bulk ) { + me.legendItems = legendItems; + }, + afterBuildLabels: noop, - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; + // - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } + beforeFit: noop, + fit: function() { + var me = this; + var opts = me.options; + var labelOpts = opts.labels; + var display = opts.display; - if ( fn ) { - for ( ; i < len; i++ ) { - fn( - elems[ i ], key, raw ? - value : - value.call( elems[ i ], i, fn( elems[ i ], key ) ) - ); - } - } - } + var ctx = me.ctx; - if ( chainable ) { - return elems; - } + var globalDefault = defaults.global; + var valueOrDefault = helpers.valueOrDefault; + var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize); + var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle); + var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily); + var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); - // Gets - if ( bulk ) { - return fn.call( elems ); - } + // Reset hit boxes + var hitboxes = me.legendHitBoxes = []; - return len ? fn( elems[ 0 ], key ) : emptyGet; -}; -var acceptData = function( owner ) { + var minSize = me.minSize; + var isHorizontal = me.isHorizontal(); - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; + if (isHorizontal) { + minSize.width = me.maxWidth; // fill all the width + minSize.height = display ? 10 : 0; + } else { + minSize.width = display ? 10 : 0; + minSize.height = me.maxHeight; // fill all the height + } + // Increase sizes here + if (display) { + ctx.font = labelFont; + if (isHorizontal) { + // Labels + // Width of each line of legend boxes. Labels wrap onto multiple lines when there are too many to fit on one + var lineWidths = me.lineWidths = [0]; + var totalHeight = me.legendItems.length ? fontSize + (labelOpts.padding) : 0; -function Data() { - this.expando = jQuery.expando + Data.uid++; -} + ctx.textAlign = 'left'; + ctx.textBaseline = 'top'; -Data.uid = 1; + helpers.each(me.legendItems, function(legendItem, i) { + var boxWidth = getBoxWidth(labelOpts, fontSize); + var width = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; -Data.prototype = { + if (lineWidths[lineWidths.length - 1] + width + labelOpts.padding >= me.width) { + totalHeight += fontSize + (labelOpts.padding); + lineWidths[lineWidths.length] = me.left; + } - cache: function( owner ) { + // Store the hitbox width and height here. Final position will be updated in `draw` + hitboxes[i] = { + left: 0, + top: 0, + width: width, + height: fontSize + }; - // Check if the owner object already has a cache - var value = owner[ this.expando ]; + lineWidths[lineWidths.length - 1] += width + labelOpts.padding; + }); - // If not, create one - if ( !value ) { - value = {}; + minSize.height += totalHeight; - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return an empty object. - if ( acceptData( owner ) ) { + } else { + var vPadding = labelOpts.padding; + var columnWidths = me.columnWidths = []; + var totalWidth = labelOpts.padding; + var currentColWidth = 0; + var currentColHeight = 0; + var itemHeight = fontSize + vPadding; + + helpers.each(me.legendItems, function(legendItem, i) { + var boxWidth = getBoxWidth(labelOpts, fontSize); + var itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width; + + // If too tall, go to new column + if (currentColHeight + itemHeight > minSize.height) { + totalWidth += currentColWidth + labelOpts.padding; + columnWidths.push(currentColWidth); // previous column width + + currentColWidth = 0; + currentColHeight = 0; + } - // If it is a node unlikely to be stringify-ed or looped over - // use plain assignment - if ( owner.nodeType ) { - owner[ this.expando ] = value; + // Get max width + currentColWidth = Math.max(currentColWidth, itemWidth); + currentColHeight += itemHeight; - // Otherwise secure it in a non-enumerable property - // configurable must be true to allow the property to be - // deleted when data is removed - } else { - Object.defineProperty( owner, this.expando, { - value: value, - configurable: true - } ); + // Store the hitbox width and height here. Final position will be updated in `draw` + hitboxes[i] = { + left: 0, + top: 0, + width: itemWidth, + height: fontSize + }; + }); + + totalWidth += currentColWidth; + columnWidths.push(currentColWidth); + minSize.width += totalWidth; } } - } - return value; - }, - set: function( owner, data, value ) { - var prop, - cache = this.cache( owner ); + me.width = minSize.width; + me.height = minSize.height; + }, + afterFit: noop, - // Handle: [ owner, key, value ] args - // Always use camelCase key (gh-2257) - if ( typeof data === "string" ) { - cache[ jQuery.camelCase( data ) ] = value; + // Shared Methods + isHorizontal: function() { + return this.options.position === 'top' || this.options.position === 'bottom'; + }, - // Handle: [ owner, { properties } ] args - } else { + // Actually draw the legend on the canvas + draw: function() { + var me = this; + var opts = me.options; + var labelOpts = opts.labels; + var globalDefault = defaults.global; + var lineDefault = globalDefault.elements.line; + var legendWidth = me.width; + var lineWidths = me.lineWidths; + + if (opts.display) { + var ctx = me.ctx; + var valueOrDefault = helpers.valueOrDefault; + var fontColor = valueOrDefault(labelOpts.fontColor, globalDefault.defaultFontColor); + var fontSize = valueOrDefault(labelOpts.fontSize, globalDefault.defaultFontSize); + var fontStyle = valueOrDefault(labelOpts.fontStyle, globalDefault.defaultFontStyle); + var fontFamily = valueOrDefault(labelOpts.fontFamily, globalDefault.defaultFontFamily); + var labelFont = helpers.fontString(fontSize, fontStyle, fontFamily); + var cursor; + + // Canvas setup + ctx.textAlign = 'left'; + ctx.textBaseline = 'middle'; + ctx.lineWidth = 0.5; + ctx.strokeStyle = fontColor; // for strikethrough effect + ctx.fillStyle = fontColor; // render in correct colour + ctx.font = labelFont; + + var boxWidth = getBoxWidth(labelOpts, fontSize); + var hitboxes = me.legendHitBoxes; + + // current position + var drawLegendBox = function(x, y, legendItem) { + if (isNaN(boxWidth) || boxWidth <= 0) { + return; + } - // Copy the properties one-by-one to the cache object - for ( prop in data ) { - cache[ jQuery.camelCase( prop ) ] = data[ prop ]; - } - } - return cache; - }, - get: function( owner, key ) { - return key === undefined ? - this.cache( owner ) : + // Set the ctx for the box + ctx.save(); - // Always use camelCase key (gh-2257) - owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; - }, - access: function( owner, key, value ) { + ctx.fillStyle = valueOrDefault(legendItem.fillStyle, globalDefault.defaultColor); + ctx.lineCap = valueOrDefault(legendItem.lineCap, lineDefault.borderCapStyle); + ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, lineDefault.borderDashOffset); + ctx.lineJoin = valueOrDefault(legendItem.lineJoin, lineDefault.borderJoinStyle); + ctx.lineWidth = valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth); + ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, globalDefault.defaultColor); + var isLineWidthZero = (valueOrDefault(legendItem.lineWidth, lineDefault.borderWidth) === 0); + + if (ctx.setLineDash) { + // IE 9 and 10 do not support line dash + ctx.setLineDash(valueOrDefault(legendItem.lineDash, lineDefault.borderDash)); + } - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ( ( key && typeof key === "string" ) && value === undefined ) ) { + if (opts.labels && opts.labels.usePointStyle) { + // Recalculate x and y for drawPoint() because its expecting + // x and y to be center of figure (instead of top left) + var radius = fontSize * Math.SQRT2 / 2; + var offSet = radius / Math.SQRT2; + var centerX = x + offSet; + var centerY = y + offSet; - return this.get( owner, key ); - } + // Draw pointStyle as legend symbol + helpers.canvas.drawPoint(ctx, legendItem.pointStyle, radius, centerX, centerY); + } else { + // Draw box as legend symbol + if (!isLineWidthZero) { + ctx.strokeRect(x, y, boxWidth, fontSize); + } + ctx.fillRect(x, y, boxWidth, fontSize); + } - // When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); + ctx.restore(); + }; + var fillText = function(x, y, legendItem, textWidth) { + var halfFontSize = fontSize / 2; + var xLeft = boxWidth + halfFontSize + x; + var yMiddle = y + halfFontSize; - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, - cache = owner[ this.expando ]; + ctx.fillText(legendItem.text, xLeft, yMiddle); - if ( cache === undefined ) { - return; - } + if (legendItem.hidden) { + // Strikethrough the text if hidden + ctx.beginPath(); + ctx.lineWidth = 2; + ctx.moveTo(xLeft, yMiddle); + ctx.lineTo(xLeft + textWidth, yMiddle); + ctx.stroke(); + } + }; - if ( key !== undefined ) { + // Horizontal + var isHorizontal = me.isHorizontal(); + if (isHorizontal) { + cursor = { + x: me.left + ((legendWidth - lineWidths[0]) / 2), + y: me.top + labelOpts.padding, + line: 0 + }; + } else { + cursor = { + x: me.left + labelOpts.padding, + y: me.top + labelOpts.padding, + line: 0 + }; + } - // Support array or space separated string of keys - if ( Array.isArray( key ) ) { + var itemHeight = fontSize + labelOpts.padding; + helpers.each(me.legendItems, function(legendItem, i) { + var textWidth = ctx.measureText(legendItem.text).width; + var width = boxWidth + (fontSize / 2) + textWidth; + var x = cursor.x; + var y = cursor.y; + + if (isHorizontal) { + if (x + width >= legendWidth) { + y = cursor.y += itemHeight; + cursor.line++; + x = cursor.x = me.left + ((legendWidth - lineWidths[cursor.line]) / 2); + } + } else if (y + itemHeight > me.bottom) { + x = cursor.x = x + me.columnWidths[cursor.line] + labelOpts.padding; + y = cursor.y = me.top + labelOpts.padding; + cursor.line++; + } - // If key is an array of keys... - // We always set camelCase keys, so remove that. - key = key.map( jQuery.camelCase ); - } else { - key = jQuery.camelCase( key ); + drawLegendBox(x, y, legendItem); - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - key = key in cache ? - [ key ] : - ( key.match( rnothtmlwhite ) || [] ); - } + hitboxes[i].left = x; + hitboxes[i].top = y; - i = key.length; + // Fill the actual label + fillText(x, y, legendItem, textWidth); - while ( i-- ) { - delete cache[ key[ i ] ]; - } - } + if (isHorizontal) { + cursor.x += width + (labelOpts.padding); + } else { + cursor.y += itemHeight; + } - // Remove the expando if there's no more data - if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + }); + } + }, - // Support: Chrome <=35 - 45 - // Webkit & Blink performance suffers when deleting properties - // from DOM nodes, so set to undefined instead - // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) - if ( owner.nodeType ) { - owner[ this.expando ] = undefined; + /** + * Handle an event + * @private + * @param {IEvent} event - The event to handle + * @return {Boolean} true if a change occured + */ + handleEvent: function(e) { + var me = this; + var opts = me.options; + var type = e.type === 'mouseup' ? 'click' : e.type; + var changed = false; + + if (type === 'mousemove') { + if (!opts.onHover) { + return; + } + } else if (type === 'click') { + if (!opts.onClick) { + return; + } } else { - delete owner[ this.expando ]; + return; } - } - }, - hasData: function( owner ) { - var cache = owner[ this.expando ]; - return cache !== undefined && !jQuery.isEmptyObject( cache ); - } -}; -var dataPriv = new Data(); - -var dataUser = new Data(); + // Chart event already has relative position in it + var x = e.x; + var y = e.y; + if (x >= me.left && x <= me.right && y >= me.top && y <= me.bottom) { + // See if we are touching one of the dataset boxes + var lh = me.legendHitBoxes; + for (var i = 0; i < lh.length; ++i) { + var hitBox = lh[i]; -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) { + // Touching an element + if (type === 'click') { + // use e.native for backwards compatibility + opts.onClick.call(me, e.native, me.legendItems[i]); + changed = true; + break; + } else if (type === 'mousemove') { + // use e.native for backwards compatibility + opts.onHover.call(me, e.native, me.legendItems[i]); + changed = true; + break; + } + } + } + } -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /[A-Z]/g; + return changed; + } + }); -function getData( data ) { - if ( data === "true" ) { - return true; - } + function createNewLegendAndAttach(chart, legendOpts) { + var legend = new Chart.Legend({ + ctx: chart.ctx, + options: legendOpts, + chart: chart + }); - if ( data === "false" ) { - return false; + layout.configure(chart, legend, legendOpts); + layout.addBox(chart, legend); + chart.legend = legend; } - if ( data === "null" ) { - return null; - } + return { + id: 'legend', - // Only convert to a number if it doesn't change the string - if ( data === +data + "" ) { - return +data; - } + beforeInit: function(chart) { + var legendOpts = chart.options.legend; - if ( rbrace.test( data ) ) { - return JSON.parse( data ); - } + if (legendOpts) { + createNewLegendAndAttach(chart, legendOpts); + } + }, - return data; -} + beforeUpdate: function(chart) { + var legendOpts = chart.options.legend; + var legend = chart.legend; -function dataAttr( elem, key, data ) { - var name; + if (legendOpts) { + helpers.mergeIf(legendOpts, defaults.global.legend); - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); - data = elem.getAttribute( name ); + if (legend) { + layout.configure(chart, legend, legendOpts); + legend.options = legendOpts; + } else { + createNewLegendAndAttach(chart, legendOpts); + } + } else if (legend) { + layout.removeBox(chart, legend); + delete chart.legend; + } + }, - if ( typeof data === "string" ) { - try { - data = getData( data ); - } catch ( e ) {} - - // Make sure we set the data so it isn't changed later - dataUser.set( elem, key, data ); - } else { - data = undefined; + afterEvent: function(chart, e) { + var legend = chart.legend; + if (legend) { + legend.handleEvent(e); + } } + }; +}; + })(); +}); + +require.register("chart.js/src/plugins/plugin.title.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; + +var defaults = require('../core/core.defaults'); +var Element = require('../core/core.element'); +var helpers = require('../helpers/index'); + +defaults._set('global', { + title: { + display: false, + fontStyle: 'bold', + fullWidth: true, + lineHeight: 1.2, + padding: 10, + position: 'top', + text: '', + weight: 2000 // by default greater than legend (1000) to be above } - return data; -} +}); -jQuery.extend( { - hasData: function( elem ) { - return dataUser.hasData( elem ) || dataPriv.hasData( elem ); - }, +module.exports = function(Chart) { - data: function( elem, name, data ) { - return dataUser.access( elem, name, data ); - }, + var layout = Chart.layoutService; + var noop = helpers.noop; - removeData: function( elem, name ) { - dataUser.remove( elem, name ); - }, + Chart.Title = Element.extend({ + initialize: function(config) { + var me = this; + helpers.extend(me, config); - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to dataPriv methods, these can be deprecated. - _data: function( elem, name, data ) { - return dataPriv.access( elem, name, data ); - }, + // Contains hit boxes for each dataset (in dataset order) + me.legendHitBoxes = []; + }, - _removeData: function( elem, name ) { - dataPriv.remove( elem, name ); - } -} ); + // These methods are ordered by lifecycle. Utilities then follow. -jQuery.fn.extend( { - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; + beforeUpdate: noop, + update: function(maxWidth, maxHeight, margins) { + var me = this; - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = dataUser.get( elem ); + // Update Lifecycle - Probably don't want to ever extend or overwrite this function ;) + me.beforeUpdate(); - if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { + // Absorb the master measurements + me.maxWidth = maxWidth; + me.maxHeight = maxHeight; + me.margins = margins; - // Support: IE 11 only - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice( 5 ) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - dataPriv.set( elem, "hasDataAttrs", true ); - } + // Dimensions + me.beforeSetDimensions(); + me.setDimensions(); + me.afterSetDimensions(); + // Labels + me.beforeBuildLabels(); + me.buildLabels(); + me.afterBuildLabels(); + + // Fit + me.beforeFit(); + me.fit(); + me.afterFit(); + // + me.afterUpdate(); + + return me.minSize; + + }, + afterUpdate: noop, + + // + + beforeSetDimensions: noop, + setDimensions: function() { + var me = this; + // Set the unconstrained dimension before label rotation + if (me.isHorizontal()) { + // Reset position before calculating rotation + me.width = me.maxWidth; + me.left = 0; + me.right = me.width; + } else { + me.height = me.maxHeight; + + // Reset position before calculating rotation + me.top = 0; + me.bottom = me.height; } - return data; - } + // Reset padding + me.paddingLeft = 0; + me.paddingTop = 0; + me.paddingRight = 0; + me.paddingBottom = 0; - // Sets multiple values - if ( typeof key === "object" ) { - return this.each( function() { - dataUser.set( this, key ); - } ); - } + // Reset minSize + me.minSize = { + width: 0, + height: 0 + }; + }, + afterSetDimensions: noop, - return access( this, function( value ) { - var data; + // - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { + beforeBuildLabels: noop, + buildLabels: noop, + afterBuildLabels: noop, - // Attempt to get data from the cache - // The key will always be camelCased in Data - data = dataUser.get( elem, key ); - if ( data !== undefined ) { - return data; + // + + beforeFit: noop, + fit: function() { + var me = this; + var valueOrDefault = helpers.valueOrDefault; + var opts = me.options; + var display = opts.display; + var fontSize = valueOrDefault(opts.fontSize, defaults.global.defaultFontSize); + var minSize = me.minSize; + var lineCount = helpers.isArray(opts.text) ? opts.text.length : 1; + var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize); + var textSize = display ? (lineCount * lineHeight) + (opts.padding * 2) : 0; + + if (me.isHorizontal()) { + minSize.width = me.maxWidth; // fill all the width + minSize.height = textSize; + } else { + minSize.width = textSize; + minSize.height = me.maxHeight; // fill all the height + } + + me.width = minSize.width; + me.height = minSize.height; + + }, + afterFit: noop, + + // Shared Methods + isHorizontal: function() { + var pos = this.options.position; + return pos === 'top' || pos === 'bottom'; + }, + + // Actually draw the title block on the canvas + draw: function() { + var me = this; + var ctx = me.ctx; + var valueOrDefault = helpers.valueOrDefault; + var opts = me.options; + var globalDefaults = defaults.global; + + if (opts.display) { + var fontSize = valueOrDefault(opts.fontSize, globalDefaults.defaultFontSize); + var fontStyle = valueOrDefault(opts.fontStyle, globalDefaults.defaultFontStyle); + var fontFamily = valueOrDefault(opts.fontFamily, globalDefaults.defaultFontFamily); + var titleFont = helpers.fontString(fontSize, fontStyle, fontFamily); + var lineHeight = helpers.options.toLineHeight(opts.lineHeight, fontSize); + var offset = lineHeight / 2 + opts.padding; + var rotation = 0; + var top = me.top; + var left = me.left; + var bottom = me.bottom; + var right = me.right; + var maxWidth, titleX, titleY; + + ctx.fillStyle = valueOrDefault(opts.fontColor, globalDefaults.defaultFontColor); // render in correct colour + ctx.font = titleFont; + + // Horizontal + if (me.isHorizontal()) { + titleX = left + ((right - left) / 2); // midpoint of the width + titleY = top + offset; + maxWidth = right - left; + } else { + titleX = opts.position === 'left' ? left + offset : right - offset; + titleY = top + ((bottom - top) / 2); + maxWidth = bottom - top; + rotation = Math.PI * (opts.position === 'left' ? -0.5 : 0.5); } - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, key ); - if ( data !== undefined ) { - return data; + ctx.save(); + ctx.translate(titleX, titleY); + ctx.rotate(rotation); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + var text = opts.text; + if (helpers.isArray(text)) { + var y = 0; + for (var i = 0; i < text.length; ++i) { + ctx.fillText(text[i], 0, y, maxWidth); + y += lineHeight; + } + } else { + ctx.fillText(text, 0, 0, maxWidth); } - // We tried really hard, but the data doesn't exist. - return; + ctx.restore(); } + } + }); - // Set the data... - this.each( function() { - - // We always store the camelCased key - dataUser.set( this, key, value ); - } ); - }, null, value, arguments.length > 1, null, true ); - }, + function createNewTitleBlockAndAttach(chart, titleOpts) { + var title = new Chart.Title({ + ctx: chart.ctx, + options: titleOpts, + chart: chart + }); - removeData: function( key ) { - return this.each( function() { - dataUser.remove( this, key ); - } ); + layout.configure(chart, title, titleOpts); + layout.addBox(chart, title); + chart.titleBlock = title; } -} ); + return { + id: 'title', -jQuery.extend( { - queue: function( elem, type, data ) { - var queue; + beforeInit: function(chart) { + var titleOpts = chart.options.title; - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = dataPriv.get( elem, type ); + if (titleOpts) { + createNewTitleBlockAndAttach(chart, titleOpts); + } + }, - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || Array.isArray( data ) ) { - queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + beforeUpdate: function(chart) { + var titleOpts = chart.options.title; + var titleBlock = chart.titleBlock; + + if (titleOpts) { + helpers.mergeIf(titleOpts, defaults.global.title); + + if (titleBlock) { + layout.configure(chart, titleBlock, titleOpts); + titleBlock.options = titleOpts; } else { - queue.push( data ); + createNewTitleBlockAndAttach(chart, titleOpts); } + } else if (titleBlock) { + Chart.layoutService.removeBox(chart, titleBlock); + delete chart.titleBlock; } - return queue || []; } - }, + }; +}; + })(); +}); - dequeue: function( elem, type ) { - type = type || "fx"; +require.register("chart.js/src/scales/scale.category.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; +module.exports = function(Chart) { - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } + // Default config for a category scale + var defaultConfig = { + position: 'bottom' + }; - if ( fn ) { + var DatasetScale = Chart.Scale.extend({ + /** + * Internal function to get the correct labels. If data.xLabels or data.yLabels are defined, use those + * else fall back to data.labels + * @private + */ + getLabels: function() { + var data = this.chart.data; + return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels; + }, - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); + determineDataLimits: function() { + var me = this; + var labels = me.getLabels(); + me.minIndex = 0; + me.maxIndex = labels.length - 1; + var findIndex; + + if (me.options.ticks.min !== undefined) { + // user specified min value + findIndex = labels.indexOf(me.options.ticks.min); + me.minIndex = findIndex !== -1 ? findIndex : me.minIndex; } - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } + if (me.options.ticks.max !== undefined) { + // user specified max value + findIndex = labels.indexOf(me.options.ticks.max); + me.maxIndex = findIndex !== -1 ? findIndex : me.maxIndex; + } - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, + me.min = labels[me.minIndex]; + me.max = labels[me.maxIndex]; + }, - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { - empty: jQuery.Callbacks( "once memory" ).add( function() { - dataPriv.remove( elem, [ type + "queue", key ] ); - } ) - } ); - } -} ); + buildTicks: function() { + var me = this; + var labels = me.getLabels(); + // If we are viewing some subset of labels, slice the original array + me.ticks = (me.minIndex === 0 && me.maxIndex === labels.length - 1) ? labels : labels.slice(me.minIndex, me.maxIndex + 1); + }, -jQuery.fn.extend( { - queue: function( type, data ) { - var setter = 2; + getLabelForIndex: function(index, datasetIndex) { + var me = this; + var data = me.chart.data; + var isHorizontal = me.isHorizontal(); - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } + if (data.yLabels && !isHorizontal) { + return me.getRightValue(data.datasets[datasetIndex].data[index]); + } + return me.ticks[index - me.minIndex]; + }, - if ( arguments.length < setter ) { - return jQuery.queue( this[ 0 ], type ); - } + // Used to get data value locations. Value can either be an index or a numerical value + getPixelForValue: function(value, index) { + var me = this; + var offset = me.options.offset; + // 1 is added because we need the length but we have the indexes + var offsetAmt = Math.max((me.maxIndex + 1 - me.minIndex - (offset ? 0 : 1)), 1); - return data === undefined ? - this : - this.each( function() { - var queue = jQuery.queue( this, type, data ); + // If value is a data object, then index is the index in the data array, + // not the index of the scale. We need to change that. + var valueCategory; + if (value !== undefined && value !== null) { + valueCategory = me.isHorizontal() ? value.x : value.y; + } + if (valueCategory !== undefined || (value !== undefined && isNaN(index))) { + var labels = me.getLabels(); + value = valueCategory || value; + var idx = labels.indexOf(value); + index = idx !== -1 ? idx : index; + } - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); + if (me.isHorizontal()) { + var valueWidth = me.width / offsetAmt; + var widthOffset = (valueWidth * (index - me.minIndex)); - if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { - jQuery.dequeue( this, type ); + if (offset) { + widthOffset += (valueWidth / 2); } - } ); - }, - dequeue: function( type ) { - return this.each( function() { - jQuery.dequeue( this, type ); - } ); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; + return me.left + Math.round(widthOffset); + } + var valueHeight = me.height / offsetAmt; + var heightOffset = (valueHeight * (index - me.minIndex)); - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; + if (offset) { + heightOffset += (valueHeight / 2); + } - while ( i-- ) { - tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); + return me.top + Math.round(heightOffset); + }, + getPixelForTick: function(index) { + return this.getPixelForValue(this.ticks[index], index + this.minIndex, null); + }, + getValueForPixel: function(pixel) { + var me = this; + var offset = me.options.offset; + var value; + var offsetAmt = Math.max((me._ticks.length - (offset ? 0 : 1)), 1); + var horz = me.isHorizontal(); + var valueDimension = (horz ? me.width : me.height) / offsetAmt; + + pixel -= horz ? me.left : me.top; + + if (offset) { + pixel -= (valueDimension / 2); } - } - resolve(); - return defer.promise( obj ); - } -} ); -var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; -var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + if (pixel <= 0) { + value = 0; + } else { + value = Math.round(pixel / valueDimension); + } + return value + me.minIndex; + }, + getBasePixel: function() { + return this.bottom; + } + }); -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + Chart.scaleService.registerScaleType('category', DatasetScale, defaultConfig); -var isHiddenWithinTree = function( elem, el ) { +}; + })(); +}); - // isHiddenWithinTree might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; +require.register("chart.js/src/scales/scale.linear.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Inline style trumps all - return elem.style.display === "none" || - elem.style.display === "" && +var defaults = require('../core/core.defaults'); +var helpers = require('../helpers/index'); +var Ticks = require('../core/core.ticks'); - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - jQuery.contains( elem.ownerDocument, elem ) && +module.exports = function(Chart) { - jQuery.css( elem, "display" ) === "none"; + var defaultConfig = { + position: 'left', + ticks: { + callback: Ticks.formatters.linear + } }; -var swap = function( elem, options, callback, args ) { - var ret, name, - old = {}; + var LinearScale = Chart.LinearScaleBase.extend({ - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } + determineDataLimits: function() { + var me = this; + var opts = me.options; + var chart = me.chart; + var data = chart.data; + var datasets = data.datasets; + var isHorizontal = me.isHorizontal(); + var DEFAULT_MIN = 0; + var DEFAULT_MAX = 1; - ret = callback.apply( elem, args || [] ); + function IDMatches(meta) { + return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; + } - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } + // First Calculate the range + me.min = null; + me.max = null; - return ret; -}; + var hasStacks = opts.stacked; + if (hasStacks === undefined) { + helpers.each(datasets, function(dataset, datasetIndex) { + if (hasStacks) { + return; + } + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && + meta.stack !== undefined) { + hasStacks = true; + } + }); + } + if (opts.stacked || hasStacks) { + var valuesPerStack = {}; + helpers.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + var key = [ + meta.type, + // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined + ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), + meta.stack + ].join('.'); -function adjustCSS( elem, prop, valueParts, tween ) { - var adjusted, - scale = 1, - maxIterations = 20, - currentValue = tween ? - function() { - return tween.cur(); - } : - function() { - return jQuery.css( elem, prop, "" ); - }, - initial = currentValue(), - unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + if (valuesPerStack[key] === undefined) { + valuesPerStack[key] = { + positiveValues: [], + negativeValues: [] + }; + } - // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && - rcssNum.exec( jQuery.css( elem, prop ) ); + // Store these per type + var positiveValues = valuesPerStack[key].positiveValues; + var negativeValues = valuesPerStack[key].negativeValues; - if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } - // Trust units reported by jQuery.css - unit = unit || initialInUnit[ 3 ]; + positiveValues[index] = positiveValues[index] || 0; + negativeValues[index] = negativeValues[index] || 0; - // Make sure we update the tween properties later on - valueParts = valueParts || []; + if (opts.relativePoints) { + positiveValues[index] = 100; + } else if (value < 0) { + negativeValues[index] += value; + } else { + positiveValues[index] += value; + } + }); + } + }); - // Iteratively approximate from a nonzero starting point - initialInUnit = +initial || 1; + helpers.each(valuesPerStack, function(valuesForType) { + var values = valuesForType.positiveValues.concat(valuesForType.negativeValues); + var minVal = helpers.min(values); + var maxVal = helpers.max(values); + me.min = me.min === null ? minVal : Math.min(me.min, minVal); + me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); + }); - do { + } else { + helpers.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } - // If previous iteration zeroed out, double until we get *something*. - // Use string for doubling so we don't accidentally see scale as unchanged below - scale = scale || ".5"; + if (me.min === null) { + me.min = value; + } else if (value < me.min) { + me.min = value; + } - // Adjust and apply - initialInUnit = initialInUnit / scale; - jQuery.style( elem, prop, initialInUnit + unit ); + if (me.max === null) { + me.max = value; + } else if (value > me.max) { + me.max = value; + } + }); + } + }); + } - // Update scale, tolerating zero or NaN from tween.cur() - // Break the loop if scale is unchanged or perfect, or if we've just had enough. - } while ( - scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations - ); - } + me.min = isFinite(me.min) && !isNaN(me.min) ? me.min : DEFAULT_MIN; + me.max = isFinite(me.max) && !isNaN(me.max) ? me.max : DEFAULT_MAX; - if ( valueParts ) { - initialInUnit = +initialInUnit || +initial || 0; + // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero + this.handleTickRangeOptions(); + }, + getTickLimit: function() { + var maxTicks; + var me = this; + var tickOpts = me.options.ticks; - // Apply relative offset (+=/-=) if specified - adjusted = valueParts[ 1 ] ? - initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : - +valueParts[ 2 ]; - if ( tween ) { - tween.unit = unit; - tween.start = initialInUnit; - tween.end = adjusted; - } - } - return adjusted; -} + if (me.isHorizontal()) { + maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.width / 50)); + } else { + // The factor of 2 used to scale the font size has been experimentally determined. + var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, defaults.global.defaultFontSize); + maxTicks = Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(me.height / (2 * tickFontSize))); + } + return maxTicks; + }, + // Called after the ticks are built. We need + handleDirectionalChanges: function() { + if (!this.isHorizontal()) { + // We are in a vertical orientation. The top value is the highest. So reverse the array + this.ticks.reverse(); + } + }, + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + // Utils + getPixelForValue: function(value) { + // This must be called after fit has been run so that + // this.left, this.top, this.right, and this.bottom have been defined + var me = this; + var start = me.start; -var defaultDisplayMap = {}; + var rightValue = +me.getRightValue(value); + var pixel; + var range = me.end - start; -function getDefaultDisplay( elem ) { - var temp, - doc = elem.ownerDocument, - nodeName = elem.nodeName, - display = defaultDisplayMap[ nodeName ]; + if (me.isHorizontal()) { + pixel = me.left + (me.width / range * (rightValue - start)); + return Math.round(pixel); + } - if ( display ) { - return display; - } + pixel = me.bottom - (me.height / range * (rightValue - start)); + return Math.round(pixel); + }, + getValueForPixel: function(pixel) { + var me = this; + var isHorizontal = me.isHorizontal(); + var innerDimension = isHorizontal ? me.width : me.height; + var offset = (isHorizontal ? pixel - me.left : me.bottom - pixel) / innerDimension; + return me.start + ((me.end - me.start) * offset); + }, + getPixelForTick: function(index) { + return this.getPixelForValue(this.ticksAsNumbers[index]); + } + }); + Chart.scaleService.registerScaleType('linear', LinearScale, defaultConfig); - temp = doc.body.appendChild( doc.createElement( nodeName ) ); - display = jQuery.css( temp, "display" ); +}; + })(); +}); - temp.parentNode.removeChild( temp ); +require.register("chart.js/src/scales/scale.linearbase.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - if ( display === "none" ) { - display = "block"; - } - defaultDisplayMap[ nodeName ] = display; +var helpers = require('../helpers/index'); +var Ticks = require('../core/core.ticks'); - return display; -} +module.exports = function(Chart) { -function showHide( elements, show ) { - var display, elem, - values = [], - index = 0, - length = elements.length; + var noop = helpers.noop; - // Determine new display value for elements that need to change - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } + Chart.LinearScaleBase = Chart.Scale.extend({ + getRightValue: function(value) { + if (typeof value === 'string') { + return +value; + } + return Chart.Scale.prototype.getRightValue.call(this, value); + }, - display = elem.style.display; - if ( show ) { + handleTickRangeOptions: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + + // If we are forcing it to begin at 0, but 0 will already be rendered on the chart, + // do nothing since that would make the chart weird. If the user really wants a weird chart + // axis, they can manually override it + if (tickOpts.beginAtZero) { + var minSign = helpers.sign(me.min); + var maxSign = helpers.sign(me.max); + + if (minSign < 0 && maxSign < 0) { + // move the top up to 0 + me.max = 0; + } else if (minSign > 0 && maxSign > 0) { + // move the bottom down to 0 + me.min = 0; + } + } - // Since we force visibility upon cascade-hidden elements, an immediate (and slow) - // check is required in this first loop unless we have a nonempty display value (either - // inline or about-to-be-restored) - if ( display === "none" ) { - values[ index ] = dataPriv.get( elem, "display" ) || null; - if ( !values[ index ] ) { - elem.style.display = ""; + var setMin = tickOpts.min !== undefined || tickOpts.suggestedMin !== undefined; + var setMax = tickOpts.max !== undefined || tickOpts.suggestedMax !== undefined; + + if (tickOpts.min !== undefined) { + me.min = tickOpts.min; + } else if (tickOpts.suggestedMin !== undefined) { + if (me.min === null) { + me.min = tickOpts.suggestedMin; + } else { + me.min = Math.min(me.min, tickOpts.suggestedMin); } } - if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { - values[ index ] = getDefaultDisplay( elem ); + + if (tickOpts.max !== undefined) { + me.max = tickOpts.max; + } else if (tickOpts.suggestedMax !== undefined) { + if (me.max === null) { + me.max = tickOpts.suggestedMax; + } else { + me.max = Math.max(me.max, tickOpts.suggestedMax); + } } - } else { - if ( display !== "none" ) { - values[ index ] = "none"; - // Remember what we're overwriting - dataPriv.set( elem, "display", display ); + if (setMin !== setMax) { + // We set the min or the max but not both. + // So ensure that our range is good + // Inverted or 0 length range can happen when + // ticks.min is set, and no datasets are visible + if (me.min >= me.max) { + if (setMin) { + me.max = me.min + 1; + } else { + me.min = me.max - 1; + } + } } - } - } - // Set the display of the elements in a second loop to avoid constant reflow - for ( index = 0; index < length; index++ ) { - if ( values[ index ] != null ) { - elements[ index ].style.display = values[ index ]; - } - } + if (me.min === me.max) { + me.max++; - return elements; -} + if (!tickOpts.beginAtZero) { + me.min--; + } + } + }, + getTickLimit: noop, + handleDirectionalChanges: noop, + + buildTicks: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + + // Figure out what the max number of ticks we can support it is based on the size of + // the axis area. For now, we say that the minimum tick spacing in pixels must be 50 + // We also limit the maximum number of ticks to 11 which gives a nice 10 squares on + // the graph. Make sure we always have at least 2 ticks + var maxTicks = me.getTickLimit(); + maxTicks = Math.max(2, maxTicks); + + var numericGeneratorOptions = { + maxTicks: maxTicks, + min: tickOpts.min, + max: tickOpts.max, + stepSize: helpers.valueOrDefault(tickOpts.fixedStepSize, tickOpts.stepSize) + }; + var ticks = me.ticks = Ticks.generators.linear(numericGeneratorOptions, me); -jQuery.fn.extend( { - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state ) { - if ( typeof state === "boolean" ) { - return state ? this.show() : this.hide(); - } + me.handleDirectionalChanges(); - return this.each( function() { - if ( isHiddenWithinTree( this ) ) { - jQuery( this ).show(); + // At this point, we need to update our max and min given the tick values since we have expanded the + // range of the scale + me.max = helpers.max(ticks); + me.min = helpers.min(ticks); + + if (tickOpts.reverse) { + ticks.reverse(); + + me.start = me.max; + me.end = me.min; } else { - jQuery( this ).hide(); + me.start = me.min; + me.end = me.max; } - } ); - } -} ); -var rcheckableType = ( /^(?:checkbox|radio)$/i ); + }, + convertTicksToLabels: function() { + var me = this; + me.ticksAsNumbers = me.ticks.slice(); + me.zeroLineIndex = me.ticks.indexOf(0); -var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + Chart.Scale.prototype.convertTicksToLabels.call(me); + } + }); +}; + })(); +}); -var rscriptType = ( /^$|\/(?:java|ecma)script/i ); +require.register("chart.js/src/scales/scale.logarithmic.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; +var helpers = require('../helpers/index'); +var Ticks = require('../core/core.ticks'); +module.exports = function(Chart) { -// We have to close these tags to support XHTML (#13200) -var wrapMap = { + var defaultConfig = { + position: 'left', - // Support: IE <=9 only - option: [ 1, "" ], + // label settings + ticks: { + callback: Ticks.formatters.logarithmic + } + }; - // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten - // this by omitting or other required elements. - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], + var LogarithmicScale = Chart.Scale.extend({ + determineDataLimits: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + var chart = me.chart; + var data = chart.data; + var datasets = data.datasets; + var valueOrDefault = helpers.valueOrDefault; + var isHorizontal = me.isHorizontal(); + function IDMatches(meta) { + return isHorizontal ? meta.xAxisID === me.id : meta.yAxisID === me.id; + } + + // Calculate Range + me.min = null; + me.max = null; + me.minNotZero = null; + + var hasStacks = opts.stacked; + if (hasStacks === undefined) { + helpers.each(datasets, function(dataset, datasetIndex) { + if (hasStacks) { + return; + } - _default: [ 0, "", "" ] -}; + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta) && + meta.stack !== undefined) { + hasStacks = true; + } + }); + } -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; + if (opts.stacked || hasStacks) { + var valuesPerStack = {}; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; + helpers.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + var key = [ + meta.type, + // we have a separate stack for stack=undefined datasets when the opts.stacked is undefined + ((opts.stacked === undefined && meta.stack === undefined) ? datasetIndex : ''), + meta.stack + ].join('.'); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + if (valuesPerStack[key] === undefined) { + valuesPerStack[key] = []; + } -function getAll( context, tag ) { + helpers.each(dataset.data, function(rawValue, index) { + var values = valuesPerStack[key]; + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } - // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) - var ret; + values[index] = values[index] || 0; - if ( typeof context.getElementsByTagName !== "undefined" ) { - ret = context.getElementsByTagName( tag || "*" ); + if (opts.relativePoints) { + values[index] = 100; + } else { + // Don't need to split positive and negative since the log scale can't handle a 0 crossing + values[index] += value; + } + }); + } + }); - } else if ( typeof context.querySelectorAll !== "undefined" ) { - ret = context.querySelectorAll( tag || "*" ); + helpers.each(valuesPerStack, function(valuesForType) { + var minVal = helpers.min(valuesForType); + var maxVal = helpers.max(valuesForType); + me.min = me.min === null ? minVal : Math.min(me.min, minVal); + me.max = me.max === null ? maxVal : Math.max(me.max, maxVal); + }); - } else { - ret = []; - } + } else { + helpers.each(datasets, function(dataset, datasetIndex) { + var meta = chart.getDatasetMeta(datasetIndex); + if (chart.isDatasetVisible(datasetIndex) && IDMatches(meta)) { + helpers.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } - if ( tag === undefined || tag && nodeName( context, tag ) ) { - return jQuery.merge( [ context ], ret ); - } + if (me.min === null) { + me.min = value; + } else if (value < me.min) { + me.min = value; + } - return ret; -} + if (me.max === null) { + me.max = value; + } else if (value > me.max) { + me.max = value; + } + if (value !== 0 && (me.minNotZero === null || value < me.minNotZero)) { + me.minNotZero = value; + } + }); + } + }); + } -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; + me.min = valueOrDefault(tickOpts.min, me.min); + me.max = valueOrDefault(tickOpts.max, me.max); - for ( ; i < l; i++ ) { - dataPriv.set( - elems[ i ], - "globalEval", - !refElements || dataPriv.get( refElements[ i ], "globalEval" ) - ); - } -} + if (me.min === me.max) { + if (me.min !== 0 && me.min !== null) { + me.min = Math.pow(10, Math.floor(helpers.log10(me.min)) - 1); + me.max = Math.pow(10, Math.floor(helpers.log10(me.max)) + 1); + } else { + me.min = 1; + me.max = 10; + } + } + }, + buildTicks: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + + var generationOptions = { + min: tickOpts.min, + max: tickOpts.max + }; + var ticks = me.ticks = Ticks.generators.logarithmic(generationOptions, me); + if (!me.isHorizontal()) { + // We are in a vertical orientation. The top value is the highest. So reverse the array + ticks.reverse(); + } -var rhtml = /<|&#?\w+;/; + // At this point, we need to update our max and min given the tick values since we have expanded the + // range of the scale + me.max = helpers.max(ticks); + me.min = helpers.min(ticks); -function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; + if (tickOpts.reverse) { + ticks.reverse(); - for ( ; i < l; i++ ) { - elem = elems[ i ]; + me.start = me.max; + me.end = me.min; + } else { + me.start = me.min; + me.end = me.max; + } + }, + convertTicksToLabels: function() { + this.tickValues = this.ticks.slice(); - if ( elem || elem === 0 ) { + Chart.Scale.prototype.convertTicksToLabels.call(this); + }, + // Get the correct tooltip label + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + getPixelForTick: function(index) { + return this.getPixelForValue(this.tickValues[index]); + }, + getPixelForValue: function(value) { + var me = this; + var start = me.start; + var newVal = +me.getRightValue(value); + var opts = me.options; + var tickOpts = opts.ticks; + var innerDimension, pixel, range; + + if (me.isHorizontal()) { + range = helpers.log10(me.end) - helpers.log10(start); // todo: if start === 0 + if (newVal === 0) { + pixel = me.left; + } else { + innerDimension = me.width; + pixel = me.left + (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); + } + } else { + // Bottom - top since pixels increase downward on a screen + innerDimension = me.height; + if (start === 0 && !tickOpts.reverse) { + range = helpers.log10(me.end) - helpers.log10(me.minNotZero); + if (newVal === start) { + pixel = me.bottom; + } else if (newVal === me.minNotZero) { + pixel = me.bottom - innerDimension * 0.02; + } else { + pixel = me.bottom - innerDimension * 0.02 - (innerDimension * 0.98 / range * (helpers.log10(newVal) - helpers.log10(me.minNotZero))); + } + } else if (me.end === 0 && tickOpts.reverse) { + range = helpers.log10(me.start) - helpers.log10(me.minNotZero); + if (newVal === me.end) { + pixel = me.top; + } else if (newVal === me.minNotZero) { + pixel = me.top + innerDimension * 0.02; + } else { + pixel = me.top + innerDimension * 0.02 + (innerDimension * 0.98 / range * (helpers.log10(newVal) - helpers.log10(me.minNotZero))); + } + } else if (newVal === 0) { + pixel = tickOpts.reverse ? me.top : me.bottom; + } else { + range = helpers.log10(me.end) - helpers.log10(start); + innerDimension = me.height; + pixel = me.bottom - (innerDimension / range * (helpers.log10(newVal) - helpers.log10(start))); + } + } + return pixel; + }, + getValueForPixel: function(pixel) { + var me = this; + var range = helpers.log10(me.end) - helpers.log10(me.start); + var value, innerDimension; + + if (me.isHorizontal()) { + innerDimension = me.width; + value = me.start * Math.pow(10, (pixel - me.left) * range / innerDimension); + } else { // todo: if start === 0 + innerDimension = me.height; + value = Math.pow(10, (me.bottom - pixel) * range / innerDimension) / me.start; + } + return value; + } + }); + Chart.scaleService.registerScaleType('logarithmic', LogarithmicScale, defaultConfig); - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { +}; + })(); +}); - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); +require.register("chart.js/src/scales/scale.radialLinear.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + 'use strict'; - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); +var defaults = require('../core/core.defaults'); +var helpers = require('../helpers/index'); +var Ticks = require('../core/core.ticks'); - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); +module.exports = function(Chart) { - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + var globalDefaults = defaults.global; - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } + var defaultConfig = { + display: true, - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); + // Boolean - Whether to animate scaling the chart from the centre + animate: true, + position: 'chartArea', - // Remember the top-level container - tmp = fragment.firstChild; + angleLines: { + display: true, + color: 'rgba(0, 0, 0, 0.1)', + lineWidth: 1 + }, - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } + gridLines: { + circular: false + }, - // Remove wrapper from fragment - fragment.textContent = ""; + // label settings + ticks: { + // Boolean - Show a backdrop to the scale label + showLabelBackdrop: true, - i = 0; - while ( ( elem = nodes[ i++ ] ) ) { + // String - The colour of the label backdrop + backdropColor: 'rgba(255,255,255,0.75)', - // Skip elements already in the context collection (trac-4087) - if ( selection && jQuery.inArray( elem, selection ) > -1 ) { - if ( ignored ) { - ignored.push( elem ); - } - continue; - } + // Number - The backdrop padding above & below the label in pixels + backdropPaddingY: 2, - contains = jQuery.contains( elem.ownerDocument, elem ); + // Number - The backdrop padding to the side of the label in pixels + backdropPaddingX: 2, - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); + callback: Ticks.formatters.linear + }, - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } + pointLabels: { + // Boolean - if true, show point labels + display: true, - // Capture executables - if ( scripts ) { - j = 0; - while ( ( elem = tmp[ j++ ] ) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } + // Number - Point label font size in pixels + fontSize: 10, + + // Function - Used to convert point labels + callback: function(label) { + return label; } } + }; + + function getValueCount(scale) { + var opts = scale.options; + return opts.angleLines.display || opts.pointLabels.display ? scale.chart.data.labels.length : 0; } - return fragment; -} + function getPointLabelFontOptions(scale) { + var pointLabelOptions = scale.options.pointLabels; + var fontSize = helpers.valueOrDefault(pointLabelOptions.fontSize, globalDefaults.defaultFontSize); + var fontStyle = helpers.valueOrDefault(pointLabelOptions.fontStyle, globalDefaults.defaultFontStyle); + var fontFamily = helpers.valueOrDefault(pointLabelOptions.fontFamily, globalDefaults.defaultFontFamily); + var font = helpers.fontString(fontSize, fontStyle, fontFamily); + return { + size: fontSize, + style: fontStyle, + family: fontFamily, + font: font + }; + } -( function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); + function measureLabelSize(ctx, fontSize, label) { + if (helpers.isArray(label)) { + return { + w: helpers.longestText(ctx, ctx.font, label), + h: (label.length * fontSize) + ((label.length - 1) * 1.5 * fontSize) + }; + } - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); + return { + w: ctx.measureText(label).width, + h: fontSize + }; + } - div.appendChild( input ); + function determineLimits(angle, pos, size, min, max) { + if (angle === min || angle === max) { + return { + start: pos - (size / 2), + end: pos + (size / 2) + }; + } else if (angle < min || angle > max) { + return { + start: pos - size - 5, + end: pos + }; + } - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + return { + start: pos, + end: pos + size + 5 + }; + } - // Support: IE <=11 only - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -} )(); -var documentElement = document.documentElement; + /** + * Helper function to fit a radial linear scale with point labels + */ + function fitWithPointLabels(scale) { + /* + * Right, this is really confusing and there is a lot of maths going on here + * The gist of the problem is here: https://gist.github.com/nnnick/696cc9c55f4b0beb8fe9 + * + * Reaction: https://dl.dropboxusercontent.com/u/34601363/toomuchscience.gif + * + * Solution: + * + * We assume the radius of the polygon is half the size of the canvas at first + * at each index we check if the text overlaps. + * + * Where it does, we store that angle and that index. + * + * After finding the largest index and angle we calculate how much we need to remove + * from the shape radius to move the point inwards by that x. + * + * We average the left and right distances to get the maximum shape radius that can fit in the box + * along with labels. + * + * Once we have that, we can find the centre point for the chart, by taking the x text protrusion + * on each side, removing that from the size, halving it and adding the left x protrusion width. + * + * This will mean we have a shape fitted to the canvas, as large as it can be with the labels + * and position it in the most space efficient manner + * + * https://dl.dropboxusercontent.com/u/34601363/yeahscience.gif + */ + + var plFont = getPointLabelFontOptions(scale); + + // Get maximum radius of the polygon. Either half the height (minus the text width) or half the width. + // Use this to calculate the offset + change. - Make sure L/R protrusion is at least 0 to stop issues with centre points + var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); + var furthestLimits = { + r: scale.width, + l: 0, + t: scale.height, + b: 0 + }; + var furthestAngles = {}; + var i, textSize, pointPosition; + scale.ctx.font = plFont.font; + scale._pointLabelSizes = []; + var valueCount = getValueCount(scale); + for (i = 0; i < valueCount; i++) { + pointPosition = scale.getPointPosition(i, largestPossibleRadius); + textSize = measureLabelSize(scale.ctx, plFont.size, scale.pointLabels[i] || ''); + scale._pointLabelSizes[i] = textSize; -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + // Add quarter circle to make degree 0 mean top of circle + var angleRadians = scale.getIndexAngle(i); + var angle = helpers.toDegrees(angleRadians) % 360; + var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180); + var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270); -function returnTrue() { - return true; -} + if (hLimits.start < furthestLimits.l) { + furthestLimits.l = hLimits.start; + furthestAngles.l = angleRadians; + } -function returnFalse() { - return false; -} + if (hLimits.end > furthestLimits.r) { + furthestLimits.r = hLimits.end; + furthestAngles.r = angleRadians; + } -// Support: IE <=9 only -// See #13393 for more info -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} + if (vLimits.start < furthestLimits.t) { + furthestLimits.t = vLimits.start; + furthestAngles.t = angleRadians; + } -function on( elem, types, selector, data, fn, one ) { - var origFn, type; + if (vLimits.end > furthestLimits.b) { + furthestLimits.b = vLimits.end; + furthestAngles.b = angleRadians; + } + } - // Types can be a map of types/handlers - if ( typeof types === "object" ) { + scale.setReductions(largestPossibleRadius, furthestLimits, furthestAngles); + } - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { + /** + * Helper function to fit a radial linear scale with no point labels + */ + function fit(scale) { + var largestPossibleRadius = Math.min(scale.height / 2, scale.width / 2); + scale.drawingArea = Math.round(largestPossibleRadius); + scale.setCenterPoint(0, 0, 0, 0); + } - // ( types-Object, data ) - data = data || selector; - selector = undefined; + function getTextAlignForAngle(angle) { + if (angle === 0 || angle === 180) { + return 'center'; + } else if (angle < 180) { + return 'left'; } - for ( type in types ) { - on( elem, type, selector, data, types[ type ], one ); + + return 'right'; + } + + function fillText(ctx, text, position, fontSize) { + if (helpers.isArray(text)) { + var y = position.y; + var spacing = 1.5 * fontSize; + + for (var i = 0; i < text.length; ++i) { + ctx.fillText(text[i], position.x, y); + y += spacing; + } + } else { + ctx.fillText(text, position.x, position.y); } - return elem; } - if ( data == null && fn == null ) { + function adjustPointPositionForLabelHeight(angle, textSize, position) { + if (angle === 90 || angle === 270) { + position.y -= (textSize.h / 2); + } else if (angle > 270 || angle < 90) { + position.y -= textSize.h; + } + } - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return elem; - } + function drawPointLabels(scale) { + var ctx = scale.ctx; + var valueOrDefault = helpers.valueOrDefault; + var opts = scale.options; + var angleLineOpts = opts.angleLines; + var pointLabelOpts = opts.pointLabels; - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { + ctx.lineWidth = angleLineOpts.lineWidth; + ctx.strokeStyle = angleLineOpts.color; - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; + var outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max); - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return elem.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - } ); -} + // Point Label Font + var plFont = getPointLabelFontOptions(scale); -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { + ctx.textBaseline = 'top'; - global: {}, + for (var i = getValueCount(scale) - 1; i >= 0; i--) { + if (angleLineOpts.display) { + var outerPosition = scale.getPointPosition(i, outerDistance); + ctx.beginPath(); + ctx.moveTo(scale.xCenter, scale.yCenter); + ctx.lineTo(outerPosition.x, outerPosition.y); + ctx.stroke(); + ctx.closePath(); + } - add: function( elem, types, handler, data, selector ) { + if (pointLabelOpts.display) { + // Extra 3px out for some label spacing + var pointLabelPosition = scale.getPointPosition(i, outerDistance + 5); - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.get( elem ); + // Keep this in loop since we may support array properties here + var pointLabelFontColor = valueOrDefault(pointLabelOpts.fontColor, globalDefaults.defaultFontColor); + ctx.font = plFont.font; + ctx.fillStyle = pointLabelFontColor; - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; + var angleRadians = scale.getIndexAngle(i); + var angle = helpers.toDegrees(angleRadians); + ctx.textAlign = getTextAlignForAngle(angle); + adjustPointPositionForLabelHeight(angle, scale._pointLabelSizes[i], pointLabelPosition); + fillText(ctx, scale.pointLabels[i] || '', pointLabelPosition, plFont.size); + } } + } - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } + function drawRadiusLine(scale, gridLineOpts, radius, index) { + var ctx = scale.ctx; + ctx.strokeStyle = helpers.valueAtIndexOrDefault(gridLineOpts.color, index - 1); + ctx.lineWidth = helpers.valueAtIndexOrDefault(gridLineOpts.lineWidth, index - 1); - // Ensure that invalid selectors throw exceptions at attach time - // Evaluate against documentElement in case elem is a non-element node (e.g., document) - if ( selector ) { - jQuery.find.matchesSelector( documentElement, selector ); - } + if (scale.options.gridLines.circular) { + // Draw circular arcs between the points + ctx.beginPath(); + ctx.arc(scale.xCenter, scale.yCenter, radius, 0, Math.PI * 2); + ctx.closePath(); + ctx.stroke(); + } else { + // Draw straight lines connecting each index + var valueCount = getValueCount(scale); - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } + if (valueCount === 0) { + return; + } - // Init the element's event structure and main handler, if this is the first - if ( !( events = elemData.events ) ) { - events = elemData.events = {}; - } - if ( !( eventHandle = elemData.handle ) ) { - eventHandle = elemData.handle = function( e ) { + ctx.beginPath(); + var pointPosition = scale.getPointPosition(0, radius); + ctx.moveTo(pointPosition.x, pointPosition.y); - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; + for (var i = 1; i < valueCount; i++) { + pointPosition = scale.getPointPosition(i, radius); + ctx.lineTo(pointPosition.x, pointPosition.y); + } + + ctx.closePath(); + ctx.stroke(); } + } - // Handle multiple events separated by a space - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + function numberOrZero(param) { + return helpers.isNumber(param) ? param : 0; + } - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } + var LinearRadialScale = Chart.LinearScaleBase.extend({ + setDimensions: function() { + var me = this; + var opts = me.options; + var tickOpts = opts.ticks; + // Set the unconstrained dimension before label rotation + me.width = me.maxWidth; + me.height = me.maxHeight; + me.xCenter = Math.round(me.width / 2); + me.yCenter = Math.round(me.height / 2); + + var minSize = helpers.min([me.height, me.width]); + var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); + me.drawingArea = opts.display ? (minSize / 2) - (tickFontSize / 2 + tickOpts.backdropPaddingY) : (minSize / 2); + }, + determineDataLimits: function() { + var me = this; + var chart = me.chart; + var min = Number.POSITIVE_INFINITY; + var max = Number.NEGATIVE_INFINITY; + + helpers.each(chart.data.datasets, function(dataset, datasetIndex) { + if (chart.isDatasetVisible(datasetIndex)) { + var meta = chart.getDatasetMeta(datasetIndex); + + helpers.each(dataset.data, function(rawValue, index) { + var value = +me.getRightValue(rawValue); + if (isNaN(value) || meta.data[index].hidden) { + return; + } - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; + min = Math.min(value, min); + max = Math.max(value, max); + }); + } + }); - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; + me.min = (min === Number.POSITIVE_INFINITY ? 0 : min); + me.max = (max === Number.NEGATIVE_INFINITY ? 0 : max); - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; + // Common base implementation to handle ticks.min, ticks.max, ticks.beginAtZero + me.handleTickRangeOptions(); + }, + getTickLimit: function() { + var tickOpts = this.options.ticks; + var tickFontSize = helpers.valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); + return Math.min(tickOpts.maxTicksLimit ? tickOpts.maxTicksLimit : 11, Math.ceil(this.drawingArea / (1.5 * tickFontSize))); + }, + convertTicksToLabels: function() { + var me = this; - // handleObj is passed to all event handlers - handleObj = jQuery.extend( { - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join( "." ) - }, handleObjIn ); + Chart.LinearScaleBase.prototype.convertTicksToLabels.call(me); - // Init the event handler queue if we're the first - if ( !( handlers = events[ type ] ) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; + // Point labels + me.pointLabels = me.chart.data.labels.map(me.options.pointLabels.callback, me); + }, + getLabelForIndex: function(index, datasetIndex) { + return +this.getRightValue(this.chart.data.datasets[datasetIndex].data[index]); + }, + fit: function() { + if (this.options.pointLabels.display) { + fitWithPointLabels(this); + } else { + fit(this); + } + }, + /** + * Set radius reductions and determine new radius and center point + * @private + */ + setReductions: function(largestPossibleRadius, furthestLimits, furthestAngles) { + var me = this; + var radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l); + var radiusReductionRight = Math.max(furthestLimits.r - me.width, 0) / Math.sin(furthestAngles.r); + var radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t); + var radiusReductionBottom = -Math.max(furthestLimits.b - me.height, 0) / Math.cos(furthestAngles.b); + + radiusReductionLeft = numberOrZero(radiusReductionLeft); + radiusReductionRight = numberOrZero(radiusReductionRight); + radiusReductionTop = numberOrZero(radiusReductionTop); + radiusReductionBottom = numberOrZero(radiusReductionBottom); + + me.drawingArea = Math.min( + Math.round(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2), + Math.round(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)); + me.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom); + }, + setCenterPoint: function(leftMovement, rightMovement, topMovement, bottomMovement) { + var me = this; + var maxRight = me.width - rightMovement - me.drawingArea; + var maxLeft = leftMovement + me.drawingArea; + var maxTop = topMovement + me.drawingArea; + var maxBottom = me.height - bottomMovement - me.drawingArea; + + me.xCenter = Math.round(((maxLeft + maxRight) / 2) + me.left); + me.yCenter = Math.round(((maxTop + maxBottom) / 2) + me.top); + }, - // Only use addEventListener if the special events handler returns false - if ( !special.setup || - special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + getIndexAngle: function(index) { + var angleMultiplier = (Math.PI * 2) / getValueCount(this); + var startAngle = this.chart.options && this.chart.options.startAngle ? + this.chart.options.startAngle : + 0; - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle ); - } - } - } + var startAngleRadians = startAngle * Math.PI * 2 / 360; - if ( special.add ) { - special.add.call( elem, handleObj ); + // Start from the top instead of right, so remove a quarter of the circle + return index * angleMultiplier + startAngleRadians; + }, + getDistanceFromCenterForValue: function(value) { + var me = this; - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } + if (value === null) { + return 0; // null always in center } - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); + // Take into account half font size + the yPadding of the top value + var scalingFactor = me.drawingArea / (me.max - me.min); + if (me.options.ticks.reverse) { + return (me.max - value) * scalingFactor; } + return (value - me.min) * scalingFactor; + }, + getPointPosition: function(index, distanceFromCenter) { + var me = this; + var thisAngle = me.getIndexAngle(index) - (Math.PI / 2); + return { + x: Math.round(Math.cos(thisAngle) * distanceFromCenter) + me.xCenter, + y: Math.round(Math.sin(thisAngle) * distanceFromCenter) + me.yCenter + }; + }, + getPointPositionForValue: function(index, value) { + return this.getPointPosition(index, this.getDistanceFromCenterForValue(value)); + }, - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } + getBasePosition: function() { + var me = this; + var min = me.min; + var max = me.max; - }, + return me.getPointPositionForValue(0, + me.beginAtZero ? 0 : + min < 0 && max < 0 ? max : + min > 0 && max > 0 ? min : + 0); + }, - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { + draw: function() { + var me = this; + var opts = me.options; + var gridLineOpts = opts.gridLines; + var tickOpts = opts.ticks; + var valueOrDefault = helpers.valueOrDefault; - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + if (opts.display) { + var ctx = me.ctx; + var startAngle = this.getIndexAngle(0); - if ( !elemData || !( events = elemData.events ) ) { - return; - } + // Tick Font + var tickFontSize = valueOrDefault(tickOpts.fontSize, globalDefaults.defaultFontSize); + var tickFontStyle = valueOrDefault(tickOpts.fontStyle, globalDefaults.defaultFontStyle); + var tickFontFamily = valueOrDefault(tickOpts.fontFamily, globalDefaults.defaultFontFamily); + var tickLabelFont = helpers.fontString(tickFontSize, tickFontStyle, tickFontFamily); - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[ t ] ) || []; - type = origType = tmp[ 1 ]; - namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + helpers.each(me.ticks, function(label, index) { + // Don't draw a centre value (if it is minimum) + if (index > 0 || tickOpts.reverse) { + var yCenterOffset = me.getDistanceFromCenterForValue(me.ticksAsNumbers[index]); - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } + // Draw circular lines around the scale + if (gridLineOpts.display && index !== 0) { + drawRadiusLine(me, gridLineOpts, yCenterOffset, index); + } - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[ 2 ] && - new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + if (tickOpts.display) { + var tickFontColor = valueOrDefault(tickOpts.fontColor, globalDefaults.defaultFontColor); + ctx.font = tickLabelFont; - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; + ctx.save(); + ctx.translate(me.xCenter, me.yCenter); + ctx.rotate(startAngle); - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || - selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); + if (tickOpts.showLabelBackdrop) { + var labelWidth = ctx.measureText(label).width; + ctx.fillStyle = tickOpts.backdropColor; + ctx.fillRect( + -labelWidth / 2 - tickOpts.backdropPaddingX, + -yCenterOffset - tickFontSize / 2 - tickOpts.backdropPaddingY, + labelWidth + tickOpts.backdropPaddingX * 2, + tickFontSize + tickOpts.backdropPaddingY * 2 + ); + } - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = tickFontColor; + ctx.fillText(label, 0, -yCenterOffset); + ctx.restore(); + } } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || - special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + }); - jQuery.removeEvent( elem, type, elemData.handle ); + if (opts.angleLines.display || opts.pointLabels.display) { + drawPointLabels(me); } - - delete events[ type ]; } } + }); + Chart.scaleService.registerScaleType('radialLinear', LinearRadialScale, defaultConfig); - // Remove data and the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - dataPriv.remove( elem, "handle events" ); - } - }, +}; + })(); +}); - dispatch: function( nativeEvent ) { +require.register("chart.js/src/scales/scale.time.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chart.js"); + (function() { + /* global window: false */ +'use strict'; - // Make a writable jQuery.Event from the native event object - var event = jQuery.event.fix( nativeEvent ); +var moment = require('moment'); +moment = typeof moment === 'function' ? moment : window.moment; - var i, j, ret, matched, handleObj, handlerQueue, - args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; +var defaults = require('../core/core.defaults'); +var helpers = require('../helpers/index'); - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[ 0 ] = event; +// Integer constants are from the ES6 spec. +var MIN_INTEGER = Number.MIN_SAFE_INTEGER || -9007199254740991; +var MAX_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; - for ( i = 1; i < arguments.length; i++ ) { - args[ i ] = arguments[ i ]; - } +var INTERVALS = { + millisecond: { + major: true, + size: 1, + steps: [1, 2, 5, 10, 20, 50, 100, 250, 500] + }, + second: { + major: true, + size: 1000, + steps: [1, 2, 5, 10, 30] + }, + minute: { + major: true, + size: 60000, + steps: [1, 2, 5, 10, 30] + }, + hour: { + major: true, + size: 3600000, + steps: [1, 2, 3, 6, 12] + }, + day: { + major: true, + size: 86400000, + steps: [1, 2, 5] + }, + week: { + major: false, + size: 604800000, + steps: [1, 2, 3, 4] + }, + month: { + major: true, + size: 2.628e9, + steps: [1, 2, 3] + }, + quarter: { + major: false, + size: 7.884e9, + steps: [1, 2, 3, 4] + }, + year: { + major: true, + size: 3.154e10 + } +}; - event.delegateTarget = this; +var UNITS = Object.keys(INTERVALS); - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; +function sorter(a, b) { + return a - b; +} + +function arrayUnique(items) { + var hash = {}; + var out = []; + var i, ilen, item; + + for (i = 0, ilen = items.length; i < ilen; ++i) { + item = items[i]; + if (!hash[item]) { + hash[item] = true; + out.push(item); } + } - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + return out; +} - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; +/** + * Returns an array of {time, pos} objects used to interpolate a specific `time` or position + * (`pos`) on the scale, by searching entries before and after the requested value. `pos` is + * a decimal between 0 and 1: 0 being the start of the scale (left or top) and 1 the other + * extremity (left + width or top + height). Note that it would be more optimized to directly + * store pre-computed pixels, but the scale dimensions are not guaranteed at the time we need + * to create the lookup table. The table ALWAYS contains at least two items: min and max. + * + * @param {Number[]} timestamps - timestamps sorted from lowest to highest. + * @param {String} distribution - If 'linear', timestamps will be spread linearly along the min + * and max range, so basically, the table will contains only two items: {min, 0} and {max, 1}. + * If 'series', timestamps will be positioned at the same distance from each other. In this + * case, only timestamps that break the time linearity are registered, meaning that in the + * best case, all timestamps are linear, the table contains only min and max. + */ +function buildLookupTable(timestamps, min, max, distribution) { + if (distribution === 'linear' || !timestamps.length) { + return [ + {time: min, pos: 0}, + {time: max, pos: 1} + ]; + } - j = 0; - while ( ( handleObj = matched.handlers[ j++ ] ) && - !event.isImmediatePropagationStopped() ) { + var table = []; + var items = [min]; + var i, ilen, prev, curr, next; - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + for (i = 0, ilen = timestamps.length; i < ilen; ++i) { + curr = timestamps[i]; + if (curr > min && curr < max) { + items.push(curr); + } + } - event.handleObj = handleObj; - event.data = handleObj.data; + items.push(max); - ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || - handleObj.handler ).apply( matched.elem, args ); + for (i = 0, ilen = items.length; i < ilen; ++i) { + next = items[i + 1]; + prev = items[i - 1]; + curr = items[i]; - if ( ret !== undefined ) { - if ( ( event.result = ret ) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } + // only add points that breaks the scale linearity + if (prev === undefined || next === undefined || Math.round((next + prev) / 2) !== curr) { + table.push({time: curr, pos: i / (ilen - 1)}); } + } - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); + return table; +} + +// @see adapted from http://www.anujgakhar.com/2014/03/01/binary-search-in-javascript/ +function lookup(table, key, value) { + var lo = 0; + var hi = table.length - 1; + var mid, i0, i1; + + while (lo >= 0 && lo <= hi) { + mid = (lo + hi) >> 1; + i0 = table[mid - 1] || null; + i1 = table[mid]; + + if (!i0) { + // given value is outside table (before first item) + return {lo: null, hi: i1}; + } else if (i1[key] < value) { + lo = mid + 1; + } else if (i0[key] > value) { + hi = mid - 1; + } else { + return {lo: i0, hi: i1}; } + } - return event.result; - }, + // given value is outside table (after last item) + return {lo: i1, hi: null}; +} - handlers: function( event, handlers ) { - var i, handleObj, sel, matchedHandlers, matchedSelectors, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; +/** + * Linearly interpolates the given source `value` using the table items `skey` values and + * returns the associated `tkey` value. For example, interpolate(table, 'time', 42, 'pos') + * returns the position for a timestamp equal to 42. If value is out of bounds, values at + * index [0, 1] or [n - 1, n] are used for the interpolation. + */ +function interpolate(table, skey, sval, tkey) { + var range = lookup(table, skey, sval); - // Find delegate handlers - if ( delegateCount && + // Note: the lookup table ALWAYS contains at least 2 items (min and max) + var prev = !range.lo ? table[0] : !range.hi ? table[table.length - 2] : range.lo; + var next = !range.lo ? table[1] : !range.hi ? table[table.length - 1] : range.hi; - // Support: IE <=9 - // Black-hole SVG instance trees (trac-13180) - cur.nodeType && + var span = next[skey] - prev[skey]; + var ratio = span ? (sval - prev[skey]) / span : 0; + var offset = (next[tkey] - prev[tkey]) * ratio; - // Support: Firefox <=42 - // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) - // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only - // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) - !( event.type === "click" && event.button >= 1 ) ) { + return prev[tkey] + offset; +} - for ( ; cur !== this; cur = cur.parentNode || this ) { +/** + * Convert the given value to a moment object using the given time options. + * @see http://momentjs.com/docs/#/parsing/ + */ +function momentify(value, options) { + var parser = options.parser; + var format = options.parser || options.format; - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { - matchedHandlers = []; - matchedSelectors = {}; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; + if (typeof parser === 'function') { + return parser(value); + } - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; + if (typeof value === 'string' && typeof format === 'string') { + return moment(value, format); + } - if ( matchedSelectors[ sel ] === undefined ) { - matchedSelectors[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) > -1 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matchedSelectors[ sel ] ) { - matchedHandlers.push( handleObj ); - } - } - if ( matchedHandlers.length ) { - handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); - } - } - } - } + if (!(value instanceof moment)) { + value = moment(value); + } - // Add the remaining (directly-bound) handlers - cur = this; - if ( delegateCount < handlers.length ) { - handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); - } + if (value.isValid()) { + return value; + } - return handlerQueue; - }, + // Labels are in an incompatible moment format and no `parser` has been provided. + // The user might still use the deprecated `format` option to convert his inputs. + if (typeof format === 'function') { + return format(value); + } - addProp: function( name, hook ) { - Object.defineProperty( jQuery.Event.prototype, name, { - enumerable: true, - configurable: true, + return value; +} - get: jQuery.isFunction( hook ) ? - function() { - if ( this.originalEvent ) { - return hook( this.originalEvent ); - } - } : - function() { - if ( this.originalEvent ) { - return this.originalEvent[ name ]; - } - }, +function parse(input, scale) { + if (helpers.isNullOrUndef(input)) { + return null; + } - set: function( value ) { - Object.defineProperty( this, name, { - enumerable: true, - configurable: true, - writable: true, - value: value - } ); - } - } ); - }, + var options = scale.options.time; + var value = momentify(scale.getRightValue(input), options); + if (!value.isValid()) { + return null; + } - fix: function( originalEvent ) { - return originalEvent[ jQuery.expando ] ? - originalEvent : - new jQuery.Event( originalEvent ); - }, + if (options.round) { + value.startOf(options.round); + } - special: { - load: { + return value.valueOf(); +} - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { +/** + * Returns the number of unit to skip to be able to display up to `capacity` number of ticks + * in `unit` for the given `min` / `max` range and respecting the interval steps constraints. + */ +function determineStepSize(min, max, unit, capacity) { + var range = max - min; + var interval = INTERVALS[unit]; + var milliseconds = interval.size; + var steps = interval.steps; + var i, ilen, factor; + + if (!steps) { + return Math.ceil(range / ((capacity || 1) * milliseconds)); + } - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { + for (i = 0, ilen = steps.length; i < ilen; ++i) { + factor = steps[i]; + if (Math.ceil(range / (milliseconds * factor)) <= capacity) { + break; + } + } - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, + return factor; +} - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return nodeName( event.target, "a" ); - } - }, +function determineUnit(minUnit, min, max, capacity) { + var ilen = UNITS.length; + var i, interval, factor; - beforeunload: { - postDispatch: function( event ) { + for (i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) { + interval = INTERVALS[UNITS[i]]; + factor = interval.steps ? interval.steps[interval.steps.length - 1] : MAX_INTEGER; - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } + if (Math.ceil((max - min) / (factor * interval.size)) <= capacity) { + return UNITS[i]; } } -}; -jQuery.removeEvent = function( elem, type, handle ) { + return UNITS[ilen - 1]; +} - // This "if" is needed for plain objects - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle ); +function determineMajorUnit(unit) { + for (var i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) { + if (INTERVALS[UNITS[i]].major) { + return UNITS[i]; + } } -}; - -jQuery.Event = function( src, props ) { +} - // Allow instantiation without the 'new' keyword - if ( !( this instanceof jQuery.Event ) ) { - return new jQuery.Event( src, props ); +/** + * Generates a maximum of `capacity` timestamps between min and max, rounded to the + * `minor` unit, aligned on the `major` unit and using the given scale time `options`. + * Important: this method can return ticks outside the min and max range, it's the + * responsibility of the calling code to clamp values if needed. + */ +function generate(min, max, minor, major, capacity, options) { + var timeOpts = options.time; + var stepSize = helpers.valueOrDefault(timeOpts.stepSize, timeOpts.unitStepSize); + var weekday = minor === 'week' ? timeOpts.isoWeekday : false; + var majorTicksEnabled = options.ticks.major.enabled; + var interval = INTERVALS[minor]; + var first = moment(min); + var last = moment(max); + var ticks = []; + var time; + + if (!stepSize) { + stepSize = determineStepSize(min, max, minor, capacity); } - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && + // For 'week' unit, handle the first day of week option + if (weekday) { + first = first.isoWeekday(weekday); + last = last.isoWeekday(weekday); + } - // Support: Android <=2.3 only - src.returnValue === false ? - returnTrue : - returnFalse; + // Align first/last ticks on unit + first = first.startOf(weekday ? 'day' : minor); + last = last.startOf(weekday ? 'day' : minor); - // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; + // Make sure that the last tick include max + if (last < max) { + last.add(1, minor); + } - this.currentTarget = src.currentTarget; - this.relatedTarget = src.relatedTarget; + time = moment(first); - // Event type - } else { - this.type = src; + if (majorTicksEnabled && major && !weekday && !timeOpts.round) { + // Align the first tick on the previous `minor` unit aligned on the `major` unit: + // we first aligned time on the previous `major` unit then add the number of full + // stepSize there is between first and the previous major time. + time.startOf(major); + time.add(~~((first - time) / (interval.size * stepSize)) * stepSize, minor); } - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); + for (; time < last; time.add(stepSize, minor)) { + ticks.push(+time); } - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); + ticks.push(+time); - // Mark it as fixed - this[ jQuery.expando ] = true; -}; + return ticks; +} -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - constructor: jQuery.Event, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - isSimulated: false, +/** + * Returns the right and left offsets from edges in the form of {left, right}. + * Offsets are added when the `offset` option is true. + */ +function computeOffsets(table, ticks, min, max, options) { + var left = 0; + var right = 0; + var upper, lower; + + if (options.offset && ticks.length) { + if (!options.time.min) { + upper = ticks.length > 1 ? ticks[1] : max; + lower = ticks[0]; + left = ( + interpolate(table, 'time', upper, 'pos') - + interpolate(table, 'time', lower, 'pos') + ) / 2; + } + if (!options.time.max) { + upper = ticks[ticks.length - 1]; + lower = ticks.length > 1 ? ticks[ticks.length - 2] : min; + right = ( + interpolate(table, 'time', upper, 'pos') - + interpolate(table, 'time', lower, 'pos') + ) / 2; + } + } - preventDefault: function() { - var e = this.originalEvent; + return {left: left, right: right}; +} - this.isDefaultPrevented = returnTrue; +function ticksFromTimestamps(values, majorUnit) { + var ticks = []; + var i, ilen, value, major; - if ( e && !this.isSimulated ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; + for (i = 0, ilen = values.length; i < ilen; ++i) { + value = values[i]; + major = majorUnit ? value === +moment(value).startOf(majorUnit) : false; - this.isPropagationStopped = returnTrue; + ticks.push({ + value: value, + major: major + }); + } - if ( e && !this.isSimulated ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; + return ticks; +} - this.isImmediatePropagationStopped = returnTrue; +module.exports = function(Chart) { - if ( e && !this.isSimulated ) { - e.stopImmediatePropagation(); + var defaultConfig = { + position: 'bottom', + + /** + * Data distribution along the scale: + * - 'linear': data are spread according to their time (distances can vary), + * - 'series': data are spread at the same distance from each other. + * @see https://github.com/chartjs/Chart.js/pull/4507 + * @since 2.7.0 + */ + distribution: 'linear', + + /** + * Scale boundary strategy (bypassed by min/max time options) + * - `data`: make sure data are fully visible, ticks outside are removed + * - `ticks`: make sure ticks are fully visible, data outside are truncated + * @see https://github.com/chartjs/Chart.js/pull/4556 + * @since 2.7.0 + */ + bounds: 'data', + + time: { + parser: false, // false == a pattern string from http://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment + format: false, // DEPRECATED false == date objects, moment object, callback or a pattern string from http://momentjs.com/docs/#/parsing/string-format/ + unit: false, // false == automatic or override with week, month, year, etc. + round: false, // none, or override with week, month, year, etc. + displayFormat: false, // DEPRECATED + isoWeekday: false, // override week start day - see http://momentjs.com/docs/#/get-set/iso-weekday/ + minUnit: 'millisecond', + + // defaults to unit's corresponding unitFormat below or override using pattern string from http://momentjs.com/docs/#/displaying/format/ + displayFormats: { + millisecond: 'h:mm:ss.SSS a', // 11:20:01.123 AM, + second: 'h:mm:ss a', // 11:20:01 AM + minute: 'h:mm a', // 11:20 AM + hour: 'hA', // 5PM + day: 'MMM D', // Sep 4 + week: 'll', // Week 46, or maybe "[W]WW - YYYY" ? + month: 'MMM YYYY', // Sept 2015 + quarter: '[Q]Q - YYYY', // Q3 + year: 'YYYY' // 2015 + }, + }, + ticks: { + autoSkip: false, + + /** + * Ticks generation input values: + * - 'auto': generates "optimal" ticks based on scale size and time options. + * - 'data': generates ticks from data (including labels from data {t|x|y} objects). + * - 'labels': generates ticks from user given `data.labels` values ONLY. + * @see https://github.com/chartjs/Chart.js/pull/4507 + * @since 2.7.0 + */ + source: 'auto', + + major: { + enabled: false + } } + }; - this.stopPropagation(); - } -}; + var TimeScale = Chart.Scale.extend({ + initialize: function() { + if (!moment) { + throw new Error('Chart.js - Moment.js could not be found! You must include it before Chart.js to use the time scale. Download at https://momentjs.com'); + } -// Includes all common event props including KeyEvent and MouseEvent specific props -jQuery.each( { - altKey: true, - bubbles: true, - cancelable: true, - changedTouches: true, - ctrlKey: true, - detail: true, - eventPhase: true, - metaKey: true, - pageX: true, - pageY: true, - shiftKey: true, - view: true, - "char": true, - charCode: true, - key: true, - keyCode: true, - button: true, - buttons: true, - clientX: true, - clientY: true, - offsetX: true, - offsetY: true, - pointerId: true, - pointerType: true, - screenX: true, - screenY: true, - targetTouches: true, - toElement: true, - touches: true, + this.mergeTicksOptions(); - which: function( event ) { - var button = event.button; + Chart.Scale.prototype.initialize.call(this); + }, - // Add which for key events - if ( event.which == null && rkeyEvent.test( event.type ) ) { - return event.charCode != null ? event.charCode : event.keyCode; - } + update: function() { + var me = this; + var options = me.options; - // Add which for click: 1 === left; 2 === middle; 3 === right - if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { - if ( button & 1 ) { - return 1; + // DEPRECATIONS: output a message only one time per update + if (options.time && options.time.format) { + console.warn('options.time.format is deprecated and replaced by options.time.parser.'); } - if ( button & 2 ) { - return 3; + return Chart.Scale.prototype.update.apply(me, arguments); + }, + + /** + * Allows data to be referenced via 't' attribute + */ + getRightValue: function(rawValue) { + if (rawValue && rawValue.t !== undefined) { + rawValue = rawValue.t; } + return Chart.Scale.prototype.getRightValue.call(this, rawValue); + }, - if ( button & 4 ) { - return 2; + determineDataLimits: function() { + var me = this; + var chart = me.chart; + var timeOpts = me.options.time; + var min = parse(timeOpts.min, me) || MAX_INTEGER; + var max = parse(timeOpts.max, me) || MIN_INTEGER; + var timestamps = []; + var datasets = []; + var labels = []; + var i, j, ilen, jlen, data, timestamp; + + // Convert labels to timestamps + for (i = 0, ilen = chart.data.labels.length; i < ilen; ++i) { + labels.push(parse(chart.data.labels[i], me)); + } + + // Convert data to timestamps + for (i = 0, ilen = (chart.data.datasets || []).length; i < ilen; ++i) { + if (chart.isDatasetVisible(i)) { + data = chart.data.datasets[i].data; + + // Let's consider that all data have the same format. + if (helpers.isObject(data[0])) { + datasets[i] = []; + + for (j = 0, jlen = data.length; j < jlen; ++j) { + timestamp = parse(data[j], me); + timestamps.push(timestamp); + datasets[i][j] = timestamp; + } + } else { + timestamps.push.apply(timestamps, labels); + datasets[i] = labels.slice(0); + } + } else { + datasets[i] = []; + } } - return 0; - } + if (labels.length) { + // Sort labels **after** data have been converted + labels = arrayUnique(labels).sort(sorter); + min = Math.min(min, labels[0]); + max = Math.max(max, labels[labels.length - 1]); + } - return event.which; - } -}, jQuery.event.addProp ); + if (timestamps.length) { + timestamps = arrayUnique(timestamps).sort(sorter); + min = Math.min(min, timestamps[0]); + max = Math.max(max, timestamps[timestamps.length - 1]); + } -// Create mouseenter/leave events using mouseover/out and event-time checks -// so that event delegation works in jQuery. -// Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). -jQuery.each( { - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, + // In case there is no valid min/max, let's use today limits + min = min === MAX_INTEGER ? +moment().startOf('day') : min; + max = max === MIN_INTEGER ? +moment().endOf('day') + 1 : max; - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; + // Make sure that max is strictly higher than min (required by the lookup table) + me.min = Math.min(min, max); + me.max = Math.max(min + 1, max); - // For mouseenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -} ); + // PRIVATE + me._horizontal = me.isHorizontal(); + me._table = []; + me._timestamps = { + data: timestamps, + datasets: datasets, + labels: labels + }; + }, -jQuery.fn.extend( { + buildTicks: function() { + var me = this; + var min = me.min; + var max = me.max; + var options = me.options; + var timeOpts = options.time; + var formats = timeOpts.displayFormats; + var capacity = me.getLabelCapacity(min); + var unit = timeOpts.unit || determineUnit(timeOpts.minUnit, min, max, capacity); + var majorUnit = determineMajorUnit(unit); + var timestamps = []; + var ticks = []; + var i, ilen, timestamp; + + switch (options.ticks.source) { + case 'data': + timestamps = me._timestamps.data; + break; + case 'labels': + timestamps = me._timestamps.labels; + break; + case 'auto': + default: + timestamps = generate(min, max, unit, majorUnit, capacity, options); + } - on: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn ); - }, - one: function( types, selector, data, fn ) { - return on( this, types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { + if (options.bounds === 'ticks' && timestamps.length) { + min = timestamps[0]; + max = timestamps[timestamps.length - 1]; + } - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? - handleObj.origType + "." + handleObj.namespace : - handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { + // Enforce limits with user min/max options + min = parse(timeOpts.min, me) || min; + max = parse(timeOpts.max, me) || max; - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); + // Remove ticks outside the min/max range + for (i = 0, ilen = timestamps.length; i < ilen; ++i) { + timestamp = timestamps[i]; + if (timestamp >= min && timestamp <= max) { + ticks.push(timestamp); + } } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each( function() { - jQuery.event.remove( this, types, fn, selector ); - } ); - } -} ); + me.min = min; + me.max = max; + // PRIVATE + me._unit = unit; + me._majorUnit = majorUnit; + me._minorFormat = formats[unit]; + me._majorFormat = formats[majorUnit]; + me._table = buildLookupTable(me._timestamps.data, min, max, options.distribution); + me._offsets = computeOffsets(me._table, ticks, min, max, options); -var + return ticksFromTimestamps(ticks, majorUnit); + }, - /* eslint-disable max-len */ + getLabelForIndex: function(index, datasetIndex) { + var me = this; + var data = me.chart.data; + var timeOpts = me.options.time; + var label = data.labels && index < data.labels.length ? data.labels[index] : ''; + var value = data.datasets[datasetIndex].data[index]; - // See https://github.com/eslint/eslint/issues/3229 - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + if (helpers.isObject(value)) { + label = me.getRightValue(value); + } + if (timeOpts.tooltipFormat) { + label = momentify(label, timeOpts).format(timeOpts.tooltipFormat); + } - /* eslint-enable */ + return label; + }, - // Support: IE <=10 - 11, Edge 12 - 13 - // In IE/Edge using regex groups here causes severe slowdowns. - // See https://connect.microsoft.com/IE/feedback/details/1736512/ - rnoInnerhtml = /\s*$/g; + convertTicksToLabels: function(ticks) { + var labels = []; + var i, ilen; -// Prefer a tbody over its parent table for containing new rows -function manipulationTarget( elem, content ) { - if ( nodeName( elem, "table" ) && - nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + for (i = 0, ilen = ticks.length; i < ilen; ++i) { + labels.push(this.tickFormatFunction(moment(ticks[i].value), i, ticks)); + } - return jQuery( ">tbody", elem )[ 0 ] || elem; - } + return labels; + }, - return elem; -} + /** + * @private + */ + getPixelForOffset: function(time) { + var me = this; + var size = me._horizontal ? me.width : me.height; + var start = me._horizontal ? me.left : me.top; + var pos = interpolate(me._table, 'time', time, 'pos'); -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); + return start + size * (me._offsets.left + pos) / (me._offsets.left + 1 + me._offsets.right); + }, - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute( "type" ); - } + getPixelForValue: function(value, index, datasetIndex) { + var me = this; + var time = null; - return elem; -} + if (index !== undefined && datasetIndex !== undefined) { + time = me._timestamps.datasets[datasetIndex][index]; + } -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + if (time === null) { + time = parse(value, me); + } - if ( dest.nodeType !== 1 ) { - return; - } + if (time !== null) { + return me.getPixelForOffset(time); + } + }, - // 1. Copy private data: events, handlers, etc. - if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); - events = pdataOld.events; + getPixelForTick: function(index) { + var ticks = this.getTicks(); + return index >= 0 && index < ticks.length ? + this.getPixelForOffset(ticks[index].value) : + null; + }, - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; + getValueForPixel: function(pixel) { + var me = this; + var size = me._horizontal ? me.width : me.height; + var start = me._horizontal ? me.left : me.top; + var pos = (size ? (pixel - start) / size : 0) * (me._offsets.left + 1 + me._offsets.left) - me._offsets.right; + var time = interpolate(me._table, 'pos', pos, 'time'); - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } + return moment(time); + }, + + /** + * Crude approximation of what the label width might be + * @private + */ + getLabelWidth: function(label) { + var me = this; + var ticksOpts = me.options.ticks; + var tickLabelWidth = me.ctx.measureText(label).width; + var angle = helpers.toRadians(ticksOpts.maxRotation); + var cosRotation = Math.cos(angle); + var sinRotation = Math.sin(angle); + var tickFontSize = helpers.valueOrDefault(ticksOpts.fontSize, defaults.global.defaultFontSize); + + return (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation); + }, + + /** + * @private + */ + getLabelCapacity: function(exampleTime) { + var me = this; + + me._minorFormat = me.options.time.displayFormats.millisecond; // Pick the longest format for guestimation + + var exampleLabel = me.tickFormatFunction(moment(exampleTime), 0, []); + var tickLabelWidth = me.getLabelWidth(exampleLabel); + var innerWidth = me.isHorizontal() ? me.width : me.height; + + return Math.floor(innerWidth / tickLabelWidth); } - } + }); - // 2. Copy user data - if ( dataUser.hasData( src ) ) { - udataOld = dataUser.access( src ); - udataCur = jQuery.extend( {}, udataOld ); + Chart.scaleService.registerScaleType('time', TimeScale, defaultConfig); +}; + })(); +}); - dataUser.set( dest, udataCur ); - } +require.register("chartjs-color-string/color-string.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chartjs-color-string"); + (function() { + /* MIT license */ +var colorNames = require('color-name'); + +module.exports = { + getRgba: getRgba, + getHsla: getHsla, + getRgb: getRgb, + getHsl: getHsl, + getHwb: getHwb, + getAlpha: getAlpha, + + hexString: hexString, + rgbString: rgbString, + rgbaString: rgbaString, + percentString: percentString, + percentaString: percentaString, + hslString: hslString, + hslaString: hslaString, + hwbString: hwbString, + keyword: keyword } -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; +function getRgba(string) { + if (!string) { + return; + } + var abbr = /^#([a-fA-F0-9]{3})$/i, + hex = /^#([a-fA-F0-9]{6})$/i, + rgba = /^rgba?\(\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*,\s*([+-]?\d+)\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + per = /^rgba?\(\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*,\s*([+-]?[\d\.]+)\%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)$/i, + keyword = /(\w+)/; + + var rgb = [0, 0, 0], + a = 1, + match = string.match(abbr); + if (match) { + match = match[1]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i] + match[i], 16); + } + } + else if (match = string.match(hex)) { + match = match[1]; + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match.slice(i * 2, i * 2 + 2), 16); + } + } + else if (match = string.match(rgba)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = parseInt(match[i + 1]); + } + a = parseFloat(match[4]); + } + else if (match = string.match(per)) { + for (var i = 0; i < rgb.length; i++) { + rgb[i] = Math.round(parseFloat(match[i + 1]) * 2.55); + } + a = parseFloat(match[4]); + } + else if (match = string.match(keyword)) { + if (match[1] == "transparent") { + return [0, 0, 0, 0]; + } + rgb = colorNames[match[1]]; + if (!rgb) { + return; + } + } + + for (var i = 0; i < rgb.length; i++) { + rgb[i] = scale(rgb[i], 0, 255); + } + if (!a && a != 0) { + a = 1; + } + else { + a = scale(a, 0, 1); + } + rgb[3] = a; + return rgb; +} - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } +function getHsla(string) { + if (!string) { + return; + } + var hsl = /^hsla?\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hsl); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + s = scale(parseFloat(match[2]), 0, 100), + l = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, s, l, a]; + } } -function domManip( collection, args, callback, ignored ) { +function getHwb(string) { + if (!string) { + return; + } + var hwb = /^hwb\(\s*([+-]?\d+)(?:deg)?\s*,\s*([+-]?[\d\.]+)%\s*,\s*([+-]?[\d\.]+)%\s*(?:,\s*([+-]?[\d\.]+)\s*)?\)/; + var match = string.match(hwb); + if (match) { + var alpha = parseFloat(match[4]); + var h = scale(parseInt(match[1]), 0, 360), + w = scale(parseFloat(match[2]), 0, 100), + b = scale(parseFloat(match[3]), 0, 100), + a = scale(isNaN(alpha) ? 1 : alpha, 0, 1); + return [h, w, b, a]; + } +} - // Flatten any nested arrays - args = concat.apply( [], args ); +function getRgb(string) { + var rgba = getRgba(string); + return rgba && rgba.slice(0, 3); +} - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = collection.length, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); +function getHsl(string) { + var hsla = getHsla(string); + return hsla && hsla.slice(0, 3); +} - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return collection.each( function( index ) { - var self = collection.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - domManip( self, args, callback, ignored ); - } ); - } +function getAlpha(string) { + var vals = getRgba(string); + if (vals) { + return vals[3]; + } + else if (vals = getHsla(string)) { + return vals[3]; + } + else if (vals = getHwb(string)) { + return vals[3]; + } +} - if ( l ) { - fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); - first = fragment.firstChild; +// generators +function hexString(rgb) { + return "#" + hexDouble(rgb[0]) + hexDouble(rgb[1]) + + hexDouble(rgb[2]); +} - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } +function rgbString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return rgbaString(rgba, alpha); + } + return "rgb(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + ")"; +} - // Require either new content or an interest in ignored elements to invoke the callback - if ( first || ignored ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; +function rgbaString(rgba, alpha) { + if (alpha === undefined) { + alpha = (rgba[3] !== undefined ? rgba[3] : 1); + } + return "rgba(" + rgba[0] + ", " + rgba[1] + ", " + rgba[2] + + ", " + alpha + ")"; +} - // Use the original fragment for the last item - // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; +function percentString(rgba, alpha) { + if (alpha < 1 || (rgba[3] && rgba[3] < 1)) { + return percentaString(rgba, alpha); + } + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); + return "rgb(" + r + "%, " + g + "%, " + b + "%)"; +} - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { +function percentaString(rgba, alpha) { + var r = Math.round(rgba[0]/255 * 100), + g = Math.round(rgba[1]/255 * 100), + b = Math.round(rgba[2]/255 * 100); + return "rgba(" + r + "%, " + g + "%, " + b + "%, " + (alpha || rgba[3] || 1) + ")"; +} - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } +function hslString(hsla, alpha) { + if (alpha < 1 || (hsla[3] && hsla[3] < 1)) { + return hslaString(hsla, alpha); + } + return "hsl(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%)"; +} - callback.call( collection[ i ], node, i ); - } +function hslaString(hsla, alpha) { + if (alpha === undefined) { + alpha = (hsla[3] !== undefined ? hsla[3] : 1); + } + return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + + alpha + ")"; +} - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; +// hwb is a bit different than rgb(a) & hsl(a) since there is no alpha specific syntax +// (hwb have alpha optional & 1 is default value) +function hwbString(hwb, alpha) { + if (alpha === undefined) { + alpha = (hwb[3] !== undefined ? hwb[3] : 1); + } + return "hwb(" + hwb[0] + ", " + hwb[1] + "%, " + hwb[2] + "%" + + (alpha !== undefined && alpha !== 1 ? ", " + alpha : "") + ")"; +} - // Reenable scripts - jQuery.map( scripts, restoreScript ); +function keyword(rgb) { + return reverseNames[rgb.slice(0, 3)]; +} - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !dataPriv.access( node, "globalEval" ) && - jQuery.contains( doc, node ) ) { +// helpers +function scale(num, min, max) { + return Math.min(Math.max(min, num), max); +} - if ( node.src ) { +function hexDouble(num) { + var str = num.toString(16).toUpperCase(); + return (str.length < 2) ? "0" + str : str; +} - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - DOMEval( node.textContent.replace( rcleanScript, "" ), doc ); - } - } - } - } - } - } - return collection; +//create a list of reverse color names +var reverseNames = {}; +for (var name in colorNames) { + reverseNames[colorNames[name]] = name; } + })(); +}); -function remove( elem, selector, keepData ) { - var node, - nodes = selector ? jQuery.filter( selector, elem ) : elem, - i = 0; +require.register("chartjs-color/index.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "chartjs-color"); + (function() { + /* MIT license */ +var convert = require('color-convert'); +var string = require('chartjs-color-string'); - for ( ; ( node = nodes[ i ] ) != null; i++ ) { - if ( !keepData && node.nodeType === 1 ) { - jQuery.cleanData( getAll( node ) ); - } +var Color = function (obj) { + if (obj instanceof Color) { + return obj; + } + if (!(this instanceof Color)) { + return new Color(obj); + } - if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { - setGlobalEval( getAll( node, "script" ) ); - } - node.parentNode.removeChild( node ); + this.valid = false; + this.values = { + rgb: [0, 0, 0], + hsl: [0, 0, 0], + hsv: [0, 0, 0], + hwb: [0, 0, 0], + cmyk: [0, 0, 0, 0], + alpha: 1 + }; + + // parse Color() argument + var vals; + if (typeof obj === 'string') { + vals = string.getRgba(obj); + if (vals) { + this.setValues('rgb', vals); + } else if (vals = string.getHsla(obj)) { + this.setValues('hsl', vals); + } else if (vals = string.getHwb(obj)) { + this.setValues('hwb', vals); + } + } else if (typeof obj === 'object') { + vals = obj; + if (vals.r !== undefined || vals.red !== undefined) { + this.setValues('rgb', vals); + } else if (vals.l !== undefined || vals.lightness !== undefined) { + this.setValues('hsl', vals); + } else if (vals.v !== undefined || vals.value !== undefined) { + this.setValues('hsv', vals); + } else if (vals.w !== undefined || vals.whiteness !== undefined) { + this.setValues('hwb', vals); + } else if (vals.c !== undefined || vals.cyan !== undefined) { + this.setValues('cmyk', vals); } } +}; - return elem; -} +Color.prototype = { + isValid: function () { + return this.valid; + }, + rgb: function () { + return this.setSpace('rgb', arguments); + }, + hsl: function () { + return this.setSpace('hsl', arguments); + }, + hsv: function () { + return this.setSpace('hsv', arguments); + }, + hwb: function () { + return this.setSpace('hwb', arguments); + }, + cmyk: function () { + return this.setSpace('cmyk', arguments); + }, -jQuery.extend( { - htmlPrefilter: function( html ) { - return html.replace( rxhtmlTag, "<$1>" ); + rgbArray: function () { + return this.values.rgb; + }, + hslArray: function () { + return this.values.hsl; + }, + hsvArray: function () { + return this.values.hsv; + }, + hwbArray: function () { + var values = this.values; + if (values.alpha !== 1) { + return values.hwb.concat([values.alpha]); + } + return values.hwb; + }, + cmykArray: function () { + return this.values.cmyk; + }, + rgbaArray: function () { + var values = this.values; + return values.rgb.concat([values.alpha]); + }, + hslaArray: function () { + var values = this.values; + return values.hsl.concat([values.alpha]); + }, + alpha: function (val) { + if (val === undefined) { + return this.values.alpha; + } + this.setValues('alpha', val); + return this; }, - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); + red: function (val) { + return this.setChannel('rgb', 0, val); + }, + green: function (val) { + return this.setChannel('rgb', 1, val); + }, + blue: function (val) { + return this.setChannel('rgb', 2, val); + }, + hue: function (val) { + if (val) { + val %= 360; + val = val < 0 ? 360 + val : val; + } + return this.setChannel('hsl', 0, val); + }, + saturation: function (val) { + return this.setChannel('hsl', 1, val); + }, + lightness: function (val) { + return this.setChannel('hsl', 2, val); + }, + saturationv: function (val) { + return this.setChannel('hsv', 1, val); + }, + whiteness: function (val) { + return this.setChannel('hwb', 1, val); + }, + blackness: function (val) { + return this.setChannel('hwb', 2, val); + }, + value: function (val) { + return this.setChannel('hsv', 2, val); + }, + cyan: function (val) { + return this.setChannel('cmyk', 0, val); + }, + magenta: function (val) { + return this.setChannel('cmyk', 1, val); + }, + yellow: function (val) { + return this.setChannel('cmyk', 2, val); + }, + black: function (val) { + return this.setChannel('cmyk', 3, val); + }, - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { + hexString: function () { + return string.hexString(this.values.rgb); + }, + rgbString: function () { + return string.rgbString(this.values.rgb, this.values.alpha); + }, + rgbaString: function () { + return string.rgbaString(this.values.rgb, this.values.alpha); + }, + percentString: function () { + return string.percentString(this.values.rgb, this.values.alpha); + }, + hslString: function () { + return string.hslString(this.values.hsl, this.values.alpha); + }, + hslaString: function () { + return string.hslaString(this.values.hsl, this.values.alpha); + }, + hwbString: function () { + return string.hwbString(this.values.hwb, this.values.alpha); + }, + keyword: function () { + return string.keyword(this.values.rgb, this.values.alpha); + }, - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); + rgbNumber: function () { + var rgb = this.values.rgb; + return (rgb[0] << 16) | (rgb[1] << 8) | rgb[2]; + }, - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } + luminosity: function () { + // http://www.w3.org/TR/WCAG20/#relativeluminancedef + var rgb = this.values.rgb; + var lum = []; + for (var i = 0; i < rgb.length; i++) { + var chan = rgb[i] / 255; + lum[i] = (chan <= 0.03928) ? chan / 12.92 : Math.pow(((chan + 0.055) / 1.055), 2.4); } + return 0.2126 * lum[0] + 0.7152 * lum[1] + 0.0722 * lum[2]; + }, - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } + contrast: function (color2) { + // http://www.w3.org/TR/WCAG20/#contrast-ratiodef + var lum1 = this.luminosity(); + var lum2 = color2.luminosity(); + if (lum1 > lum2) { + return (lum1 + 0.05) / (lum2 + 0.05); } + return (lum2 + 0.05) / (lum1 + 0.05); + }, - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + level: function (color2) { + var contrastRatio = this.contrast(color2); + if (contrastRatio >= 7.1) { + return 'AAA'; } - // Return the cloned set - return clone; + return (contrastRatio >= 4.5) ? 'AA' : ''; }, - cleanData: function( elems ) { - var data, elem, type, - special = jQuery.event.special, - i = 0; + dark: function () { + // YIQ equation from http://24ways.org/2010/calculating-color-contrast + var rgb = this.values.rgb; + var yiq = (rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000; + return yiq < 128; + }, - for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { - if ( acceptData( elem ) ) { - if ( ( data = elem[ dataPriv.expando ] ) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); + light: function () { + return !this.dark(); + }, - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } + negate: function () { + var rgb = []; + for (var i = 0; i < 3; i++) { + rgb[i] = 255 - this.values.rgb[i]; + } + this.setValues('rgb', rgb); + return this; + }, - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataPriv.expando ] = undefined; - } - if ( elem[ dataUser.expando ] ) { + lighten: function (ratio) { + var hsl = this.values.hsl; + hsl[2] += hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, - // Support: Chrome <=35 - 45+ - // Assign undefined instead of using delete, see Data#remove - elem[ dataUser.expando ] = undefined; - } - } - } - } -} ); + darken: function (ratio) { + var hsl = this.values.hsl; + hsl[2] -= hsl[2] * ratio; + this.setValues('hsl', hsl); + return this; + }, -jQuery.fn.extend( { - detach: function( selector ) { - return remove( this, selector, true ); + saturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] += hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; }, - remove: function( selector ) { - return remove( this, selector ); + desaturate: function (ratio) { + var hsl = this.values.hsl; + hsl[1] -= hsl[1] * ratio; + this.setValues('hsl', hsl); + return this; }, - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each( function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - } ); - }, null, value, arguments.length ); + whiten: function (ratio) { + var hwb = this.values.hwb; + hwb[1] += hwb[1] * ratio; + this.setValues('hwb', hwb); + return this; }, - append: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - } ); + blacken: function (ratio) { + var hwb = this.values.hwb; + hwb[2] += hwb[2] * ratio; + this.setValues('hwb', hwb); + return this; }, - prepend: function() { - return domManip( this, arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - } ); + greyscale: function () { + var rgb = this.values.rgb; + // http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale + var val = rgb[0] * 0.3 + rgb[1] * 0.59 + rgb[2] * 0.11; + this.setValues('rgb', [val, val, val]); + return this; }, - before: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - } ); + clearer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha - (alpha * ratio)); + return this; }, - after: function() { - return domManip( this, arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - } ); + opaquer: function (ratio) { + var alpha = this.values.alpha; + this.setValues('alpha', alpha + (alpha * ratio)); + return this; }, - empty: function() { - var elem, - i = 0; + rotate: function (degrees) { + var hsl = this.values.hsl; + var hue = (hsl[0] + degrees) % 360; + hsl[0] = hue < 0 ? 360 + hue : hue; + this.setValues('hsl', hsl); + return this; + }, - for ( ; ( elem = this[ i ] ) != null; i++ ) { - if ( elem.nodeType === 1 ) { + /** + * Ported from sass implementation in C + * https://github.com/sass/libsass/blob/0e6b4a2850092356aa3ece07c6b249f0221caced/functions.cpp#L209 + */ + mix: function (mixinColor, weight) { + var color1 = this; + var color2 = mixinColor; + var p = weight === undefined ? 0.5 : weight; + + var w = 2 * p - 1; + var a = color1.alpha() - color2.alpha(); + + var w1 = (((w * a === -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + return this + .rgb( + w1 * color1.red() + w2 * color2.red(), + w1 * color1.green() + w2 * color2.green(), + w1 * color1.blue() + w2 * color2.blue() + ) + .alpha(color1.alpha() * p + color2.alpha() * (1 - p)); + }, - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); + toJSON: function () { + return this.rgb(); + }, - // Remove any remaining nodes - elem.textContent = ""; + clone: function () { + // NOTE(SB): using node-clone creates a dependency to Buffer when using browserify, + // making the final build way to big to embed in Chart.js. So let's do it manually, + // assuming that values to clone are 1 dimension arrays containing only numbers, + // except 'alpha' which is a number. + var result = new Color(); + var source = this.values; + var target = result.values; + var value, type; + + for (var prop in source) { + if (source.hasOwnProperty(prop)) { + value = source[prop]; + type = ({}).toString.call(value); + if (type === '[object Array]') { + target[prop] = value.slice(0); + } else if (type === '[object Number]') { + target[prop] = value; + } else { + console.error('unexpected color value:', value); + } } } - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + return result; + } +}; - return this.map( function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - } ); - }, +Color.prototype.spaces = { + rgb: ['red', 'green', 'blue'], + hsl: ['hue', 'saturation', 'lightness'], + hsv: ['hue', 'saturation', 'value'], + hwb: ['hue', 'whiteness', 'blackness'], + cmyk: ['cyan', 'magenta', 'yellow', 'black'] +}; - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; +Color.prototype.maxes = { + rgb: [255, 255, 255], + hsl: [360, 100, 100], + hsv: [360, 100, 100], + hwb: [360, 100, 100], + cmyk: [100, 100, 100, 100] +}; - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } +Color.prototype.getValues = function (space) { + var values = this.values; + var vals = {}; - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + for (var i = 0; i < space.length; i++) { + vals[space.charAt(i)] = values[space][i]; + } - value = jQuery.htmlPrefilter( value ); + if (values.alpha !== 1) { + vals.a = values.alpha; + } - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; + // {r: 255, g: 255, b: 255, a: 0.4} + return vals; +}; - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } +Color.prototype.setValues = function (space, vals) { + var values = this.values; + var spaces = this.spaces; + var maxes = this.maxes; + var alpha = 1; + var i; - elem = 0; + this.valid = true; - // If using innerHTML throws an exception, use the fallback method - } catch ( e ) {} - } + if (space === 'alpha') { + alpha = vals; + } else if (vals.length) { + // [10, 10, 10] + values[space] = vals.slice(0, space.length); + alpha = vals[space.length]; + } else if (vals[space.charAt(0)] !== undefined) { + // {r: 10, g: 10, b: 10} + for (i = 0; i < space.length; i++) { + values[space][i] = vals[space.charAt(i)]; + } - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, + alpha = vals.a; + } else if (vals[spaces[space][0]] !== undefined) { + // {red: 10, green: 10, blue: 10} + var chans = spaces[space]; - replaceWith: function() { - var ignored = []; + for (i = 0; i < space.length; i++) { + values[space][i] = vals[chans[i]]; + } - // Make the changes, replacing each non-ignored context element with the new content - return domManip( this, arguments, function( elem ) { - var parent = this.parentNode; + alpha = vals.alpha; + } - if ( jQuery.inArray( this, ignored ) < 0 ) { - jQuery.cleanData( getAll( this ) ); - if ( parent ) { - parent.replaceChild( elem, this ); - } - } + values.alpha = Math.max(0, Math.min(1, (alpha === undefined ? values.alpha : alpha))); - // Force callback invocation - }, ignored ); + if (space === 'alpha') { + return false; } -} ); -jQuery.each( { - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; + var capped; - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); + // cap values of the space prior converting all values + for (i = 0; i < space.length; i++) { + capped = Math.max(0, Math.min(maxes[space][i], values[space][i])); + values[space][i] = Math.round(capped); + } - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit - push.apply( ret, elems.get() ); + // convert to all the other color spaces + for (var sname in spaces) { + if (sname !== space) { + values[sname] = convert[space][sname](values[space]); } + } - return this.pushStack( ret ); - }; -} ); -var rmargin = ( /^margin/ ); + return true; +}; -var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); +Color.prototype.setSpace = function (space, args) { + var vals = args[0]; -var getStyles = function( elem ) { + if (vals === undefined) { + // color.rgb() + return this.getValues(space); + } - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" - var view = elem.ownerDocument.defaultView; + // color.rgb(10, 10, 10) + if (typeof vals === 'number') { + vals = Array.prototype.slice.call(args); + } - if ( !view || !view.opener ) { - view = window; - } + this.setValues(space, vals); + return this; +}; - return view.getComputedStyle( elem ); - }; +Color.prototype.setChannel = function (space, index, val) { + var svalues = this.values[space]; + if (val === undefined) { + // color.red() + return svalues[index]; + } else if (val === svalues[index]) { + // color.red(color.red()) + return this; + } + // color.red(100) + svalues[index] = val; + this.setValues(space, svalues); + return this; +}; -( function() { +if (typeof window !== 'undefined') { + window.Color = Color; +} - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { +module.exports = Color; + })(); +}); - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } +require.register("color-convert/conversions.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "color-convert"); + (function() { + /* MIT license */ + +module.exports = { + rgb2hsl: rgb2hsl, + rgb2hsv: rgb2hsv, + rgb2hwb: rgb2hwb, + rgb2cmyk: rgb2cmyk, + rgb2keyword: rgb2keyword, + rgb2xyz: rgb2xyz, + rgb2lab: rgb2lab, + rgb2lch: rgb2lch, + + hsl2rgb: hsl2rgb, + hsl2hsv: hsl2hsv, + hsl2hwb: hsl2hwb, + hsl2cmyk: hsl2cmyk, + hsl2keyword: hsl2keyword, + + hsv2rgb: hsv2rgb, + hsv2hsl: hsv2hsl, + hsv2hwb: hsv2hwb, + hsv2cmyk: hsv2cmyk, + hsv2keyword: hsv2keyword, + + hwb2rgb: hwb2rgb, + hwb2hsl: hwb2hsl, + hwb2hsv: hwb2hsv, + hwb2cmyk: hwb2cmyk, + hwb2keyword: hwb2keyword, + + cmyk2rgb: cmyk2rgb, + cmyk2hsl: cmyk2hsl, + cmyk2hsv: cmyk2hsv, + cmyk2hwb: cmyk2hwb, + cmyk2keyword: cmyk2keyword, + + keyword2rgb: keyword2rgb, + keyword2hsl: keyword2hsl, + keyword2hsv: keyword2hsv, + keyword2hwb: keyword2hwb, + keyword2cmyk: keyword2cmyk, + keyword2lab: keyword2lab, + keyword2xyz: keyword2xyz, + + xyz2rgb: xyz2rgb, + xyz2lab: xyz2lab, + xyz2lch: xyz2lch, + + lab2xyz: lab2xyz, + lab2rgb: lab2rgb, + lab2lch: lab2lch, + + lch2lab: lch2lab, + lch2xyz: lch2xyz, + lch2rgb: lch2rgb +} - div.style.cssText = - "box-sizing:border-box;" + - "position:relative;display:block;" + - "margin:auto;border:1px;padding:1px;" + - "top:1%;width:50%"; - div.innerHTML = ""; - documentElement.appendChild( container ); - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; +function rgb2hsl(rgb) { + var r = rgb[0]/255, + g = rgb[1]/255, + b = rgb[2]/255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h, s, l; - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = divStyle.marginLeft === "2px"; - boxSizingReliableVal = divStyle.width === "4px"; + if (max == min) + h = 0; + else if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g)/ delta; - // Support: Android 4.0 - 4.3 only - // Some styles come back with percentage values, even though they shouldn't - div.style.marginRight = "50%"; - pixelMarginRightVal = divStyle.marginRight === "4px"; + h = Math.min(h * 60, 360); - documentElement.removeChild( container ); + if (h < 0) + h += 360; - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } + l = (min + max) / 2; - var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, - container = document.createElement( "div" ), - div = document.createElement( "div" ); + if (max == min) + s = 0; + else if (l <= 0.5) + s = delta / (max + min); + else + s = delta / (2 - max - min); - // Finish early in limited (non-browser) environments - if ( !div.style ) { - return; - } + return [h, s * 100, l * 100]; +} - // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) - div.style.backgroundClip = "content-box"; - div.cloneNode( true ).style.backgroundClip = ""; - support.clearCloneStyle = div.style.backgroundClip === "content-box"; +function rgb2hsv(rgb) { + var r = rgb[0], + g = rgb[1], + b = rgb[2], + min = Math.min(r, g, b), + max = Math.max(r, g, b), + delta = max - min, + h, s, v; + + if (max == 0) + s = 0; + else + s = (delta/max * 1000)/10; + + if (max == min) + h = 0; + else if (r == max) + h = (g - b) / delta; + else if (g == max) + h = 2 + (b - r) / delta; + else if (b == max) + h = 4 + (r - g) / delta; + + h = Math.min(h * 60, 360); + + if (h < 0) + h += 360; + + v = ((max / 255) * 1000) / 10; + + return [h, s, v]; +} - container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + - "padding:0;margin-top:1px;position:absolute"; - container.appendChild( div ); +function rgb2hwb(rgb) { + var r = rgb[0], + g = rgb[1], + b = rgb[2], + h = rgb2hsl(rgb)[0], + w = 1/255 * Math.min(r, Math.min(g, b)), + b = 1 - 1/255 * Math.max(r, Math.max(g, b)); - jQuery.extend( support, { - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - boxSizingReliable: function() { - computeStyleTests(); - return boxSizingReliableVal; - }, - pixelMarginRight: function() { - computeStyleTests(); - return pixelMarginRightVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - } - } ); -} )(); + return [h, w * 100, b * 100]; +} +function rgb2cmyk(rgb) { + var r = rgb[0] / 255, + g = rgb[1] / 255, + b = rgb[2] / 255, + c, m, y, k; + + k = Math.min(1 - r, 1 - g, 1 - b); + c = (1 - r - k) / (1 - k) || 0; + m = (1 - g - k) / (1 - k) || 0; + y = (1 - b - k) / (1 - k) || 0; + return [c * 100, m * 100, y * 100, k * 100]; +} -function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; +function rgb2keyword(rgb) { + return reverseKeywords[JSON.stringify(rgb)]; +} - computed = computed || getStyles( elem ); +function rgb2xyz(rgb) { + var r = rgb[0] / 255, + g = rgb[1] / 255, + b = rgb[2] / 255; - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) - if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; + // assume sRGB + r = r > 0.04045 ? Math.pow(((r + 0.055) / 1.055), 2.4) : (r / 12.92); + g = g > 0.04045 ? Math.pow(((g + 0.055) / 1.055), 2.4) : (g / 12.92); + b = b > 0.04045 ? Math.pow(((b + 0.055) / 1.055), 2.4) : (b / 12.92); - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } + var x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805); + var y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722); + var z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505); - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { + return [x * 100, y *100, z * 100]; +} - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; +function rgb2lab(rgb) { + var xyz = rgb2xyz(rgb), + x = xyz[0], + y = xyz[1], + z = xyz[2], + l, a, b; - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; + x /= 95.047; + y /= 100; + z /= 108.883; - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } + x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - return ret !== undefined ? + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); - // Support: IE <=9 - 11 only - // IE returns zIndex value as an integer. - ret + "" : - ret; + return [l, a, b]; } +function rgb2lch(args) { + return lab2lch(rgb2lab(args)); +} -function addGetHookIf( conditionFn, hookFn ) { +function hsl2rgb(hsl) { + var h = hsl[0] / 360, + s = hsl[1] / 100, + l = hsl[2] / 100, + t1, t2, t3, rgb, val; - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { + if (s == 0) { + val = l * 255; + return [val, val, val]; + } - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } + if (l < 0.5) + t2 = l * (1 + s); + else + t2 = l + s - l * s; + t1 = 2 * l - t2; + + rgb = [0, 0, 0]; + for (var i = 0; i < 3; i++) { + t3 = h + 1 / 3 * - (i - 1); + t3 < 0 && t3++; + t3 > 1 && t3--; + + if (6 * t3 < 1) + val = t1 + (t2 - t1) * 6 * t3; + else if (2 * t3 < 1) + val = t2; + else if (3 * t3 < 2) + val = t1 + (t2 - t1) * (2 / 3 - t3) * 6; + else + val = t1; + + rgb[i] = val * 255; + } - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; + return rgb; } +function hsl2hsv(hsl) { + var h = hsl[0], + s = hsl[1] / 100, + l = hsl[2] / 100, + sv, v; -var + if(l === 0) { + // no need to do calc on black + // also avoids divide by 0 error + return [0, 0, 0]; + } - // Swappable if display is none or starts with table - // except "table", "table-cell", or "table-caption" - // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: "0", - fontWeight: "400" - }, + l *= 2; + s *= (l <= 1) ? l : 2 - l; + v = (l + s) / 2; + sv = (2 * s) / (l + s); + return [h, sv * 100, v * 100]; +} - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; +function hsl2hwb(args) { + return rgb2hwb(hsl2rgb(args)); +} -// Return a css property mapped to a potentially vendor prefixed property -function vendorPropName( name ) { +function hsl2cmyk(args) { + return rgb2cmyk(hsl2rgb(args)); +} - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } +function hsl2keyword(args) { + return rgb2keyword(hsl2rgb(args)); +} - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } +function hsv2rgb(hsv) { + var h = hsv[0] / 60, + s = hsv[1] / 100, + v = hsv[2] / 100, + hi = Math.floor(h) % 6; + + var f = h - Math.floor(h), + p = 255 * v * (1 - s), + q = 255 * v * (1 - (s * f)), + t = 255 * v * (1 - (s * (1 - f))), + v = 255 * v; + + switch(hi) { + case 0: + return [v, t, p]; + case 1: + return [q, v, p]; + case 2: + return [p, v, t]; + case 3: + return [p, q, v]; + case 4: + return [t, p, v]; + case 5: + return [v, p, q]; + } } -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. -function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; - } - return ret; +function hsv2hsl(hsv) { + var h = hsv[0], + s = hsv[1] / 100, + v = hsv[2] / 100, + sl, l; + + l = (2 - s) * v; + sl = s * v; + sl /= (l <= 1) ? l : 2 - l; + sl = sl || 0; + l /= 2; + return [h, sl * 100, l * 100]; } -function setPositiveNumber( elem, value, subtract ) { +function hsv2hwb(args) { + return rgb2hwb(hsv2rgb(args)) +} - // Any relative (+/-) values have already been - // normalized at this point - var matches = rcssNum.exec( value ); - return matches ? +function hsv2cmyk(args) { + return rgb2cmyk(hsv2rgb(args)); +} - // Guard against undefined "subtract", e.g., when used as in cssHooks - Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : - value; +function hsv2keyword(args) { + return rgb2keyword(hsv2rgb(args)); } -function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { - var i, - val = 0; +// http://dev.w3.org/csswg/css-color/#hwb-to-rgb +function hwb2rgb(hwb) { + var h = hwb[0] / 360, + wh = hwb[1] / 100, + bl = hwb[2] / 100, + ratio = wh + bl, + i, v, f, n; + + // wh + bl cant be > 1 + if (ratio > 1) { + wh /= ratio; + bl /= ratio; + } - // If we already have the right measurement, avoid augmentation - if ( extra === ( isBorderBox ? "border" : "content" ) ) { - i = 4; + i = Math.floor(6 * h); + v = 1 - bl; + f = 6 * h - i; + if ((i & 0x01) != 0) { + f = 1 - f; + } + n = wh + f * (v - wh); // linear interpolation + + switch (i) { + default: + case 6: + case 0: r = v; g = n; b = wh; break; + case 1: r = n; g = v; b = wh; break; + case 2: r = wh; g = v; b = n; break; + case 3: r = wh; g = n; b = v; break; + case 4: r = n; g = wh; b = v; break; + case 5: r = v; g = wh; b = n; break; + } - // Otherwise initialize for horizontal or vertical properties - } else { - i = name === "width" ? 1 : 0; - } + return [r * 255, g * 255, b * 255]; +} - for ( ; i < 4; i += 2 ) { +function hwb2hsl(args) { + return rgb2hsl(hwb2rgb(args)); +} - // Both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); - } +function hwb2hsv(args) { + return rgb2hsv(hwb2rgb(args)); +} - if ( isBorderBox ) { +function hwb2cmyk(args) { + return rgb2cmyk(hwb2rgb(args)); +} - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); - } +function hwb2keyword(args) { + return rgb2keyword(hwb2rgb(args)); +} - // At this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } else { +function cmyk2rgb(cmyk) { + var c = cmyk[0] / 100, + m = cmyk[1] / 100, + y = cmyk[2] / 100, + k = cmyk[3] / 100, + r, g, b; + + r = 1 - Math.min(1, c * (1 - k) + k); + g = 1 - Math.min(1, m * (1 - k) + k); + b = 1 - Math.min(1, y * (1 - k) + k); + return [r * 255, g * 255, b * 255]; +} - // At this point, extra isn't content, so add padding - val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); +function cmyk2hsl(args) { + return rgb2hsl(cmyk2rgb(args)); +} - // At this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); - } - } - } +function cmyk2hsv(args) { + return rgb2hsv(cmyk2rgb(args)); +} - return val; +function cmyk2hwb(args) { + return rgb2hwb(cmyk2rgb(args)); } -function getWidthOrHeight( elem, name, extra ) { +function cmyk2keyword(args) { + return rgb2keyword(cmyk2rgb(args)); +} - // Start with computed style - var valueIsBorderBox, - styles = getStyles( elem ), - val = curCSS( elem, name, styles ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test( val ) ) { - return val; - } +function xyz2rgb(xyz) { + var x = xyz[0] / 100, + y = xyz[1] / 100, + z = xyz[2] / 100, + r, g, b; - // Check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && - ( support.boxSizingReliable() || val === elem.style[ name ] ); + r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986); + g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415); + b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570); - // Fall back to offsetWidth/Height when value is "auto" - // This happens for inline elements with no explicit setting (gh-3571) - if ( val === "auto" ) { - val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ]; - } + // assume sRGB + r = r > 0.0031308 ? ((1.055 * Math.pow(r, 1.0 / 2.4)) - 0.055) + : r = (r * 12.92); - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; + g = g > 0.0031308 ? ((1.055 * Math.pow(g, 1.0 / 2.4)) - 0.055) + : g = (g * 12.92); - // Use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox, - styles - ) - ) + "px"; -} + b = b > 0.0031308 ? ((1.055 * Math.pow(b, 1.0 / 2.4)) - 0.055) + : b = (b * 12.92); -jQuery.extend( { + r = Math.min(Math.max(0, r), 1); + g = Math.min(Math.max(0, g), 1); + b = Math.min(Math.max(0, b), 1); - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { + return [r * 255, g * 255, b * 255]; +} - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - } - } - } - }, +function xyz2lab(xyz) { + var x = xyz[0], + y = xyz[1], + z = xyz[2], + l, a, b; - // Don't automatically add "px" to these possibly-unitless properties - cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, + x /= 95.047; + y /= 100; + z /= 108.883; - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - "float": "cssFloat" - }, + x = x > 0.008856 ? Math.pow(x, 1/3) : (7.787 * x) + (16 / 116); + y = y > 0.008856 ? Math.pow(y, 1/3) : (7.787 * y) + (16 / 116); + z = z > 0.008856 ? Math.pow(z, 1/3) : (7.787 * z) + (16 / 116); - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { + l = (116 * y) - 16; + a = 500 * (x - y); + b = 200 * (y - z); - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } + return [l, a, b]; +} - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - isCustomProp = rcustomProp.test( name ), - style = elem.style; +function xyz2lch(args) { + return lab2lch(xyz2lab(args)); +} - // Make sure that we're working with the right name. We don't - // want to query the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } +function lab2xyz(lab) { + var l = lab[0], + a = lab[1], + b = lab[2], + x, y, z, y2; + + if (l <= 8) { + y = (l * 100) / 903.3; + y2 = (7.787 * (y / 100)) + (16 / 116); + } else { + y = 100 * Math.pow((l + 16) / 116, 3); + y2 = Math.pow(y / 100, 1/3); + } - // Gets hook for the prefixed version, then unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + x = x / 95.047 <= 0.008856 ? x = (95.047 * ((a / 500) + y2 - (16 / 116))) / 7.787 : 95.047 * Math.pow((a / 500) + y2, 3); - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; + z = z / 108.883 <= 0.008859 ? z = (108.883 * (y2 - (b / 200) - (16 / 116))) / 7.787 : 108.883 * Math.pow(y2 - (b / 200), 3); - // Convert "+=" or "-=" to relative numbers (#7345) - if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { - value = adjustCSS( elem, name, ret ); + return [x, y, z]; +} - // Fixes bug #9237 - type = "number"; - } +function lab2lch(lab) { + var l = lab[0], + a = lab[1], + b = lab[2], + hr, h, c; - // Make sure that null and NaN values aren't set (#7116) - if ( value == null || value !== value ) { - return; - } + hr = Math.atan2(b, a); + h = hr * 360 / 2 / Math.PI; + if (h < 0) { + h += 360; + } + c = Math.sqrt(a * a + b * b); + return [l, c, h]; +} - // If a number was passed in, add the unit (except for certain CSS properties) - if ( type === "number" ) { - value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); - } +function lab2rgb(args) { + return xyz2rgb(lab2xyz(args)); +} - // background-* props affect original clone's values - if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { - style[ name ] = "inherit"; - } +function lch2lab(lch) { + var l = lch[0], + c = lch[1], + h = lch[2], + a, b, hr; - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !( "set" in hooks ) || - ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + hr = h / 360 * 2 * Math.PI; + a = c * Math.cos(hr); + b = c * Math.sin(hr); + return [l, a, b]; +} - if ( isCustomProp ) { - style.setProperty( name, value ); - } else { - style[ name ] = value; - } - } +function lch2xyz(args) { + return lab2xyz(lch2lab(args)); +} - } else { +function lch2rgb(args) { + return lab2rgb(lch2lab(args)); +} - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && - ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { +function keyword2rgb(keyword) { + return cssKeywords[keyword]; +} - return ret; - } +function keyword2hsl(args) { + return rgb2hsl(keyword2rgb(args)); +} - // Otherwise just get the value from the style object - return style[ name ]; - } - }, +function keyword2hsv(args) { + return rgb2hsv(keyword2rgb(args)); +} - css: function( elem, name, extra, styles ) { - var val, num, hooks, - origName = jQuery.camelCase( name ), - isCustomProp = rcustomProp.test( name ); +function keyword2hwb(args) { + return rgb2hwb(keyword2rgb(args)); +} - // Make sure that we're working with the right name. We don't - // want to modify the value if it is a CSS custom property - // since they are user-defined. - if ( !isCustomProp ) { - name = finalPropName( origName ); - } +function keyword2cmyk(args) { + return rgb2cmyk(keyword2rgb(args)); +} - // Try prefixed name followed by the unprefixed name - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; +function keyword2lab(args) { + return rgb2lab(keyword2rgb(args)); +} - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } +function keyword2xyz(args) { + return rgb2xyz(keyword2rgb(args)); +} - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name, styles ); - } +var cssKeywords = { + aliceblue: [240,248,255], + antiquewhite: [250,235,215], + aqua: [0,255,255], + aquamarine: [127,255,212], + azure: [240,255,255], + beige: [245,245,220], + bisque: [255,228,196], + black: [0,0,0], + blanchedalmond: [255,235,205], + blue: [0,0,255], + blueviolet: [138,43,226], + brown: [165,42,42], + burlywood: [222,184,135], + cadetblue: [95,158,160], + chartreuse: [127,255,0], + chocolate: [210,105,30], + coral: [255,127,80], + cornflowerblue: [100,149,237], + cornsilk: [255,248,220], + crimson: [220,20,60], + cyan: [0,255,255], + darkblue: [0,0,139], + darkcyan: [0,139,139], + darkgoldenrod: [184,134,11], + darkgray: [169,169,169], + darkgreen: [0,100,0], + darkgrey: [169,169,169], + darkkhaki: [189,183,107], + darkmagenta: [139,0,139], + darkolivegreen: [85,107,47], + darkorange: [255,140,0], + darkorchid: [153,50,204], + darkred: [139,0,0], + darksalmon: [233,150,122], + darkseagreen: [143,188,143], + darkslateblue: [72,61,139], + darkslategray: [47,79,79], + darkslategrey: [47,79,79], + darkturquoise: [0,206,209], + darkviolet: [148,0,211], + deeppink: [255,20,147], + deepskyblue: [0,191,255], + dimgray: [105,105,105], + dimgrey: [105,105,105], + dodgerblue: [30,144,255], + firebrick: [178,34,34], + floralwhite: [255,250,240], + forestgreen: [34,139,34], + fuchsia: [255,0,255], + gainsboro: [220,220,220], + ghostwhite: [248,248,255], + gold: [255,215,0], + goldenrod: [218,165,32], + gray: [128,128,128], + green: [0,128,0], + greenyellow: [173,255,47], + grey: [128,128,128], + honeydew: [240,255,240], + hotpink: [255,105,180], + indianred: [205,92,92], + indigo: [75,0,130], + ivory: [255,255,240], + khaki: [240,230,140], + lavender: [230,230,250], + lavenderblush: [255,240,245], + lawngreen: [124,252,0], + lemonchiffon: [255,250,205], + lightblue: [173,216,230], + lightcoral: [240,128,128], + lightcyan: [224,255,255], + lightgoldenrodyellow: [250,250,210], + lightgray: [211,211,211], + lightgreen: [144,238,144], + lightgrey: [211,211,211], + lightpink: [255,182,193], + lightsalmon: [255,160,122], + lightseagreen: [32,178,170], + lightskyblue: [135,206,250], + lightslategray: [119,136,153], + lightslategrey: [119,136,153], + lightsteelblue: [176,196,222], + lightyellow: [255,255,224], + lime: [0,255,0], + limegreen: [50,205,50], + linen: [250,240,230], + magenta: [255,0,255], + maroon: [128,0,0], + mediumaquamarine: [102,205,170], + mediumblue: [0,0,205], + mediumorchid: [186,85,211], + mediumpurple: [147,112,219], + mediumseagreen: [60,179,113], + mediumslateblue: [123,104,238], + mediumspringgreen: [0,250,154], + mediumturquoise: [72,209,204], + mediumvioletred: [199,21,133], + midnightblue: [25,25,112], + mintcream: [245,255,250], + mistyrose: [255,228,225], + moccasin: [255,228,181], + navajowhite: [255,222,173], + navy: [0,0,128], + oldlace: [253,245,230], + olive: [128,128,0], + olivedrab: [107,142,35], + orange: [255,165,0], + orangered: [255,69,0], + orchid: [218,112,214], + palegoldenrod: [238,232,170], + palegreen: [152,251,152], + paleturquoise: [175,238,238], + palevioletred: [219,112,147], + papayawhip: [255,239,213], + peachpuff: [255,218,185], + peru: [205,133,63], + pink: [255,192,203], + plum: [221,160,221], + powderblue: [176,224,230], + purple: [128,0,128], + rebeccapurple: [102, 51, 153], + red: [255,0,0], + rosybrown: [188,143,143], + royalblue: [65,105,225], + saddlebrown: [139,69,19], + salmon: [250,128,114], + sandybrown: [244,164,96], + seagreen: [46,139,87], + seashell: [255,245,238], + sienna: [160,82,45], + silver: [192,192,192], + skyblue: [135,206,235], + slateblue: [106,90,205], + slategray: [112,128,144], + slategrey: [112,128,144], + snow: [255,250,250], + springgreen: [0,255,127], + steelblue: [70,130,180], + tan: [210,180,140], + teal: [0,128,128], + thistle: [216,191,216], + tomato: [255,99,71], + turquoise: [64,224,208], + violet: [238,130,238], + wheat: [245,222,179], + white: [255,255,255], + whitesmoke: [245,245,245], + yellow: [255,255,0], + yellowgreen: [154,205,50] +}; - // Convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } +var reverseKeywords = {}; +for (var key in cssKeywords) { + reverseKeywords[JSON.stringify(cssKeywords[key])] = key; +} + })(); +}); - // Make numeric if forced or a qualifier was provided and val looks numeric - if ( extra === "" || extra ) { - num = parseFloat( val ); - return extra === true || isFinite( num ) ? num || 0 : val; - } +require.register("color-convert/index.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "color-convert"); + (function() { + var conversions = require("./conversions"); - return val; - } -} ); +var convert = function() { + return new Converter(); +} -jQuery.each( [ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { +for (var func in conversions) { + // export Raw versions + convert[func + "Raw"] = (function(func) { + // accept array or plain args + return function(arg) { + if (typeof arg == "number") + arg = Array.prototype.slice.call(arguments); + return conversions[func](arg); + } + })(func); + + var pair = /(\w+)2(\w+)/.exec(func), + from = pair[1], + to = pair[2]; + + // export rgb2hsl and ["rgb"]["hsl"] + convert[from] = convert[from] || {}; + + convert[from][to] = convert[func] = (function(func) { + return function(arg) { + if (typeof arg == "number") + arg = Array.prototype.slice.call(arguments); + + var val = conversions[func](arg); + if (typeof val == "string" || val === undefined) + return val; // keyword + + for (var i = 0; i < val.length; i++) + val[i] = Math.round(val[i]); + return val; + } + })(func); +} - // Certain elements can have dimension info if we invisibly show them - // but it must have a current display style that would benefit - return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero - // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only - // Running getBoundingClientRect on a disconnected node - // in IE throws an error. - ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? - swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - } ) : - getWidthOrHeight( elem, name, extra ); - } - }, +/* Converter does lazy conversion and caching */ +var Converter = function() { + this.convs = {}; +}; - set: function( elem, value, extra ) { - var matches, - styles = extra && getStyles( elem ), - subtract = extra && augmentWidthOrHeight( - elem, - name, - extra, - jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - styles - ); +/* Either get the values for a space or + set the values for a space, depending on args */ +Converter.prototype.routeSpace = function(space, args) { + var values = args[0]; + if (values === undefined) { + // color.rgb() + return this.getValues(space); + } + // color.rgb(10, 10, 10) + if (typeof values == "number") { + values = Array.prototype.slice.call(args); + } + + return this.setValues(space, values); +}; + +/* Set the values for a space, invalidating cache */ +Converter.prototype.setValues = function(space, values) { + this.space = space; + this.convs = {}; + this.convs[space] = values; + return this; +}; - // Convert to pixels if value adjustment is needed - if ( subtract && ( matches = rcssNum.exec( value ) ) && - ( matches[ 3 ] || "px" ) !== "px" ) { +/* Get the values for a space. If there's already + a conversion for the space, fetch it, otherwise + compute it */ +Converter.prototype.getValues = function(space) { + var vals = this.convs[space]; + if (!vals) { + var fspace = this.space, + from = this.convs[fspace]; + vals = convert[fspace][space](from); + + this.convs[space] = vals; + } + return vals; +}; - elem.style[ name ] = value; - value = jQuery.css( elem, name ); - } +["rgb", "hsl", "hsv", "cmyk", "keyword"].forEach(function(space) { + Converter.prototype[space] = function(vals) { + return this.routeSpace(space, arguments); + } +}); - return setPositiveNumber( elem, value, subtract ); - } - }; -} ); +module.exports = convert; + })(); +}); -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } +require.register("color-name/index.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "color-name"); + (function() { + 'use strict' + +module.exports = { + "aliceblue": [240, 248, 255], + "antiquewhite": [250, 235, 215], + "aqua": [0, 255, 255], + "aquamarine": [127, 255, 212], + "azure": [240, 255, 255], + "beige": [245, 245, 220], + "bisque": [255, 228, 196], + "black": [0, 0, 0], + "blanchedalmond": [255, 235, 205], + "blue": [0, 0, 255], + "blueviolet": [138, 43, 226], + "brown": [165, 42, 42], + "burlywood": [222, 184, 135], + "cadetblue": [95, 158, 160], + "chartreuse": [127, 255, 0], + "chocolate": [210, 105, 30], + "coral": [255, 127, 80], + "cornflowerblue": [100, 149, 237], + "cornsilk": [255, 248, 220], + "crimson": [220, 20, 60], + "cyan": [0, 255, 255], + "darkblue": [0, 0, 139], + "darkcyan": [0, 139, 139], + "darkgoldenrod": [184, 134, 11], + "darkgray": [169, 169, 169], + "darkgreen": [0, 100, 0], + "darkgrey": [169, 169, 169], + "darkkhaki": [189, 183, 107], + "darkmagenta": [139, 0, 139], + "darkolivegreen": [85, 107, 47], + "darkorange": [255, 140, 0], + "darkorchid": [153, 50, 204], + "darkred": [139, 0, 0], + "darksalmon": [233, 150, 122], + "darkseagreen": [143, 188, 143], + "darkslateblue": [72, 61, 139], + "darkslategray": [47, 79, 79], + "darkslategrey": [47, 79, 79], + "darkturquoise": [0, 206, 209], + "darkviolet": [148, 0, 211], + "deeppink": [255, 20, 147], + "deepskyblue": [0, 191, 255], + "dimgray": [105, 105, 105], + "dimgrey": [105, 105, 105], + "dodgerblue": [30, 144, 255], + "firebrick": [178, 34, 34], + "floralwhite": [255, 250, 240], + "forestgreen": [34, 139, 34], + "fuchsia": [255, 0, 255], + "gainsboro": [220, 220, 220], + "ghostwhite": [248, 248, 255], + "gold": [255, 215, 0], + "goldenrod": [218, 165, 32], + "gray": [128, 128, 128], + "green": [0, 128, 0], + "greenyellow": [173, 255, 47], + "grey": [128, 128, 128], + "honeydew": [240, 255, 240], + "hotpink": [255, 105, 180], + "indianred": [205, 92, 92], + "indigo": [75, 0, 130], + "ivory": [255, 255, 240], + "khaki": [240, 230, 140], + "lavender": [230, 230, 250], + "lavenderblush": [255, 240, 245], + "lawngreen": [124, 252, 0], + "lemonchiffon": [255, 250, 205], + "lightblue": [173, 216, 230], + "lightcoral": [240, 128, 128], + "lightcyan": [224, 255, 255], + "lightgoldenrodyellow": [250, 250, 210], + "lightgray": [211, 211, 211], + "lightgreen": [144, 238, 144], + "lightgrey": [211, 211, 211], + "lightpink": [255, 182, 193], + "lightsalmon": [255, 160, 122], + "lightseagreen": [32, 178, 170], + "lightskyblue": [135, 206, 250], + "lightslategray": [119, 136, 153], + "lightslategrey": [119, 136, 153], + "lightsteelblue": [176, 196, 222], + "lightyellow": [255, 255, 224], + "lime": [0, 255, 0], + "limegreen": [50, 205, 50], + "linen": [250, 240, 230], + "magenta": [255, 0, 255], + "maroon": [128, 0, 0], + "mediumaquamarine": [102, 205, 170], + "mediumblue": [0, 0, 205], + "mediumorchid": [186, 85, 211], + "mediumpurple": [147, 112, 219], + "mediumseagreen": [60, 179, 113], + "mediumslateblue": [123, 104, 238], + "mediumspringgreen": [0, 250, 154], + "mediumturquoise": [72, 209, 204], + "mediumvioletred": [199, 21, 133], + "midnightblue": [25, 25, 112], + "mintcream": [245, 255, 250], + "mistyrose": [255, 228, 225], + "moccasin": [255, 228, 181], + "navajowhite": [255, 222, 173], + "navy": [0, 0, 128], + "oldlace": [253, 245, 230], + "olive": [128, 128, 0], + "olivedrab": [107, 142, 35], + "orange": [255, 165, 0], + "orangered": [255, 69, 0], + "orchid": [218, 112, 214], + "palegoldenrod": [238, 232, 170], + "palegreen": [152, 251, 152], + "paleturquoise": [175, 238, 238], + "palevioletred": [219, 112, 147], + "papayawhip": [255, 239, 213], + "peachpuff": [255, 218, 185], + "peru": [205, 133, 63], + "pink": [255, 192, 203], + "plum": [221, 160, 221], + "powderblue": [176, 224, 230], + "purple": [128, 0, 128], + "rebeccapurple": [102, 51, 153], + "red": [255, 0, 0], + "rosybrown": [188, 143, 143], + "royalblue": [65, 105, 225], + "saddlebrown": [139, 69, 19], + "salmon": [250, 128, 114], + "sandybrown": [244, 164, 96], + "seagreen": [46, 139, 87], + "seashell": [255, 245, 238], + "sienna": [160, 82, 45], + "silver": [192, 192, 192], + "skyblue": [135, 206, 235], + "slateblue": [106, 90, 205], + "slategray": [112, 128, 144], + "slategrey": [112, 128, 144], + "snow": [255, 250, 250], + "springgreen": [0, 255, 127], + "steelblue": [70, 130, 180], + "tan": [210, 180, 140], + "teal": [0, 128, 128], + "thistle": [216, 191, 216], + "tomato": [255, 99, 71], + "turquoise": [64, 224, 208], + "violet": [238, 130, 238], + "wheat": [245, 222, 179], + "white": [255, 255, 255], + "whitesmoke": [245, 245, 245], + "yellow": [255, 255, 0], + "yellowgreen": [154, 205, 50] +}; + })(); +}); + +require.register("jquery/dist/jquery.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "jquery"); + (function() { + /*! + * jQuery JavaScript Library v3.2.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2017-03-20T18:59Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); } -); -// These hooks are used by animate to expand properties -jQuery.each( { - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i = 0, - expanded = {}, +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - // Assumes a single number if not a string - parts = typeof value === "string" ? value.split( " " ) : [ value ]; +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; - for ( ; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } +var arr = []; - return expanded; - } - }; +var document = window.document; - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -} ); +var getProto = Object.getPrototypeOf; -jQuery.fn.extend( { - css: function( name, value ) { - return access( this, function( elem, name, value ) { - var styles, len, - map = {}, - i = 0; +var slice = arr.slice; - if ( Array.isArray( name ) ) { - styles = getStyles( elem ); - len = name.length; +var concat = arr.concat; - for ( ; i < len; i++ ) { - map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); - } +var push = arr.push; - return map; - } +var indexOf = arr.indexOf; - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - } -} ); +var class2type = {}; +var toString = class2type.toString; -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; +var hasOwn = class2type.hasOwnProperty; -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || jQuery.easing._default; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; +var fnToString = hasOwn.toString; - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; +var ObjectFunctionString = fnToString.call( Object ); - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; +var support = {}; - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; -Tween.prototype.init.prototype = Tween.prototype; + function DOMEval( code, doc ) { + doc = doc || document; -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; + var script = doc.createElement( "script" ); - // Use a property on the element directly when it is not a DOM element, - // or when there is no matching style property that exists. - if ( tween.elem.nodeType !== 1 || - tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { - return tween.elem[ tween.prop ]; - } + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module - // Passing an empty string as a 3rd parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails. - // Simple values such as "10px" are parsed to Float; - // complex values such as "rotate(1rad)" are returned as-is. - result = jQuery.css( tween.elem, tween.prop, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // Use step hook for back compat. - // Use cssHook if its there. - // Use .style if available and use plain properties where available. - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; +var + version = "3.2.1", -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; + // Define a local copy of jQuery + jQuery = function( selector, context ) { -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p * Math.PI ) / 2; + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); }, - _default: "swing" -}; - -jQuery.fx = Tween.prototype.init; -// Back compat <1.8 extension point -jQuery.fx.step = {}; + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; +jQuery.fn = jQuery.prototype = { -var - fxNow, inProgress, - rfxtypes = /^(?:toggle|show|hide)$/, - rrun = /queueHooks$/; + // The current version of jQuery being used + jquery: version, -function schedule() { - if ( inProgress ) { - if ( document.hidden === false && window.requestAnimationFrame ) { - window.requestAnimationFrame( schedule ); - } else { - window.setTimeout( schedule, jQuery.fx.interval ); - } + constructor: jQuery, - jQuery.fx.tick(); - } -} + // The default length of a jQuery object is 0 + length: 0, -// Animations created synchronously will run synchronously -function createFxNow() { - window.setTimeout( function() { - fxNow = undefined; - } ); - return ( fxNow = jQuery.now() ); -} + toArray: function() { + return slice.call( this ); + }, -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - i = 0, - attrs = { height: type }; + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { - // If we include width, step value is 1 to do all cssExpand values, - // otherwise step value is 2 to skip over Left and Right - includeWidth = includeWidth ? 1 : 0; - for ( ; i < 4; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, - return attrs; -} + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { -function createTween( value, prop, animation ) { - var tween, - collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); - // We're done with this property - return tween; - } - } -} + // Add the old object onto the stack (as a reference) + ret.prevObject = this; -function defaultPrefilter( elem, props, opts ) { - var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, - isBox = "width" in props || "height" in props, - anim = this, - orig = {}, - style = elem.style, - hidden = elem.nodeType && isHiddenWithinTree( elem ), - dataShow = dataPriv.get( elem, "fxshow" ); + // Return the newly-formed element set + return ret; + }, - // Queue-skipping animations hijack the fx hooks - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, - anim.always( function() { + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, - // Ensure the complete handler is called before this completes - anim.always( function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - } ); - } ); - } + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, - // Detect show/hide animations - for ( prop in props ) { - value = props[ prop ]; - if ( rfxtypes.test( value ) ) { - delete props[ prop ]; - toggle = toggle || value === "toggle"; - if ( value === ( hidden ? "hide" : "show" ) ) { + first: function() { + return this.eq( 0 ); + }, - // Pretend to be hidden if this is a "show" and - // there is still data from a stopped show/hide - if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { - hidden = true; + last: function() { + return this.eq( -1 ); + }, - // Ignore all other no-op show/hide data - } else { - continue; - } - } - orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); - } + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; } - // Bail out if this is a no-op like .hide().hide() - propTween = !jQuery.isEmptyObject( props ); - if ( !propTween && jQuery.isEmptyObject( orig ) ) { - return; + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; } - // Restrict "overflow" and "display" styles during box animations - if ( isBox && elem.nodeType === 1 ) { + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } - // Support: IE <=9 - 11, Edge 12 - 13 - // Record all 3 overflow attributes because IE does not infer the shorthand - // from identically-valued overflowX and overflowY - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + for ( ; i < length; i++ ) { - // Identify a display type, preferring old show/hide data over the CSS cascade - restoreDisplay = dataShow && dataShow.display; - if ( restoreDisplay == null ) { - restoreDisplay = dataPriv.get( elem, "display" ); - } - display = jQuery.css( elem, "display" ); - if ( display === "none" ) { - if ( restoreDisplay ) { - display = restoreDisplay; - } else { + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { - // Get nonempty value(s) by temporarily forcing visibility - showHide( [ elem ], true ); - restoreDisplay = elem.style.display || restoreDisplay; - display = jQuery.css( elem, "display" ); - showHide( [ elem ] ); - } - } + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; - // Animate inline elements as inline-block - if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { - if ( jQuery.css( elem, "float" ) === "none" ) { + // Prevent never-ending loop + if ( target === copy ) { + continue; + } - // Restore the original display value at the end of pure show/hide animations - if ( !propTween ) { - anim.done( function() { - style.display = restoreDisplay; - } ); - if ( restoreDisplay == null ) { - display = style.display; - restoreDisplay = display === "none" ? "" : display; + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && Array.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; } - style.display = "inline-block"; } } } - if ( opts.overflow ) { - style.overflow = "hidden"; - anim.always( function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - } ); - } + // Return the modified object + return target; +}; - // Implement show/hide animations - propTween = false; - for ( prop in orig ) { +jQuery.extend( { - // General show/hide setup for this element animation - if ( !propTween ) { - if ( dataShow ) { - if ( "hidden" in dataShow ) { - hidden = dataShow.hidden; - } - } else { - dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); - } + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - // Store hidden/visible for toggle so `.stop().toggle()` "reverses" - if ( toggle ) { - dataShow.hidden = !hidden; - } + // Assume jQuery is ready without the ready module + isReady: true, - // Show elements before animating them - if ( hidden ) { - showHide( [ elem ], true ); - } + error: function( msg ) { + throw new Error( msg ); + }, - /* eslint-disable no-loop-func */ + noop: function() {}, - anim.done( function() { + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, - /* eslint-enable no-loop-func */ + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, - // The final step of a "hide" animation is actually hiding the element - if ( !hidden ) { - showHide( [ elem ] ); - } - dataPriv.remove( elem, "fxshow" ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - } ); - } + isNumeric: function( obj ) { - // Per-property setup - propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = propTween.start; - if ( hidden ) { - propTween.end = propTween.start; - propTween.start = 0; - } - } - } -} + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( Array.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } + isPlainObject: function( obj ) { + var proto, Ctor; - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; } - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; + proto = getProto( obj ); - // Not quite $.extend, this won't overwrite existing keys. - // Reusing 'index' because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; } - } -} -function Animation( elem, properties, options ) { - var result, - stopped, - index = 0, - length = Animation.prefilters.length, - deferred = jQuery.Deferred().always( function() { + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, - // Don't match elem in the :animated selector - delete tick.elem; - } ), - tick = function() { - if ( stopped ) { - return false; + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.3 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-08-08 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true && ("form" in elem || "label" in elem); + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + disabledAncestor( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = +argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9-11, Edge + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + if ( preferredDoc !== document && + (subWindow = document.defaultView) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert(function( el ) { + el.className = "i"; + return !el.getAttribute("className"); + }); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert(function( el ) { + el.appendChild( document.createComment("") ); + return !el.getElementsByTagName("*").length; + }); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert(function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + }); + + // ID filter and find + if ( support.getById ) { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( (elem = elems[i++]) ) { + node = elem.getAttributeNode("id"); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find["TAG"] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( (support.qsa = rnative.test( document.querySelectorAll )) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( el ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll("[msallowcapture^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } + }); + + assert(function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement("input"); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll("[name=d]").length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll(":enabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll(":disabled").length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( el ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { + + // Choose the first element that is related to our preferred document + if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { + return -1; + } + if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + return a === document ? -1 : + b === document ? 1 : + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? -1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + if ( support.matchesSelector && documentIsHTML && + !compilerCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + (val = elem.getAttributeNode(name)) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return (sel + "").replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[6] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[3] ) { + match[2] = match[4] || match[5] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { return true; } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + // Use previously-cached element index if available + if ( useCache ) { + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || (node[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + (outerCache[ node.uniqueID ] = {}); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifier + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } +}; + +Expr.pseudos["nth"] = Expr.pseudos["eq"]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( (tokens = []) ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push({ + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push({ + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {}); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( (oldCache = uniqueCache[ key ]) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return (newCache[ 2 ] = oldCache[ 2 ]); + } else { + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), + len = elems.length; + + if ( outermost ) { + outermostContext = context === document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + if ( !context && elem.ownerDocument !== document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context || document, xml) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( (selector = compiled.selector || selector) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) { + + context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert(function( el ) { + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement("fieldset") ) & 1; +}); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert(function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute("href") === "#" ; +}) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + }); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert(function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +}) ) { + addHandle( "value", function( elem, name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + }); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert(function( el ) { + return el.getAttribute("disabled") == null; +}) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + (val = elem.getAttributeNode( name )) && val.specified ? + val.value : + null; + } + }); +} + +return Sizzle; + +})( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +}; +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +var risSimple = /^.[^:#\[\.,]*$/; + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Simple selector that can be filtered directly, removing non-Elements + if ( risSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + // Complex selector, compare the two sets, removing non-Elements + qualifier = jQuery.filter( qualifier, elements ); + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1; + } ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( nodeName( elem, "iframe" ) ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( jQuery.isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && jQuery.isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( jQuery.isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + jQuery.isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the master Deferred + master = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + master.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( master.state() === "pending" || + jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return master.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), master.reject ); + } + + return master.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ jQuery.camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ jQuery.camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( jQuery.camelCase ); + } else { + key = jQuery.camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + 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 ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + jQuery.contains( elem.ownerDocument, elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + +var swap = function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, + scale = 1, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + do { + + // If previous iteration zeroed out, double until we get *something*. + // Use string for doubling so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + initialInUnit = initialInUnit / scale; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // Break the loop if scale is unchanged or perfect, or if we've just had enough. + } while ( + scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations + ); + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i ); + +var rscriptType = ( /^$|\/(?:java|ecma)script/i ); + + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // Support: IE <=9 only + option: [ 1, "" ], + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +// Support: IE <=9 only +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, contains, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; +} )(); +var documentElement = document.documentElement; + + + +var + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 only +// See #13393 for more info +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = {}; + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + // Make a writable jQuery.Event from the native event object + var event = jQuery.event.fix( nativeEvent ); + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or 2) have namespace(s) + // a subset or equal to those in the bound event (both can have no namespace). + if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: jQuery.isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + + which: function( event ) { + var button = event.button; + + // Add which for key events + if ( event.which == null && rkeyEvent.test( event.type ) ) { + return event.charCode != null ? event.charCode : event.keyCode; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) { + if ( button & 1 ) { + return 1; + } + + if ( button & 2 ) { + return 3; + } + + if ( button & 4 ) { + return 2; + } + + return 0; + } + + return event.which; + } +}, jQuery.event.addProp ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + /* eslint-disable max-len */ + + // See https://github.com/eslint/eslint/issues/3229 + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, + + /* eslint-enable */ + + // Support: IE <=10 - 11, Edge 12 - 13 + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( ">tbody", elem )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.access( src ); + pdataCur = dataPriv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl ) { + jQuery._evalUrl( node.src ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html.replace( rxhtmlTag, "<$1>" ); + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rmargin = ( /^margin/ ); + +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + div.style.cssText = + "box-sizing:border-box;" + + "position:relative;display:block;" + + "margin:auto;border:1px;padding:1px;" + + "top:1%;width:50%"; + div.innerHTML = ""; + documentElement.appendChild( container ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = divStyle.marginLeft === "2px"; + boxSizingReliableVal = divStyle.width === "4px"; + + // Support: Android 4.0 - 4.3 only + // Some styles come back with percentage values, even though they shouldn't + div.style.marginRight = "50%"; + pixelMarginRightVal = divStyle.marginRight === "4px"; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" + + "padding:0;margin-top:1px;position:absolute"; + container.appendChild( div ); + + jQuery.extend( support, { + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelMarginRight: function() { + computeStyleTests(); + return pixelMarginRightVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }, + + cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style; + +// Return a css property mapped to a potentially vendor prefixed property +function vendorPropName( name ) { + + // Shortcut for names that are not vendor prefixed + if ( name in emptyStyle ) { + return name; + } + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a property mapped along what jQuery.cssProps suggests or to +// a vendor prefixed property. +function finalPropName( name ) { + var ret = jQuery.cssProps[ name ]; + if ( !ret ) { + ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; + } + return ret; +} + +function setPositiveNumber( elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i, + val = 0; + + // If we already have the right measurement, avoid augmentation + if ( extra === ( isBorderBox ? "border" : "content" ) ) { + i = 4; + + // Otherwise initialize for horizontal or vertical properties + } else { + i = name === "width" ? 1 : 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // At this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + + // At this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // At this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with computed style + var valueIsBorderBox, + styles = getStyles( elem ), + val = curCSS( elem, name, styles ), + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test( val ) ) { + return val; + } + + // Check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && + ( support.boxSizingReliable() || val === elem.style[ name ] ); + + // Fall back to offsetWidth/Height when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + if ( val === "auto" ) { + val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ]; + } + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + + // Use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + "float": "cssFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + if ( type === "number" ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = jQuery.camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + } ) : + getWidthOrHeight( elem, name, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = extra && getStyles( elem ), + subtract = extra && augmentWidthOrHeight( + elem, + name, + extra, + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles + ); + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ name ] = value; + value = jQuery.css( elem, name ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( !rmargin.test( prefix ) ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && + ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || + jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = jQuery.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 13 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = jQuery.camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( jQuery.isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + jQuery.proxy( result.stop, result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( jQuery.isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( jQuery.isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = jQuery.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( jQuery.isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + if ( typeof value === "string" && value ) { + classes = value.match( rnothtmlwhite ) || []; + + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( type === "string" ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = value.match( rnothtmlwhite ) || []; + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, isFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup contextmenu" ).split( " " ), + function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +} ); + +jQuery.fn.extend( { + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +} ); + + + + +support.focusin = "onfocusin" in window; + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = jQuery.now(); + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = jQuery.isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ) + .filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ) + .map( function( i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( jQuery.isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + 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" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 13 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available, append data to url + if ( s.data ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + + +jQuery._evalUrl = function( url ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + "throws": true + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( jQuery.isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " From 03a4760d1ce5b07c8af8a191ddc0e40918cf0003 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 11:24:23 +0100 Subject: [PATCH 27/55] fixed janitor test --- test/lib/ex_debug_toolbar/database/janitor_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lib/ex_debug_toolbar/database/janitor_test.exs b/test/lib/ex_debug_toolbar/database/janitor_test.exs index 7fac408..a39eab2 100644 --- a/test/lib/ex_debug_toolbar/database/janitor_test.exs +++ b/test/lib/ex_debug_toolbar/database/janitor_test.exs @@ -29,7 +29,7 @@ defmodule ExDebugToolbar.Database.JanitorTest do end test "it broadcasts request:deleted event for each popped requests" do - @endpoint.subscribe "dashboard" + @endpoint.subscribe "dashboard:history" Janitor.cleanup_requests() assert_broadcast "request:deleted", %{uuid: 1} assert_broadcast "request:deleted", %{uuid: 2} From 5e67b535b5c005ed8f3fe046d52df11239bd1ce3 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 11:27:09 +0100 Subject: [PATCH 28/55] for now removed notifications from dashboard layout --- web/templates/dashboard_layout/app.html.eex | 29 --------------------- 1 file changed, 29 deletions(-) diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index 4cab5ba..9a7518a 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -33,35 +33,6 @@ Toggle navigation - - From 860b8fb55c2ad14fbad93b3239d3a6ad343cdc41 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 11:33:39 +0100 Subject: [PATCH 29/55] renamed `:max_requests` to `:requests_limit` and updated janitor test to reset this limit back to original on teardown --- README.md | 2 +- config/config.exs | 2 +- lib/ex_debug_toolbar/config.ex | 9 +++++++++ lib/ex_debug_toolbar/database/janitor.ex | 4 ++-- test/lib/ex_debug_toolbar/database/janitor_test.exs | 7 ++++--- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index fdb3f3c..9aa508b 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ To change configuration, update `:ex_debug_toolbar` config key in your `config/d | remove_glob_params | boolean | true | `Plug.Router` adds `glob` params to `conn.params` and `conn.path_params` on `forward`. This option removes them | | ignore_paths | list | [~r{^/images/}, ~r{^/css/}, ~r{^/js/}, ~r{^/phoenix/live_reload/}] | A list of paths that should not be recorded by toolbar. Each item can be either string for exact match or a Regex. | | debug | boolean | false | Toggles debug logs. Requires recompilation for some logs | -| max_requests | integer | 30 | Number of requests to keep in history | +| requests_limit | integer | 30 | Number of requests to keep in history | # Troubleshooting diff --git a/config/config.exs b/config/config.exs index 668679b..6869f2e 100644 --- a/config/config.exs +++ b/config/config.exs @@ -7,7 +7,7 @@ config :ex_debug_toolbar, breakpoints_limit: 3, remove_glob_params: true, debug: false, - max_requests: 10 + requests_limit: 10 config :ex_debug_toolbar, ExDebugToolbar.Fixtures.Endpoint, instrumenters: [ExDebugToolbar.Collector.InstrumentationCollector], diff --git a/lib/ex_debug_toolbar/config.ex b/lib/ex_debug_toolbar/config.ex index b50ba81..666666a 100644 --- a/lib/ex_debug_toolbar/config.ex +++ b/lib/ex_debug_toolbar/config.ex @@ -2,6 +2,7 @@ Code.compiler_options(ignore_module_conflict: true) defmodule ExDebugToolbar.Config do @breakpoints_limit 10 + @requests_limit 30 def get(key, default) do Application.get_env(:ex_debug_toolbar, key, default) @@ -32,6 +33,14 @@ defmodule ExDebugToolbar.Config do Application.get_env(:ex_debug_toolbar, :breakpoints_limit, @breakpoints_limit) end + def get_requests_limit do + Application.get_env(:ex_debug_toolbar, :requests_limit, @requests_limit) + end + + def set_requests_limit(limit) do + Application.put_env(:ex_debug_toolbar, :requests_limit, limit) + end + def update do config = Application.get_env(:ex_debug_toolbar, ExDebugToolbar.Endpoint, []) |> Keyword.put(:pubsub, [name: ExDebugToolbar.PubSub, adapter: Phoenix.PubSub.PG2]) diff --git a/lib/ex_debug_toolbar/database/janitor.ex b/lib/ex_debug_toolbar/database/janitor.ex index 295c6c2..3a8b2ca 100644 --- a/lib/ex_debug_toolbar/database/janitor.ex +++ b/lib/ex_debug_toolbar/database/janitor.ex @@ -2,14 +2,14 @@ defmodule ExDebugToolbar.Database.Janitor do @moduledoc false alias ExDebugToolbar.Database.RequestRepo - alias ExDebugToolbar.Logger + alias ExDebugToolbar.{Logger, Config} alias ExDebugToolbar.Request.Broadcast use GenServer @doc "deletes requests from repository once they reach a limit" def cleanup_requests do - limit = Application.get_env(:ex_debug_toolbar, :max_requests, 30) + limit = Config.get_requests_limit() extra = max(0, RequestRepo.count() - limit) if extra > 0 do Logger.debug "Cleaning up #{extra} requests" diff --git a/test/lib/ex_debug_toolbar/database/janitor_test.exs b/test/lib/ex_debug_toolbar/database/janitor_test.exs index a39eab2..62811bb 100644 --- a/test/lib/ex_debug_toolbar/database/janitor_test.exs +++ b/test/lib/ex_debug_toolbar/database/janitor_test.exs @@ -3,14 +3,15 @@ defmodule ExDebugToolbar.Database.JanitorTest do import ExDebugToolbar.Test.Support.RequestHelpers alias ExDebugToolbar.Database.{RequestRepo, Janitor} - alias ExDebugToolbar.Request + alias ExDebugToolbar.{Request, Config} describe "cleanup_requests/0" do setup do RequestRepo.purge() - Application.put_env(:ex_debug_toolbar, :max_requests, 2) + limit = Config.get_requests_limit() + Config.set_requests_limit(2) on_exit fn -> - Application.put_env(:ex_debug_toolbar, :max_requests, 30) + Config.set_requests_limit(limit) end for n <- 1..4 do pid = spawn fn -> :ok end From 2545092bb35492b54f2a7ff5dd410c5b931d62a5 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 11:53:06 +0100 Subject: [PATCH 30/55] do not render requests in progress --- lib/ex_debug_toolbar/request.ex | 4 ++++ test/controllers/dashboard_controller_test.exs | 18 ++++++++++++++++-- .../ex_debug_toolbar/database/janitor_test.exs | 3 +++ web/controllers/dashboard_controller.ex | 5 ++++- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/ex_debug_toolbar/request.ex b/lib/ex_debug_toolbar/request.ex index cee36ee..8bd82fc 100644 --- a/lib/ex_debug_toolbar/request.ex +++ b/lib/ex_debug_toolbar/request.ex @@ -18,4 +18,8 @@ defmodule ExDebugToolbar.Request do def sort_by_date(requests) do Enum.sort(requests, &(NaiveDateTime.compare(&2.created_at, &1.created_at) == :lt)) end + + def filter_stopped(requests) do + Enum.filter(requests, &(&1.stopped?)) + end end diff --git a/test/controllers/dashboard_controller_test.exs b/test/controllers/dashboard_controller_test.exs index d284a53..3823db4 100644 --- a/test/controllers/dashboard_controller_test.exs +++ b/test/controllers/dashboard_controller_test.exs @@ -1,12 +1,26 @@ defmodule ExDebugToolbar.DashboardControllerTest do - use ExDebugToolbar.ConnCase, async: true + use ExDebugToolbar.ConnCase, async: false - setup :insert_request + setup :start_request describe "show/2" do test "it renders", %{conn: conn} do conn = get conn, "/" assert conn.status == 200 end + + test "it renders stopped requests", %{conn: conn} do + stop_request(@request_id) + + conn = get conn, "/" + {:ok, request} = get_request(@request_id) + + assert conn.assigns.requests == [request] + end + + test "it doesn't render requests in progress", %{conn: conn} do + conn = get conn, "/" + assert conn.assigns.requests == [] + end end end diff --git a/test/lib/ex_debug_toolbar/database/janitor_test.exs b/test/lib/ex_debug_toolbar/database/janitor_test.exs index 62811bb..76a7285 100644 --- a/test/lib/ex_debug_toolbar/database/janitor_test.exs +++ b/test/lib/ex_debug_toolbar/database/janitor_test.exs @@ -16,6 +16,9 @@ defmodule ExDebugToolbar.Database.JanitorTest do for n <- 1..4 do pid = spawn fn -> :ok end :ok = RequestRepo.insert %Request{pid: pid, uuid: n} + on_exit fn -> + delete_request(n) + end end :ok end diff --git a/web/controllers/dashboard_controller.ex b/web/controllers/dashboard_controller.ex index 9d14464..0514064 100644 --- a/web/controllers/dashboard_controller.ex +++ b/web/controllers/dashboard_controller.ex @@ -7,7 +7,10 @@ defmodule ExDebugToolbar.DashboardController do plug :put_layout, {ExDebugToolbar.DashboardLayoutView, :app} def index(conn, _) do - requests = ExDebugToolbar.get_all_requests() |> Request.sort_by_date + requests = + ExDebugToolbar.get_all_requests() + |> Request.filter_stopped + |> Request.sort_by_date conn |> assign(:requests, requests) |> render("index.html") From ec7becc44147bb6317a50dd285ceae7f5cb092e8 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 12:11:01 +0100 Subject: [PATCH 31/55] correctly print log for new request in dashboard --- web/static/js/dashboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index 3239547..696b3bf 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -49,7 +49,7 @@ class App { } onRequestCreated(data){ - this.logger.debug('Adding request', data.uuid, data.request); + this.logger.debug('Adding request', data.request.uuid, data.request); $(data.html).prependTo('#requests-history > tbody'); this.requestCountEl.text(++this.requestsCount); if (this.requestsCount == 1) { From 4ae4cbdad3e106227e7566cb5cf8e2a02cf9cee0 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Wed, 6 Dec 2017 18:09:03 +0100 Subject: [PATCH 32/55] moved request stop into request repo --- lib/ex_debug_toolbar.ex | 18 +-- lib/ex_debug_toolbar/database/request_repo.ex | 43 ++++- .../database/request_repo_test.exs | 152 ++++++++++++------ 3 files changed, 150 insertions(+), 63 deletions(-) diff --git a/lib/ex_debug_toolbar.ex b/lib/ex_debug_toolbar.ex index df672e9..d4f2d28 100644 --- a/lib/ex_debug_toolbar.ex +++ b/lib/ex_debug_toolbar.ex @@ -36,7 +36,7 @@ defmodule ExDebugToolbar do @spec stop_request(id) :: ok @decorate noop_when_toolbar_disabled() def stop_request(id) do - :ok = RequestRepo.update(id, &(%{&1 | stopped?: true}), async: false) + :ok = RequestRepo.stop(id) end @doc """ @@ -44,25 +44,23 @@ defmodule ExDebugToolbar do """ @spec delete_request(uuid) :: ok @decorate noop_when_toolbar_disabled() - def delete_request(uuid) do - RequestRepo.delete(uuid) - end + defdelegate delete_request(uuid), to: RequestRepo, as: :delete @doc """ Returns total number of tracked requests + + *Note*: this count excludes requests in progress """ @spec get_requests_count :: integer @decorate noop_when_toolbar_disabled(0) - defdelegate get_requests_count, to: RequestRepo, as: :count + defdelegate get_requests_count, to: RequestRepo, as: :stopped_count @doc """ Returns request matching provided `id`, which defaults to `self()` """ @spec get_request(id) :: Request.t() @decorate noop_when_toolbar_disabled() - def get_request(id \\ self()) do - RequestRepo.get(id) - end + defdelegate get_request(id \\ self()), to: RequestRepo, as: :get @doc """ Returns the breakpoint @@ -81,9 +79,7 @@ defmodule ExDebugToolbar do """ @spec get_all_requests() :: [Request.t()] @decorate noop_when_toolbar_disabled([]) - def get_all_requests do - RequestRepo.all - end + defdelegate get_all_requests, to: RequestRepo, as: :all @doc """ Starts a timeline event `name` in request identified by `id`, which defaults to `self()` diff --git a/lib/ex_debug_toolbar/database/request_repo.ex b/lib/ex_debug_toolbar/database/request_repo.ex index a2a9fa4..ecb1038 100644 --- a/lib/ex_debug_toolbar/database/request_repo.ex +++ b/lib/ex_debug_toolbar/database/request_repo.ex @@ -9,7 +9,8 @@ defmodule ExDebugToolbar.Database.RequestRepo do requests: %{}, pids_to_uuids: %{}, queue: :queue.new(), - count: 0 + count: 0, + stopped_count: 0 ] end @@ -26,6 +27,10 @@ defmodule ExDebugToolbar.Database.RequestRepo do end end + def stop(id) do + GenServer.call(__MODULE__, {:stop, id}, :infinity) + end + def all do GenServer.call(__MODULE__, :all) end @@ -42,6 +47,10 @@ defmodule ExDebugToolbar.Database.RequestRepo do GenServer.call(__MODULE__, :count) end + def stopped_count do + GenServer.call(__MODULE__, :stopped_count) + end + def get(id) do GenServer.call(__MODULE__, {:get, id}) end @@ -92,6 +101,22 @@ defmodule ExDebugToolbar.Database.RequestRepo do {:reply, :ok, state} end + def handle_call({:stop, id}, _from, state) do + {reply, state} = + case do_get(id, state) do + {:ok, %{stopped?: true}} -> + {:ok, state} + {:ok, request} -> + request = %{request | stopped?: true} + state = state + |> Map.update!(:requests, &Map.put(&1, request.uuid, request)) + |> Map.update!(:stopped_count, &(&1 + 1)) + {:ok, state} + _ -> {:error, state} + end + {:reply, reply, state} + end + def handle_call({:get, id}, _from, state) do {:reply, do_get(id, state), state} end @@ -108,6 +133,10 @@ defmodule ExDebugToolbar.Database.RequestRepo do {:reply, state.count, state} end + def handle_call(:stopped_count, _from, state) do + {:reply, state.stopped_count, state} + end + def handle_call({:pop, n}, _from, state) do len = min(n, state.count) {state, removed} = 1..len |> Enum.reduce({state, []}, fn _, {state, removed} -> @@ -148,9 +177,10 @@ defmodule ExDebugToolbar.Database.RequestRepo do defp delete_request(state, request) do state - |> Map.update!(:requests, &Map.delete(&1, request.uuid)) - |> Map.update!(:pids_to_uuids, &Map.delete(&1, request.pid)) - |> Map.update!(:count, &(&1 - 1)) + |> Map.update!(:requests, &Map.delete(&1, request.uuid)) + |> Map.update!(:pids_to_uuids, &Map.delete(&1, request.pid)) + |> Map.update!(:count, &(&1 - 1)) + |> dec_stopped_count(request) end defp apply_changes(request, changes) when is_map(changes) do @@ -159,4 +189,9 @@ defmodule ExDebugToolbar.Database.RequestRepo do defp apply_changes(request, changes) when is_function(changes) do changes.(request) end + + defp dec_stopped_count(state, %{stopped?: true}) do + state |> Map.update!(:stopped_count, &(&1 - 1)) + end + defp dec_stopped_count(state, _), do: state end diff --git a/test/lib/ex_debug_toolbar/database/request_repo_test.exs b/test/lib/ex_debug_toolbar/database/request_repo_test.exs index 7a6d951..fef475a 100644 --- a/test/lib/ex_debug_toolbar/database/request_repo_test.exs +++ b/test/lib/ex_debug_toolbar/database/request_repo_test.exs @@ -32,18 +32,10 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do end test "returns request by pid", %{request: request} do - self_pid = self() - pid = spawn fn -> + pid = run_in_new_process fn _ -> request = %{request | pid: self()} :ok = RequestRepo.insert(request) - send self_pid, :done end - msg = receive do - :done -> :ok - after - 200 -> :error - end - assert msg == :ok assert {:ok, request} = RequestRepo.get(pid) assert request.uuid == @request_id end @@ -73,17 +65,9 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do end test "acceps pid instead of id" do - pid = self() - spawn fn -> - assert :ok = RequestRepo.update(pid, %{logs: [:bar]}) - send pid, :done - end - msg = receive do - :done -> :ok - after - 200 -> :error + run_in_new_process fn test_pid -> + assert :ok = RequestRepo.update(test_pid, %{logs: [:bar]}) end - assert msg == :ok assert {:ok, updated_request} = get_request(@request_id) assert updated_request.logs == [:bar] end @@ -112,35 +96,24 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do end test "returns all requests" do - pid_1 = spawn fn -> :ok end - pid_2 = spawn fn -> :ok end - requests = [%Request{pid: pid_1, uuid: 1}, %Request{pid: pid_2, uuid: 2}] - for request <- requests do - :ok = RequestRepo.insert(request) - end + requests = insert_requests(2) assert requests == RequestRepo.all |> Enum.sort_by(&(&1.uuid)) end end describe "delete/1" do setup do - pid_1 = spawn fn -> :ok end - pid_2 = spawn fn -> :ok end - requests = [%Request{pid: pid_1, uuid: 1}, %Request{pid: pid_2, uuid: 2}] - for request <- requests do - :ok = RequestRepo.insert(request) - end - {:ok, %{requests: requests, pids: [pid_1, pid_2]}} + [requests: insert_requests(2)] end - test "deletes request by id", context do + test "deletes request by id", %{requests: requests}do assert :ok = RequestRepo.delete(1) - assert RequestRepo.all() == context.requests |> tl + assert RequestRepo.all() == requests |> tl end - test "deletes request by pid", context do - assert :ok = context.pids |> List.last |> RequestRepo.delete - assert RequestRepo.all() == context.requests |> Enum.reverse |> tl + test "deletes request by pid", %{requests: requests} do + assert :ok = requests |> List.last |> Map.get(:pid) |> RequestRepo.delete + assert RequestRepo.all() == requests |> Enum.reverse |> tl end test "it returns error if request doesn't exist" do @@ -155,31 +128,68 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do assert RequestRepo.all() == [] end + describe "stopped_count/0" do + setup do + [stopped_request, running_request] = insert_requests(2) + RequestRepo.stop(stopped_request.uuid) + [stopped_request: stopped_request, running_request: running_request] + end + + test "counts only stopped requests" do + assert RequestRepo.stopped_count() == 1 + end + + test "number of requests after deleting stopped request", %{stopped_request: request} do + RequestRepo.delete(request.uuid) + assert RequestRepo.stopped_count() == 0 + end + + test "number of requests after deleting running request", %{running_request: request} do + RequestRepo.delete(request.uuid) + assert RequestRepo.stopped_count() == 1 + end + + test "number of requests after purging" do + RequestRepo.purge() + assert RequestRepo.stopped_count() == 0 + end + + test "number of requests after popping stopped request" do + RequestRepo.pop(1) + assert RequestRepo.stopped_count() == 0 + end + + test "number of requests after popping running request" do + [request] = insert_requests(1) # adds stopped at the end + RequestRepo.stop(request.uuid) + RequestRepo.pop(2) # pop one stopped and one running + assert RequestRepo.stopped_count() == 1 + end + end + describe "count/0" do test "number of requests after inserting" do - pid_1 = spawn fn -> :ok end - pid_2 = spawn fn -> :ok end assert RequestRepo.count == 0 - :ok = RequestRepo.insert(%Request{pid: pid_1, uuid: 1}) + insert_requests(1) assert RequestRepo.count == 1 - :ok = RequestRepo.insert(%Request{pid: pid_2, uuid: 2}) + insert_requests(1) assert RequestRepo.count == 2 end test "number of requests after deleting" do - :ok = RequestRepo.insert(%Request{pid: self(), uuid: 1}) + insert_requests(1) RequestRepo.delete(1) assert RequestRepo.count() == 0 end test "number of requests after purging" do - :ok = RequestRepo.insert(%Request{pid: self(), uuid: 1}) + insert_requests(1) RequestRepo.purge() assert RequestRepo.count() == 0 end test "number of requests after popping" do - :ok = RequestRepo.insert(%Request{pid: self(), uuid: 1}) + insert_requests(1) RequestRepo.pop(1) assert RequestRepo.count() == 0 end @@ -187,10 +197,7 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do describe "pop/1" do setup do - for n <- 1..3 do - pid = spawn fn -> :ok end - :ok = RequestRepo.insert %Request{pid: pid, uuid: n} - end + insert_requests(3) :ok end @@ -234,8 +241,57 @@ defmodule ExDebugToolbar.Database.RequestRepoTest do end end + describe "stop/1" do + test "flags request as stopped", %{request: request} do + :ok = RequestRepo.insert(request) + {:ok, request} = RequestRepo.get(@request_id) + refute request.stopped? + :ok = RequestRepo.stop(@request_id) + {:ok, request} = RequestRepo.get(@request_id) + assert request.stopped? + end + + test "accepts pid as id", %{request: request} do + :ok = RequestRepo.insert(request) + run_in_new_process fn test_pid -> + :ok = RequestRepo.stop(test_pid) + end + {:ok, request} = RequestRepo.get(@request_id) + assert request.stopped? + end + end + defp cleanup_requests do :ok = Supervisor.terminate_child(ExDebugToolbar.Supervisor, RequestRepo) {:ok, _} = Supervisor.restart_child(ExDebugToolbar.Supervisor, RequestRepo) end + + defp run_in_new_process(fun) do + test_pid = self() + pid = spawn fn -> + fun.(test_pid) + send test_pid, :done + end + :ok = receive do + :done -> :ok + after + 200 -> :error + end + pid + end + + defp insert_requests(count) do + requests = + fn -> :ok end + |> List.duplicate(count) + |> Stream.map(&spawn/1) + |> Stream.zip(1..count) + |> Enum.map(fn {pid, uuid} -> + %Request{pid: pid, uuid: uuid} + end) + + requests |> Enum.each(&RequestRepo.insert/1) + + requests + end end From d896d2b01b53b96f629cd102a95838c849b38ea1 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Fri, 5 Jan 2018 13:25:17 +0100 Subject: [PATCH 33/55] bump elixir version in travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a1d119a..b070c70 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: elixir elixir: - - 1.5.1 + - 1.5.3 - 1.4.5 otp_release: - 20.0 From b32fd38a0f4db7a5bee5867a70bcfa69a3abadfc Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Fri, 5 Jan 2018 13:25:49 +0100 Subject: [PATCH 34/55] renamed dashboard controller into dashboard/request_controller --- .../request_controller_test.exs} | 4 ++-- web/channels/dashboard_channel.ex | 4 ++-- .../request_controller.ex} | 2 +- web/router.ex | 4 ++-- web/templates/dashboard/{ => request}/index.html.eex | 0 .../dashboard/{ => request}/index/_request_table_row.html.eex | 0 .../dashboard/{ => request}/index/_requests_table.html.eex | 2 +- web/templates/dashboard_layout/app.html.eex | 2 +- web/views/{dashboard_view.ex => dashboard/request_view.ex} | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename test/controllers/{dashboard_controller_test.exs => dashboard/request_controller_test.exs} (86%) rename web/controllers/{dashboard_controller.ex => dashboard/request_controller.ex} (87%) rename web/templates/dashboard/{ => request}/index.html.eex (100%) rename web/templates/dashboard/{ => request}/index/_request_table_row.html.eex (100%) rename web/templates/dashboard/{ => request}/index/_requests_table.html.eex (78%) rename web/views/{dashboard_view.ex => dashboard/request_view.ex} (75%) diff --git a/test/controllers/dashboard_controller_test.exs b/test/controllers/dashboard/request_controller_test.exs similarity index 86% rename from test/controllers/dashboard_controller_test.exs rename to test/controllers/dashboard/request_controller_test.exs index 3823db4..30e6132 100644 --- a/test/controllers/dashboard_controller_test.exs +++ b/test/controllers/dashboard/request_controller_test.exs @@ -1,9 +1,9 @@ -defmodule ExDebugToolbar.DashboardControllerTest do +defmodule ExDebugToolbar.Dashboard.RequestControllerTest do use ExDebugToolbar.ConnCase, async: false setup :start_request - describe "show/2" do + describe "index/2" do test "it renders", %{conn: conn} do conn = get conn, "/" assert conn.status == 200 diff --git a/web/channels/dashboard_channel.ex b/web/channels/dashboard_channel.ex index b0710ce..c98561a 100644 --- a/web/channels/dashboard_channel.ex +++ b/web/channels/dashboard_channel.ex @@ -2,7 +2,7 @@ defmodule ExDebugToolbar.DashboardChannel do @moduledoc false use ExDebugToolbar.Web, :channel - alias ExDebugToolbar.DashboardView + alias ExDebugToolbar.Dashboard.RequestView alias Phoenix.View def join("dashboard:history" = topic, _payload, socket) do @@ -23,7 +23,7 @@ defmodule ExDebugToolbar.DashboardChannel do defp build_payload(request) do PayloadHelpers.build_request_payload(request, fn -> - View.render_to_string(DashboardView, "index/_request_table_row.html", request: request) + View.render_to_string(RequestView, "index/_request_table_row.html", request: request) end) end end diff --git a/web/controllers/dashboard_controller.ex b/web/controllers/dashboard/request_controller.ex similarity index 87% rename from web/controllers/dashboard_controller.ex rename to web/controllers/dashboard/request_controller.ex index 0514064..cb40306 100644 --- a/web/controllers/dashboard_controller.ex +++ b/web/controllers/dashboard/request_controller.ex @@ -1,4 +1,4 @@ -defmodule ExDebugToolbar.DashboardController do +defmodule ExDebugToolbar.Dashboard.RequestController do @moduledoc false use ExDebugToolbar.Web, :controller diff --git a/web/router.ex b/web/router.ex index 3c60051..36fbcbd 100644 --- a/web/router.ex +++ b/web/router.ex @@ -11,8 +11,8 @@ defmodule ExDebugToolbar.Router do plug :put_secure_browser_headers end - scope "/", ExDebugToolbar do + scope "/", ExDebugToolbar.Dashboard do pipe_through :browser - get "/", DashboardController, :index + get "/", RequestController, :index end end diff --git a/web/templates/dashboard/index.html.eex b/web/templates/dashboard/request/index.html.eex similarity index 100% rename from web/templates/dashboard/index.html.eex rename to web/templates/dashboard/request/index.html.eex diff --git a/web/templates/dashboard/index/_request_table_row.html.eex b/web/templates/dashboard/request/index/_request_table_row.html.eex similarity index 100% rename from web/templates/dashboard/index/_request_table_row.html.eex rename to web/templates/dashboard/request/index/_request_table_row.html.eex diff --git a/web/templates/dashboard/index/_requests_table.html.eex b/web/templates/dashboard/request/index/_requests_table.html.eex similarity index 78% rename from web/templates/dashboard/index/_requests_table.html.eex rename to web/templates/dashboard/request/index/_requests_table.html.eex index 929231c..c54979a 100644 --- a/web/templates/dashboard/index/_requests_table.html.eex +++ b/web/templates/dashboard/request/index/_requests_table.html.eex @@ -10,7 +10,7 @@ Timestamp - <%= render_many @requests, ExDebugToolbar.DashboardView, "index/_request_table_row.html", as: :request %> + <%= render_many @requests, ExDebugToolbar.Dashboard.RequestView, "index/_request_table_row.html", as: :request %> diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index 9a7518a..1802ff3 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -20,7 +20,7 @@
- diff --git a/web/templates/dashboard/request/show/_request.html.eex b/web/templates/dashboard/request/show/_request.html.eex new file mode 100644 index 0000000..7baad5c --- /dev/null +++ b/web/templates/dashboard/request/show/_request.html.eex @@ -0,0 +1 @@ +request details From 76cd0bc47aef21665429d80e9699bf8c2183dc7b Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Fri, 5 Jan 2018 14:43:58 +0100 Subject: [PATCH 36/55] simple mock up of single request page --- .../dashboard/request/show/_request.html.eex | 46 ++++++++++++++++++- web/templates/dashboard_layout/app.html.eex | 2 +- web/views/dashboard/request_view.ex | 6 ++- 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/web/templates/dashboard/request/show/_request.html.eex b/web/templates/dashboard/request/show/_request.html.eex index 7baad5c..01345e8 100644 --- a/web/templates/dashboard/request/show/_request.html.eex +++ b/web/templates/dashboard/request/show/_request.html.eex @@ -1 +1,45 @@ -request details + diff --git a/web/templates/dashboard_layout/app.html.eex b/web/templates/dashboard_layout/app.html.eex index 1802ff3..21af507 100644 --- a/web/templates/dashboard_layout/app.html.eex +++ b/web/templates/dashboard_layout/app.html.eex @@ -45,7 +45,7 @@ diff --git a/web/templates/toolbar/show/_ecto.html.eex b/web/templates/toolbar/show/_ecto.html.eex index 6827048..a6bba5c 100644 --- a/web/templates/toolbar/show/_ecto.html.eex +++ b/web/templates/toolbar/show/_ecto.html.eex @@ -1,19 +1,17 @@ - <%= length @queries %> + <%= length(@queries.inline) + length(@queries.parallel) %> diff --git a/web/templates/toolbar/show/_timeline.html.eex b/web/templates/toolbar/show/_timeline.html.eex index 8a33444..3a64ef6 100644 --- a/web/templates/toolbar/show/_timeline.html.eex +++ b/web/templates/toolbar/show/_timeline.html.eex @@ -34,7 +34,7 @@ Average - <%= for {name, stats} <- rendered_templates(@timeline) do %> + <%= for {name, stats} <- Timeline.templates_duration_breakdown(@timeline) do %> <%= name %> <%= stats.count %> diff --git a/web/views/toolbar_view.ex b/web/views/toolbar_view.ex index 1bb40b5..ab1066a 100644 --- a/web/views/toolbar_view.ex +++ b/web/views/toolbar_view.ex @@ -30,30 +30,6 @@ defmodule ExDebugToolbar.ToolbarView do end end - def rendered_templates(%Timeline{} = timeline) do - timeline - |> Timeline.get_all_events - |> Stream.filter(&String.starts_with?(&1.name, "template#")) - |> Enum.reduce(%{}, fn event, acc -> - Map.update( - acc, - event.name, - %{count: 1, durations: [event.duration], min: 0, max: 0, avg: 0, total: 0}, - &(%{&1 | count: &1.count + 1, durations: [event.duration | &1.durations]}) - ) - end) - |> Stream.map(fn {name, stats} -> - {name, %{stats | - min: Enum.min(stats.durations), - max: Enum.max(stats.durations), - total: Enum.sum(stats.durations), - avg: div(Enum.sum(stats.durations), Enum.count(stats.durations)) - }} - end) - |> Stream.map(fn {name, stats} -> {String.trim_leading(name, "template#"), stats} end) - |> Enum.sort_by(fn {_, stats} -> -stats.total end) - end - def stats_popover_text(stats) do ~w(min max total)a |> Stream.map(&Map.get(stats, &1)) @@ -63,14 +39,6 @@ defmodule ExDebugToolbar.ToolbarView do |> Enum.join("
") end - def ecto_inline_queries(queries) do - queries |> Enum.filter(fn {_, _, type} -> type == :inline end) - end - - def ecto_parallel_queries(queries) do - queries |> Enum.filter(fn {_, _, type} -> type == :parallel end) - end - def breakpoint_code_snippet_start_line(%Breakpoint{code_snippet: code_snippet}) do code_snippet |> hd |> Tuple.to_list |> List.last end From 8848127200c38382a0ebedec4a91a79adb262499 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Sun, 21 Jan 2018 23:01:59 +0100 Subject: [PATCH 46/55] moved breakpoint related code from view to Breakpoint --- lib/ex_debug_toolbar/breakpoint.ex | 19 ++++++++++++++++++ test/channels/breakpoint_channel_test.exs | 4 ++-- .../toolbar/show/_breakpoints.html.eex | 8 ++++---- web/views/toolbar_view.ex | 20 ------------------- web/web.ex | 3 ++- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/ex_debug_toolbar/breakpoint.ex b/lib/ex_debug_toolbar/breakpoint.ex index 1d42dad..9529be1 100644 --- a/lib/ex_debug_toolbar/breakpoint.ex +++ b/lib/ex_debug_toolbar/breakpoint.ex @@ -2,6 +2,7 @@ defmodule ExDebugToolbar.Breakpoint do @moduledoc false alias ExDebugToolbar.Breakpoint.{IEx.Server, Pry} + alias ExDebugToolbar.{Breakpoint, Request} defstruct [ :id, @@ -34,4 +35,22 @@ defmodule ExDebugToolbar.Breakpoint do term -> raise ArgumentError, "Expected string to be base64 encoded %Breakpoint{}, but got #{inspect(term)}" end end + + def get_code_snippet_start_line(%Breakpoint{code_snippet: code_snippet}) do + code_snippet |> hd |> Tuple.to_list |> List.last + end + + def get_sorted_binding(%Breakpoint{binding: binding}) do + binding |> Keyword.keys |> Enum.sort + end + + def get_relative_line(%Breakpoint{code_snippet: code_snippet, line: line}) do + code_snippet + |> Enum.find_index(fn {_, n} -> n == line end) + |> Kernel.+(1) + end + + def get_uuid(%Request{uuid: request_id}, %Breakpoint{id: id}) do + %Breakpoint.UUID{request_id: request_id, breakpoint_id: id} + end end diff --git a/test/channels/breakpoint_channel_test.exs b/test/channels/breakpoint_channel_test.exs index 50d3e16..5b76981 100644 --- a/test/channels/breakpoint_channel_test.exs +++ b/test/channels/breakpoint_channel_test.exs @@ -2,7 +2,7 @@ defmodule ExDebugToolbar.BreakpointChannelTest do use ExDebugToolbar.ChannelCase, async: true alias ExDebugToolbar.BreakpointChannel - alias ExDebugToolbar.ToolbarView + alias ExDebugToolbar.Breakpoint require ExDebugToolbar setup :start_request @@ -12,7 +12,7 @@ defmodule ExDebugToolbar.BreakpointChannelTest do :timer.sleep 500 {:ok, request} = get_request() breakpoint = request.breakpoints.entries |> Map.values |> hd - topic = "breakpoint:#{ToolbarView.breakpoint_uuid(request, breakpoint)}" + topic = "breakpoint:#{Breakpoint.get_uuid(request, breakpoint)}" # initial output {:ok, _, socket} = socket() |> subscribe_and_join(BreakpointChannel, topic, %{}) diff --git a/web/templates/toolbar/show/_breakpoints.html.eex b/web/templates/toolbar/show/_breakpoints.html.eex index 03e13ac..e17527d 100644 --- a/web/templates/toolbar/show/_breakpoints.html.eex +++ b/web/templates/toolbar/show/_breakpoints.html.eex @@ -19,7 +19,7 @@ <%= for {_id, breakpoint} <- @breakpoints.entries do %> <%= breakpoint.inserted_at %> <%= breakpoint.file %> @@ -28,8 +28,8 @@ From fcad56ec73bd3623c97bf291d8d0433df59bc9a6 Mon Sep 17 00:00:00 2001 From: Boris Mikhaylov Date: Mon, 12 Mar 2018 10:15:06 +0100 Subject: [PATCH 54/55] show some parameters in overview tab --- priv/static/css/dashboard.css | 190 +++ priv/static/js/dashboard.js | 1363 ++++++++++++++++- priv/static/js/toolbar.js | 89 +- web/static/css/dashboard.scss | 4 + web/static/js/dashboard.js | 3 + web/static/js/lib/highlight.js | 23 + web/static/js/toolbar.js | 23 +- .../dashboard/request/show/_overview.html.eex | 33 + .../dashboard/request/show/_request.html.eex | 27 +- 9 files changed, 1685 insertions(+), 70 deletions(-) create mode 100644 web/static/js/lib/highlight.js create mode 100644 web/templates/dashboard/request/show/_overview.html.eex diff --git a/priv/static/css/dashboard.css b/priv/static/css/dashboard.css index 46033f3..6faf63c 100644 --- a/priv/static/css/dashboard.css +++ b/priv/static/css/dashboard.css @@ -13941,6 +13941,196 @@ table.text-center th { border-bottom-right-radius: 2px; border-bottom-left-radius: 0; } +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +code[class*="language-"], +pre[class*="language-"] { + color: black; + background: none; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + word-wrap: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; } + +pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, +code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { + text-shadow: none; + background: #b3d4fc; } + +pre[class*="language-"]::selection, pre[class*="language-"] ::selection, +code[class*="language-"]::selection, code[class*="language-"] ::selection { + text-shadow: none; + background: #b3d4fc; } + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; } } + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; } + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; } + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; + white-space: normal; } + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; } + +.token.punctuation { + color: #999; } + +.namespace { + opacity: .7; } + +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #905; } + +.token.selector, +.token.attr-name, +.token.string, +.token.char, +.token.builtin, +.token.inserted { + color: #690; } + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: rgba(255, 255, 255, 0.5); } + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; } + +.token.function { + color: #DD4A68; } + +.token.regex, +.token.important, +.token.variable { + color: #e90; } + +.token.important, +.token.bold { + font-weight: bold; } + +.token.italic { + font-style: italic; } + +.token.entity { + cursor: help; } + +pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; } + +pre.line-numbers > code { + position: relative; } + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; + /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + +.line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; } + +.line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; } + +pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; } + +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; + /* Same as .prism’s padding-top */ + background: rgba(153, 122, 102, 0.08); + background: linear-gradient(to right, rgba(153, 122, 102, 0.1) 70%, rgba(153, 122, 102, 0)); + pointer-events: none; + line-height: inherit; + white-space: pre; } + +.line-highlight:before, +.line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: rgba(153, 122, 102, 0.4); + color: #f5f2f0; + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; } + +.line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; } + .invisible-row { display: none; } diff --git a/priv/static/js/dashboard.js b/priv/static/js/dashboard.js index 74f69a5..85b4816 100644 --- a/priv/static/js/dashboard.js +++ b/priv/static/js/dashboard.js @@ -14249,6 +14249,1304 @@ var Timer = function () { })(); }); +require.register("prismjs/components/prism-elixir.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "prismjs"); + (function() { + Prism.languages.elixir = { + // Negative look-ahead is needed for string interpolation + // Negative look-behind is needed to avoid highlighting markdown headers in + // multi-line doc strings + 'comment': { + pattern: /(^|[^#])#(?![{#]).*/m, + lookbehind: true + }, + // ~r"""foo""", ~r'''foo''', ~r/foo/, ~r|foo|, ~r"foo", ~r'foo', ~r(foo), ~r[foo], ~r{foo}, ~r + 'regex': /~[rR](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|[^}])+\}|<(?:\\>|[^>])+>)[uismxfr]*/, + 'string': [ + { + // ~s"""foo""", ~s'''foo''', ~s/foo/, ~s|foo|, ~s"foo", ~s'foo', ~s(foo), ~s[foo], ~s{foo}, ~s + pattern: /~[cCsSwW](?:("""|'''|[\/|"'])(?:\\.|(?!\1)[^\\])+\1|\((?:\\\)|[^)])+\)|\[(?:\\\]|[^\]])+\]|\{(?:\\\}|#\{[^}]+\}|[^}])+\}|<(?:\\>|[^>])+>)[csa]?/, + inside: { + // See interpolation below + } + }, + { + pattern: /("""|''')[\s\S]*?\1/, + inside: { + // See interpolation below + } + }, + { + // Multi-line strings are allowed + pattern: /("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/, + inside: { + // See interpolation below + } + } + ], + 'atom': { + // Look-behind prevents bad highlighting of the :: operator + pattern: /(^|[^:]):\w+/, + lookbehind: true, + alias: 'symbol' + }, + // Look-ahead prevents bad highlighting of the :: operator + 'attr-name': /\w+:(?!:)/, + 'capture': { + // Look-behind prevents bad highlighting of the && operator + pattern: /(^|[^&])&(?:[^&\s\d()][^\s()]*|(?=\())/, + lookbehind: true, + alias: 'function' + }, + 'argument': { + // Look-behind prevents bad highlighting of the && operator + pattern: /(^|[^&])&\d+/, + lookbehind: true, + alias: 'variable' + }, + 'attribute': { + pattern: /@[\S]+/, + alias: 'variable' + }, + 'number': /\b(?:0[box][a-f\d_]+|\d[\d_]*)(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?\b/i, + 'keyword': /\b(?:after|alias|and|case|catch|cond|def(?:callback|exception|impl|module|p|protocol|struct)?|do|else|end|fn|for|if|import|not|or|require|rescue|try|unless|use|when)\b/, + 'boolean': /\b(?:true|false|nil)\b/, + 'operator': [ + /\bin\b|&&?|\|[|>]?|\\\\|::|\.\.\.?|\+\+?|-[->]?|<[-=>]|>=|!==?|\B!|=(?:==?|[>~])?|[*\/^]/, + { + // We don't want to match << + pattern: /([^<])<(?!<)/, + lookbehind: true + }, + { + // We don't want to match >> + pattern: /([^>])>(?!>)/, + lookbehind: true + } + ], + 'punctuation': /<<|>>|[.,%\[\]{}()]/ +}; + +Prism.languages.elixir.string.forEach(function(o) { + o.inside = { + 'interpolation': { + pattern: /#\{[^}]+\}/, + inside: { + 'delimiter': { + pattern: /^#\{|\}$/, + alias: 'punctuation' + }, + rest: Prism.util.clone(Prism.languages.elixir) + } + } + }; +}); + })(); +}); + +require.register("prismjs/components/prism-sql.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "prismjs"); + (function() { + Prism.languages.sql= { + 'comment': { + pattern: /(^|[^\\])(?:\/\*[\w\W]*?\*\/|(?:--|\/\/|#).*)/, + lookbehind: true + }, + 'string' : { + pattern: /(^|[^@\\])("|')(?:\\?[\s\S])*?\2/, + lookbehind: true + }, + 'variable': /@[\w.$]+|@("|'|`)(?:\\?[\s\S])+?\1/, + 'function': /\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i, // Should we highlight user defined functions too? + 'keyword': /\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i, + 'boolean': /\b(?:TRUE|FALSE|NULL)\b/i, + 'number': /\b-?(?:0x)?\d*\.?[\da-f]+\b/, + 'operator': /[-+*\/=%^~]|&&?|\|?\||!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i, + 'punctuation': /[;[\]()`,.]/ +}; + })(); +}); + +require.register("prismjs/plugins/line-highlight/prism-line-highlight.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "prismjs"); + (function() { + (function(){ + +if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) { + return; +} + +function $$(expr, con) { + return Array.prototype.slice.call((con || document).querySelectorAll(expr)); +} + +function hasClass(element, className) { + className = " " + className + " "; + return (" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf(className) > -1 +} + +// Some browsers round the line-height, others don't. +// We need to test for it to position the elements properly. +var isLineHeightRounded = (function() { + var res; + return function() { + if(typeof res === 'undefined') { + var d = document.createElement('div'); + d.style.fontSize = '13px'; + d.style.lineHeight = '1.5'; + d.style.padding = 0; + d.style.border = 0; + d.innerHTML = ' 
 '; + document.body.appendChild(d); + // Browsers that round the line-height should have offsetHeight === 38 + // The others should have 39. + res = d.offsetHeight === 38; + document.body.removeChild(d); + } + return res; + } +}()); + +function highlightLines(pre, lines, classes) { + var ranges = lines.replace(/\s+/g, '').split(','), + offset = +pre.getAttribute('data-line-offset') || 0; + + var parseMethod = isLineHeightRounded() ? parseInt : parseFloat; + var lineHeight = parseMethod(getComputedStyle(pre).lineHeight); + + for (var i=0, range; range = ranges[i++];) { + range = range.split('-'); + + var start = +range[0], + end = +range[1] || start; + + var line = document.createElement('div'); + + line.textContent = Array(end - start + 2).join(' \n'); + line.setAttribute('aria-hidden', 'true'); + line.className = (classes || '') + ' line-highlight'; + + //if the line-numbers plugin is enabled, then there is no reason for this plugin to display the line numbers + if(!hasClass(pre, 'line-numbers')) { + line.setAttribute('data-start', start); + + if(end > start) { + line.setAttribute('data-end', end); + } + } + + line.style.top = (start - offset - 1) * lineHeight + 'px'; + + //allow this to play nicely with the line-numbers plugin + if(hasClass(pre, 'line-numbers')) { + //need to attack to pre as when line-numbers is enabled, the code tag is relatively which screws up the positioning + pre.appendChild(line); + } else { + (pre.querySelector('code') || pre).appendChild(line); + } + } +} + +function applyHash() { + var hash = location.hash.slice(1); + + // Remove pre-existing temporary lines + $$('.temporary.line-highlight').forEach(function (line) { + line.parentNode.removeChild(line); + }); + + var range = (hash.match(/\.([\d,-]+)$/) || [,''])[1]; + + if (!range || document.getElementById(hash)) { + return; + } + + var id = hash.slice(0, hash.lastIndexOf('.')), + pre = document.getElementById(id); + + if (!pre) { + return; + } + + if (!pre.hasAttribute('data-line')) { + pre.setAttribute('data-line', ''); + } + + highlightLines(pre, range, 'temporary '); + + document.querySelector('.temporary.line-highlight').scrollIntoView(); +} + +var fakeTimer = 0; // Hack to limit the number of times applyHash() runs + +Prism.hooks.add('complete', function(env) { + var pre = env.element.parentNode; + var lines = pre && pre.getAttribute('data-line'); + + if (!pre || !lines || !/pre/i.test(pre.nodeName)) { + return; + } + + clearTimeout(fakeTimer); + + $$('.line-highlight', pre).forEach(function (line) { + line.parentNode.removeChild(line); + }); + + highlightLines(pre, lines); + + fakeTimer = setTimeout(applyHash, 1); +}); + +if(window.addEventListener) { + window.addEventListener('hashchange', applyHash); +} + +})(); + })(); +}); + +require.register("prismjs/plugins/line-numbers/prism-line-numbers.js", function(exports, require, module) { + require = __makeRelativeRequire(require, {}, "prismjs"); + (function() { + (function() { + +if (typeof self === 'undefined' || !self.Prism || !self.document) { + return; +} + +Prism.hooks.add('complete', function (env) { + if (!env.code) { + return; + } + + // works only for wrapped inside
 (not inline)
+	var pre = env.element.parentNode;
+	var clsReg = /\s*\bline-numbers\b\s*/;
+	if (
+		!pre || !/pre/i.test(pre.nodeName) ||
+			// Abort only if nor the 
 nor the  have the class
+		(!clsReg.test(pre.className) && !clsReg.test(env.element.className))
+	) {
+		return;
+	}
+
+	if (env.element.querySelector(".line-numbers-rows")) {
+		// Abort if line numbers already exists
+		return;
+	}
+
+	if (clsReg.test(env.element.className)) {
+		// Remove the class "line-numbers" from the 
+		env.element.className = env.element.className.replace(clsReg, '');
+	}
+	if (!clsReg.test(pre.className)) {
+		// Add the class "line-numbers" to the 
+		pre.className += ' line-numbers';
+	}
+
+	var match = env.code.match(/\n(?!$)/g);
+	var linesNum = match ? match.length + 1 : 1;
+	var lineNumbersWrapper;
+
+	var lines = new Array(linesNum + 1);
+	lines = lines.join('');
+
+	lineNumbersWrapper = document.createElement('span');
+	lineNumbersWrapper.setAttribute('aria-hidden', 'true');
+	lineNumbersWrapper.className = 'line-numbers-rows';
+	lineNumbersWrapper.innerHTML = lines;
+
+	if (pre.hasAttribute('data-start')) {
+		pre.style.counterReset = 'linenumber ' + (parseInt(pre.getAttribute('data-start'), 10) - 1);
+	}
+
+	env.element.appendChild(lineNumbersWrapper);
+
+});
+
+}());
+  })();
+});
+
+require.register("prismjs/plugins/normalize-whitespace/prism-normalize-whitespace.js", function(exports, require, module) {
+  require = __makeRelativeRequire(require, {}, "prismjs");
+  (function() {
+    (function() {
+
+if (typeof self === 'undefined' || !self.Prism || !self.document) {
+	return;
+}
+
+var assign = Object.assign || function (obj1, obj2) {
+	for (var name in obj2) {
+		if (obj2.hasOwnProperty(name))
+			obj1[name] = obj2[name];
+	}
+	return obj1;
+}
+
+function NormalizeWhitespace(defaults) {
+	this.defaults = assign({}, defaults);
+}
+
+function toCamelCase(value) {
+	return value.replace(/-(\w)/g, function(match, firstChar) {
+		return firstChar.toUpperCase();
+	});
+}
+
+function tabLen(str) {
+	var res = 0;
+	for (var i = 0; i < str.length; ++i) {
+		if (str.charCodeAt(i) == '\t'.charCodeAt(0))
+			res += 3;
+	}
+	return str.length + res;
+}
+
+NormalizeWhitespace.prototype = {
+	setDefaults: function (defaults) {
+		this.defaults = assign(this.defaults, defaults);
+	},
+	normalize: function (input, settings) {
+		settings = assign(this.defaults, settings);
+
+		for (var name in settings) {
+			var methodName = toCamelCase(name);
+			if (name !== "normalize" && methodName !== 'setDefaults' &&
+					settings[name] && this[methodName]) {
+				input = this[methodName].call(this, input, settings[name]);
+			}
+		}
+
+		return input;
+	},
+
+	/*
+	 * Normalization methods
+	 */
+	leftTrim: function (input) {
+		return input.replace(/^\s+/, '');
+	},
+	rightTrim: function (input) {
+		return input.replace(/\s+$/, '');
+	},
+	tabsToSpaces: function (input, spaces) {
+		spaces = spaces|0 || 4;
+		return input.replace(/\t/g, new Array(++spaces).join(' '));
+	},
+	spacesToTabs: function (input, spaces) {
+		spaces = spaces|0 || 4;
+		return input.replace(new RegExp(' {' + spaces + '}', 'g'), '\t');
+	},
+	removeTrailing: function (input) {
+		return input.replace(/\s*?$/gm, '');
+	},
+	// Support for deprecated plugin remove-initial-line-feed
+	removeInitialLineFeed: function (input) {
+		return input.replace(/^(?:\r?\n|\r)/, '');
+	},
+	removeIndent: function (input) {
+		var indents = input.match(/^[^\S\n\r]*(?=\S)/gm);
+
+		if (!indents || !indents[0].length)
+			return input;
+
+		indents.sort(function(a, b){return a.length - b.length; });
+
+		if (!indents[0].length)
+			return input;
+
+		return input.replace(new RegExp('^' + indents[0], 'gm'), '');
+	},
+	indent: function (input, tabs) {
+		return input.replace(/^[^\S\n\r]*(?=\S)/gm, new Array(++tabs).join('\t') + '$&');
+	},
+	breakLines: function (input, characters) {
+		characters = (characters === true) ? 80 : characters|0 || 80;
+
+		var lines = input.split('\n');
+		for (var i = 0; i < lines.length; ++i) {
+			if (tabLen(lines[i]) <= characters)
+				continue;
+
+			var line = lines[i].split(/(\s+)/g),
+			    len = 0;
+
+			for (var j = 0; j < line.length; ++j) {
+				var tl = tabLen(line[j]);
+				len += tl;
+				if (len > characters) {
+					line[j] = '\n' + line[j];
+					len = tl;
+				}
+			}
+			lines[i] = line.join('');
+		}
+		return lines.join('\n');
+	}
+};
+
+Prism.plugins.NormalizeWhitespace = new NormalizeWhitespace({
+	'remove-trailing': true,
+	'remove-indent': true,
+	'left-trim': true,
+	'right-trim': true,
+	/*'break-lines': 80,
+	'indent': 2,
+	'remove-initial-line-feed': false,
+	'tabs-to-spaces': 4,
+	'spaces-to-tabs': 4*/
+});
+
+Prism.hooks.add('before-sanity-check', function (env) {
+	var pre = env.element.parentNode;
+	var clsReg = /\bno-whitespace-normalization\b/;
+	if (!env.code || !pre || pre.nodeName.toLowerCase() !== 'pre' ||
+			(env.settings && env.settings['whitespace-normalization'] === false) ||
+			clsReg.test(pre.className) || clsReg.test(env.element.className))
+		return;
+
+	var children = pre.childNodes,
+	    before = '',
+	    after = '',
+	    codeFound = false,
+	    Normalizer = Prism.plugins.NormalizeWhitespace;
+
+	// Move surrounding whitespace from the 
 tag into the  tag
+	for (var i = 0; i < children.length; ++i) {
+		var node = children[i];
+
+		if (node == env.element) {
+			codeFound = true;
+		} else if (node.nodeName === "#text") {
+			if (codeFound) {
+				after += node.nodeValue;
+			} else {
+				before += node.nodeValue;
+			}
+
+			pre.removeChild(node);
+			--i;
+		}
+	}
+
+	if (!env.element.children.length || !Prism.plugins.KeepMarkup) {
+		env.code = before + env.code + after;
+		env.code = Normalizer.normalize(env.code, env.settings);
+	} else {
+		// Preserve markup for keep-markup plugin
+		var html = before + env.element.innerHTML + after;
+		env.element.innerHTML = Normalizer.normalize(html, env.settings);
+		env.code = env.element.textContent;
+	}
+});
+
+}());
+  })();
+});
+
+require.register("prismjs/prism.js", function(exports, require, module) {
+  require = __makeRelativeRequire(require, {}, "prismjs");
+  (function() {
+    /* **********************************************
+     Begin prism-core.js
+********************************************** */
+
+var _self = (typeof window !== 'undefined')
+	? window   // if in browser
+	: (
+		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+		? self // if in worker
+		: {}   // if in node js
+	);
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou http://lea.verou.me
+ */
+
+var Prism = (function(){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-(\w+)\b/i;
+var uniqueId = 0;
+
+var _ = _self.Prism = {
+	util: {
+		encode: function (tokens) {
+			if (tokens instanceof Token) {
+				return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+			} else if (_.util.type(tokens) === 'Array') {
+				return tokens.map(_.util.encode);
+			} else {
+				return tokens.replace(/&/g, '&').replace(/ text.length) {
+						// Something went terribly wrong, ABORT, ABORT!
+						break tokenloop;
+					}
+
+					if (str instanceof Token) {
+						continue;
+					}
+
+					pattern.lastIndex = 0;
+
+					var match = pattern.exec(str),
+					    delNum = 1;
+
+					// Greedy patterns can override/remove up to two previously matched tokens
+					if (!match && greedy && i != strarr.length - 1) {
+						pattern.lastIndex = pos;
+						match = pattern.exec(text);
+						if (!match) {
+							break;
+						}
+
+						var from = match.index + (lookbehind ? match[1].length : 0),
+						    to = match.index + match[0].length,
+						    k = i,
+						    p = pos;
+
+						for (var len = strarr.length; k < len && p < to; ++k) {
+							p += strarr[k].length;
+							// Move the index i to the element in strarr that is closest to from
+							if (from >= p) {
+								++i;
+								pos = p;
+							}
+						}
+
+						/*
+						 * If strarr[i] is a Token, then the match starts inside another Token, which is invalid
+						 * If strarr[k - 1] is greedy we are in conflict with another greedy pattern
+						 */
+						if (strarr[i] instanceof Token || strarr[k - 1].greedy) {
+							continue;
+						}
+
+						// Number of tokens to delete and replace with the new match
+						delNum = k - i;
+						str = text.slice(pos, p);
+						match.index -= pos;
+					}
+
+					if (!match) {
+						continue;
+					}
+
+					if(lookbehind) {
+						lookbehindLength = match[1].length;
+					}
+
+					var from = match.index + lookbehindLength,
+					    match = match[0].slice(lookbehindLength),
+					    to = from + match.length,
+					    before = str.slice(0, from),
+					    after = str.slice(to);
+
+					var args = [i, delNum];
+
+					if (before) {
+						args.push(before);
+					}
+
+					var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias, match, greedy);
+
+					args.push(wrapped);
+
+					if (after) {
+						args.push(after);
+					}
+
+					Array.prototype.splice.apply(strarr, args);
+				}
+			}
+		}
+
+		return strarr;
+	},
+
+	hooks: {
+		all: {},
+
+		add: function (name, callback) {
+			var hooks = _.hooks.all;
+
+			hooks[name] = hooks[name] || [];
+
+			hooks[name].push(callback);
+		},
+
+		run: function (name, env) {
+			var callbacks = _.hooks.all[name];
+
+			if (!callbacks || !callbacks.length) {
+				return;
+			}
+
+			for (var i=0, callback; callback = callbacks[i++];) {
+				callback(env);
+			}
+		}
+	}
+};
+
+var Token = _.Token = function(type, content, alias, matchedStr, greedy) {
+	this.type = type;
+	this.content = content;
+	this.alias = alias;
+	// Copy of the full string this token was created from
+	this.length = (matchedStr || "").length|0;
+	this.greedy = !!greedy;
+};
+
+Token.stringify = function(o, language, parent) {
+	if (typeof o == 'string') {
+		return o;
+	}
+
+	if (_.util.type(o) === 'Array') {
+		return o.map(function(element) {
+			return Token.stringify(element, language, o);
+		}).join('');
+	}
+
+	var env = {
+		type: o.type,
+		content: Token.stringify(o.content, language, parent),
+		tag: 'span',
+		classes: ['token', o.type],
+		attributes: {},
+		language: language,
+		parent: parent
+	};
+
+	if (env.type == 'comment') {
+		env.attributes['spellcheck'] = 'true';
+	}
+
+	if (o.alias) {
+		var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
+		Array.prototype.push.apply(env.classes, aliases);
+	}
+
+	_.hooks.run('wrap', env);
+
+	var attributes = Object.keys(env.attributes).map(function(name) {
+		return name + '="' + (env.attributes[name] || '').replace(/"/g, '"') + '"';
+	}).join(' ');
+
+	return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '';
+
+};
+
+if (!_self.document) {
+	if (!_self.addEventListener) {
+		// in Node.js
+		return _self.Prism;
+	}
+ 	// In worker
+	_self.addEventListener('message', function(evt) {
+		var message = JSON.parse(evt.data),
+		    lang = message.language,
+		    code = message.code,
+		    immediateClose = message.immediateClose;
+
+		_self.postMessage(_.highlight(code, _.languages[lang], lang));
+		if (immediateClose) {
+			_self.close();
+		}
+	}, false);
+
+	return _self.Prism;
+}
+
+//Get current script and highlight
+var script = document.currentScript || [].slice.call(document.getElementsByTagName("script")).pop();
+
+if (script) {
+	_.filename = script.src;
+
+	if (document.addEventListener && !script.hasAttribute('data-manual')) {
+		if(document.readyState !== "loading") {
+			if (window.requestAnimationFrame) {
+				window.requestAnimationFrame(_.highlightAll);
+			} else {
+				window.setTimeout(_.highlightAll, 16);
+			}
+		}
+		else {
+			document.addEventListener('DOMContentLoaded', _.highlightAll);
+		}
+	}
+}
+
+return _self.Prism;
+
+})();
+
+if (typeof module !== 'undefined' && module.exports) {
+	module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+	global.Prism = Prism;
+}
+
+
+/* **********************************************
+     Begin prism-markup.js
+********************************************** */
+
+Prism.languages.markup = {
+	'comment': //,
+	'prolog': /<\?[\w\W]+?\?>/,
+	'doctype': //i,
+	'cdata': //i,
+	'tag': {
+		pattern: /<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+		inside: {
+			'tag': {
+				pattern: /^<\/?[^\s>\/]+/i,
+				inside: {
+					'punctuation': /^<\/?/,
+					'namespace': /^[^\s>\/:]+:/
+				}
+			},
+			'attr-value': {
+				pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,
+				inside: {
+					'punctuation': /[=>"']/
+				}
+			},
+			'punctuation': /\/?>/,
+			'attr-name': {
+				pattern: /[^\s>\/]+/,
+				inside: {
+					'namespace': /^[^\s>\/:]+:/
+				}
+			}
+
+		}
+	},
+	'entity': /&#?[\da-z]{1,8};/i
+};
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function(env) {
+
+	if (env.type === 'entity') {
+		env.attributes['title'] = env.content.replace(/&/, '&');
+	}
+});
+
+Prism.languages.xml = Prism.languages.markup;
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+
+/* **********************************************
+     Begin prism-css.js
+********************************************** */
+
+Prism.languages.css = {
+	'comment': /\/\*[\w\W]*?\*\//,
+	'atrule': {
+		pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i,
+		inside: {
+			'rule': /@[\w-]+/
+			// See rest below
+		}
+	},
+	'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
+	'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
+	'string': {
+		pattern: /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,
+		greedy: true
+	},
+	'property': /(\b|\B)[\w-]+(?=\s*:)/i,
+	'important': /\B!important\b/i,
+	'function': /[-a-z0-9]+(?=\()/i,
+	'punctuation': /[(){};:]/
+};
+
+Prism.languages.css['atrule'].inside.rest = Prism.util.clone(Prism.languages.css);
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'style': {
+			pattern: /()[\w\W]*?(?=<\/style>)/i,
+			lookbehind: true,
+			inside: Prism.languages.css,
+			alias: 'language-css'
+		}
+	});
+	
+	Prism.languages.insertBefore('inside', 'attr-value', {
+		'style-attr': {
+			pattern: /\s*style=("|').*?\1/i,
+			inside: {
+				'attr-name': {
+					pattern: /^\s*style/i,
+					inside: Prism.languages.markup.tag.inside
+				},
+				'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+				'attr-value': {
+					pattern: /.+/i,
+					inside: Prism.languages.css
+				}
+			},
+			alias: 'language-css'
+		}
+	}, Prism.languages.markup.tag);
+}
+
+/* **********************************************
+     Begin prism-clike.js
+********************************************** */
+
+Prism.languages.clike = {
+	'comment': [
+		{
+			pattern: /(^|[^\\])\/\*[\w\W]*?\*\//,
+			lookbehind: true
+		},
+		{
+			pattern: /(^|[^\\:])\/\/.*/,
+			lookbehind: true
+		}
+	],
+	'string': {
+		pattern: /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+		greedy: true
+	},
+	'class-name': {
+		pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,
+		lookbehind: true,
+		inside: {
+			punctuation: /(\.|\\)/
+		}
+	},
+	'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
+	'boolean': /\b(true|false)\b/,
+	'function': /[a-z0-9_]+(?=\()/i,
+	'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,
+	'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+	'punctuation': /[{}[\];(),.:]/
+};
+
+
+/* **********************************************
+     Begin prism-javascript.js
+********************************************** */
+
+Prism.languages.javascript = Prism.languages.extend('clike', {
+	'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
+	'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
+	// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
+	'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,
+	'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/
+});
+
+Prism.languages.insertBefore('javascript', 'keyword', {
+	'regex': {
+		pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,
+		lookbehind: true,
+		greedy: true
+	}
+});
+
+Prism.languages.insertBefore('javascript', 'string', {
+	'template-string': {
+		pattern: /`(?:\\\\|\\?[^\\])*?`/,
+		greedy: true,
+		inside: {
+			'interpolation': {
+				pattern: /\$\{[^}]+\}/,
+				inside: {
+					'interpolation-punctuation': {
+						pattern: /^\$\{|\}$/,
+						alias: 'punctuation'
+					},
+					rest: Prism.languages.javascript
+				}
+			},
+			'string': /[\s\S]+/
+		}
+	}
+});
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'script': {
+			pattern: /()[\w\W]*?(?=<\/script>)/i,
+			lookbehind: true,
+			inside: Prism.languages.javascript,
+			alias: 'language-javascript'
+		}
+	});
+}
+
+Prism.languages.js = Prism.languages.javascript;
+
+/* **********************************************
+     Begin prism-file-highlight.js
+********************************************** */
+
+(function () {
+	if (typeof self === 'undefined' || !self.Prism || !self.document || !document.querySelector) {
+		return;
+	}
+
+	self.Prism.fileHighlight = function() {
+
+		var Extensions = {
+			'js': 'javascript',
+			'py': 'python',
+			'rb': 'ruby',
+			'ps1': 'powershell',
+			'psm1': 'powershell',
+			'sh': 'bash',
+			'bat': 'batch',
+			'h': 'c',
+			'tex': 'latex'
+		};
+
+		if(Array.prototype.forEach) { // Check to prevent error in IE8
+			Array.prototype.slice.call(document.querySelectorAll('pre[data-src]')).forEach(function (pre) {
+				var src = pre.getAttribute('data-src');
+
+				var language, parent = pre;
+				var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
+				while (parent && !lang.test(parent.className)) {
+					parent = parent.parentNode;
+				}
+
+				if (parent) {
+					language = (pre.className.match(lang) || [, ''])[1];
+				}
+
+				if (!language) {
+					var extension = (src.match(/\.(\w+)$/) || [, ''])[1];
+					language = Extensions[extension] || extension;
+				}
+
+				var code = document.createElement('code');
+				code.className = 'language-' + language;
+
+				pre.textContent = '';
+
+				code.textContent = 'Loading…';
+
+				pre.appendChild(code);
+
+				var xhr = new XMLHttpRequest();
+
+				xhr.open('GET', src, true);
+
+				xhr.onreadystatechange = function () {
+					if (xhr.readyState == 4) {
+
+						if (xhr.status < 400 && xhr.responseText) {
+							code.textContent = xhr.responseText;
+
+							Prism.highlightElement(code);
+						}
+						else if (xhr.status >= 400) {
+							code.textContent = '✖ Error ' + xhr.status + ' while fetching file: ' + xhr.statusText;
+						}
+						else {
+							code.textContent = '✖ Error: File does not exist or is empty';
+						}
+					}
+				};
+
+				xhr.send(null);
+			});
+		}
+
+	};
+
+	document.addEventListener('DOMContentLoaded', self.Prism.fileHighlight);
+
+})();
+  })();
+});
+
 require.register("process/browser.js", function(exports, require, module) {
   require = __makeRelativeRequire(require, {}, "process");
   (function() {
@@ -14453,6 +15751,10 @@ var _logger = require('./lib/logger');
 
 var _logger2 = _interopRequireDefault(_logger);
 
+var _highlight = require('./lib/highlight');
+
+var _highlight2 = _interopRequireDefault(_highlight);
+
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -14460,6 +15762,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
 window.$ = _jquery2.default;
 window.jQuery = _jquery2.default;
 
+
 require('admin-lte');
 
 var App = function () {
@@ -14471,6 +15774,7 @@ var App = function () {
     this.socket = this.initSocket();
     this.requestCountEl = (0, _jquery2.default)('#requests-count');
     this.requestsCount = parseInt(this.requestCountEl.text(), 10);
+    this.highlight = new _highlight2.default();
   }
 
   _createClass(App, [{
@@ -14480,6 +15784,7 @@ var App = function () {
       this.joinToolbarChannel(this.socket);
       (0, _jquery2.default)("#requests-history").on("click", "tr", this.onRequestClick);
       this.renderTooltips();
+      this.highlight.render("body");
     }
   }, {
     key: 'initSocket',
@@ -14543,6 +15848,60 @@ var opts = window.ExDebugToolbar || {};
 new App(opts).render();
 });
 
+require.register("web/static/js/lib/highlight.js", function(exports, require, module) {
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _prismjs = require('prismjs');
+
+var _prismjs2 = _interopRequireDefault(_prismjs);
+
+require('prismjs/components/prism-elixir');
+
+require('prismjs/components/prism-sql');
+
+require('prismjs/plugins/normalize-whitespace/prism-normalize-whitespace');
+
+require('prismjs/plugins/line-numbers/prism-line-numbers');
+
+require('prismjs/plugins/line-highlight/prism-line-highlight');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Highlight = function () {
+  function Highlight() {
+    _classCallCheck(this, Highlight);
+  }
+
+  _createClass(Highlight, [{
+    key: 'render',
+    value: function render(el) {
+      _prismjs2.default.plugins.NormalizeWhitespace.setDefaults({
+        'remove-trailing': true,
+        'remove-indent': true,
+        'left-trim': true,
+        'right-trim': true,
+        'remove-initial-line-feed': true
+      });
+      $(el).find(".code").each(function (i, el) {
+        _prismjs2.default.highlightElement(el, false);
+      });
+    }
+  }]);
+
+  return Highlight;
+}();
+
+exports.default = Highlight;
+});
+
 require.register("web/static/js/lib/jquery.js", function(exports, require, module) {
 'use strict';
 
@@ -14616,12 +15975,12 @@ var Logger = function () {
 exports.default = Logger;
 });
 
-require.alias("admin-lte/dist/js/adminlte.min.js", "admin-lte");
-require.alias("phoenix/priv/static/phoenix.js", "phoenix");
 require.alias("bootstrap-sass/assets/javascripts/bootstrap.js", "bootstrap-sass");
 require.alias("jquery/dist/jquery.js", "jquery");
 require.alias("process/browser.js", "process");
+require.alias("phoenix/priv/static/phoenix.js", "phoenix");
 require.alias("prismjs/prism.js", "prismjs");
+require.alias("admin-lte/dist/js/adminlte.min.js", "admin-lte");
 require.alias("xterm/lib/xterm.js", "xterm");
 require.alias("buffer/index.js", "buffer");process = require('process');require.register("___globals___", function(exports, require, module) {
   
diff --git a/priv/static/js/toolbar.js b/priv/static/js/toolbar.js
index ae4e3df..d8af200 100644
--- a/priv/static/js/toolbar.js
+++ b/priv/static/js/toolbar.js
@@ -22766,6 +22766,60 @@ module.exports = Terminal;
 //# sourceMappingURL=xterm.js.map
   })();
 });
+require.register("web/static/js/lib/highlight.js", function(exports, require, module) {
+'use strict';
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+var _prismjs = require('prismjs');
+
+var _prismjs2 = _interopRequireDefault(_prismjs);
+
+require('prismjs/components/prism-elixir');
+
+require('prismjs/components/prism-sql');
+
+require('prismjs/plugins/normalize-whitespace/prism-normalize-whitespace');
+
+require('prismjs/plugins/line-numbers/prism-line-numbers');
+
+require('prismjs/plugins/line-highlight/prism-line-highlight');
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+var Highlight = function () {
+  function Highlight() {
+    _classCallCheck(this, Highlight);
+  }
+
+  _createClass(Highlight, [{
+    key: 'render',
+    value: function render(el) {
+      _prismjs2.default.plugins.NormalizeWhitespace.setDefaults({
+        'remove-trailing': true,
+        'remove-indent': true,
+        'left-trim': true,
+        'right-trim': true,
+        'remove-initial-line-feed': true
+      });
+      $(el).find(".code").each(function (i, el) {
+        _prismjs2.default.highlightElement(el, false);
+      });
+    }
+  }]);
+
+  return Highlight;
+}();
+
+exports.default = Highlight;
+});
+
 require.register("web/static/js/lib/jquery.js", function(exports, require, module) {
 'use strict';
 
@@ -22862,19 +22916,9 @@ var _history_panel = require('./toolbar/history_panel');
 
 var _history_panel2 = _interopRequireDefault(_history_panel);
 
-var _prismjs = require('prismjs');
-
-var _prismjs2 = _interopRequireDefault(_prismjs);
-
-require('prismjs/components/prism-elixir');
-
-require('prismjs/components/prism-sql');
-
-require('prismjs/plugins/normalize-whitespace/prism-normalize-whitespace');
-
-require('prismjs/plugins/line-numbers/prism-line-numbers');
+var _highlight = require('./lib/highlight');
 
-require('prismjs/plugins/line-highlight/prism-line-highlight');
+var _highlight2 = _interopRequireDefault(_highlight);
 
 function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 
@@ -22891,6 +22935,7 @@ var App = function () {
     this.toolbar = (0, _jquery2.default)("
", { id: "ex-debug-toolbar" }); this.breakpointsPanel = new _breakpoints_panel2.default(this.socket, this.toolbar); this.historyPanel = new _history_panel2.default(this.toolbar, this.originalRequestId, this.render.bind(this)); + this.highlight = new _highlight2.default(); (0, _jquery2.default)("body").append(this.toolbar); } @@ -22948,7 +22993,7 @@ var App = function () { this.renderPopovers(this.toolbar); this.breakpointsPanel.render(uuid); this.historyPanel.render(uuid); - this.highlightCode(this.toolbar); + this.highlight.render(this.toolbar); } }, { key: 'renderPanels', @@ -23002,20 +23047,6 @@ var App = function () { } return panel.data('panel-id'); } - }, { - key: 'highlightCode', - value: function highlightCode(toolbar) { - _prismjs2.default.plugins.NormalizeWhitespace.setDefaults({ - 'remove-trailing': true, - 'remove-indent': true, - 'left-trim': true, - 'right-trim': true, - 'remove-initial-line-feed': true - }); - toolbar.find(".code").each(function (i, el) { - _prismjs2.default.highlightElement(el, false); - }); - } }, { key: 'renderPopovers', value: function renderPopovers(toolbar) { @@ -23239,12 +23270,12 @@ var HistoryPanel = function () { exports.default = HistoryPanel; }); -require.alias("admin-lte/dist/js/adminlte.min.js", "admin-lte"); -require.alias("phoenix/priv/static/phoenix.js", "phoenix"); require.alias("bootstrap-sass/assets/javascripts/bootstrap.js", "bootstrap-sass"); require.alias("jquery/dist/jquery.js", "jquery"); require.alias("process/browser.js", "process"); +require.alias("phoenix/priv/static/phoenix.js", "phoenix"); require.alias("prismjs/prism.js", "prismjs"); +require.alias("admin-lte/dist/js/adminlte.min.js", "admin-lte"); require.alias("xterm/lib/xterm.js", "xterm"); require.alias("buffer/index.js", "buffer");process = require('process');require.register("___globals___", function(exports, require, module) { diff --git a/web/static/css/dashboard.scss b/web/static/css/dashboard.scss index 8e1d325..d869e73 100644 --- a/web/static/css/dashboard.scss +++ b/web/static/css/dashboard.scss @@ -5,6 +5,10 @@ @import 'admin-lte/dist/css/AdminLTE'; @import 'admin-lte/dist/css/skins/skin-yellow'; +@import "prismjs/themes/prism"; +@import "prismjs/plugins/line-numbers/prism-line-numbers"; +@import "prismjs/plugins/line-highlight/prism-line-highlight"; + .invisible-row { display: none; } diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index 42e12fd..78110e7 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -3,6 +3,7 @@ import $ from './lib/jquery'; import Logger from './lib/logger'; window.$ = $; window.jQuery = $; +import Highlight from './lib/highlight'; require('admin-lte'); @@ -13,6 +14,7 @@ class App { this.socket = this.initSocket(); this.requestCountEl = $('#requests-count'); this.requestsCount = parseInt(this.requestCountEl.text(), 10); + this.highlight = new Highlight; } render() { @@ -20,6 +22,7 @@ class App { this.joinToolbarChannel(this.socket); $("#requests-history").on("click", "tr", this.onRequestClick); this.renderTooltips(); + this.highlight.render("body"); } initSocket() { diff --git a/web/static/js/lib/highlight.js b/web/static/js/lib/highlight.js new file mode 100644 index 0000000..b55d561 --- /dev/null +++ b/web/static/js/lib/highlight.js @@ -0,0 +1,23 @@ +import Prism from 'prismjs'; +import 'prismjs/components/prism-elixir'; +import 'prismjs/components/prism-sql'; +import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace'; +import 'prismjs/plugins/line-numbers/prism-line-numbers'; +import 'prismjs/plugins/line-highlight/prism-line-highlight'; + +class Highlight { + render(el) { + Prism.plugins.NormalizeWhitespace.setDefaults({ + 'remove-trailing': true, + 'remove-indent': true, + 'left-trim': true, + 'right-trim': true, + 'remove-initial-line-feed': true, + }); + $(el).find(".code").each((i, el) => { + Prism.highlightElement(el, false) + }) + } +} + +export default Highlight; diff --git a/web/static/js/toolbar.js b/web/static/js/toolbar.js index a0f28d3..2bac005 100644 --- a/web/static/js/toolbar.js +++ b/web/static/js/toolbar.js @@ -3,12 +3,7 @@ import $ from './lib/jquery'; import Logger from './lib/logger'; import BreakpointsPanel from './toolbar/breakpoints_panel'; import HistoryPanel from './toolbar/history_panel'; -import Prism from 'prismjs'; -import 'prismjs/components/prism-elixir'; -import 'prismjs/components/prism-sql'; -import 'prismjs/plugins/normalize-whitespace/prism-normalize-whitespace'; -import 'prismjs/plugins/line-numbers/prism-line-numbers'; -import 'prismjs/plugins/line-highlight/prism-line-highlight'; +import Highlight from './lib/highlight'; class App { constructor(opts) { @@ -19,6 +14,7 @@ class App { this.toolbar = $("
", {id: "ex-debug-toolbar"}); this.breakpointsPanel = new BreakpointsPanel(this.socket, this.toolbar); this.historyPanel = new HistoryPanel(this.toolbar, this.originalRequestId, this.render.bind(this)); + this.highlight = new Highlight; $("body").append(this.toolbar); } @@ -67,7 +63,7 @@ class App { this.renderPopovers(this.toolbar); this.breakpointsPanel.render(uuid); this.historyPanel.render(uuid); - this.highlightCode(this.toolbar); + this.highlight.render(this.toolbar); } renderPanels(toolbar) { @@ -119,19 +115,6 @@ class App { return panel.data('panel-id'); } - highlightCode(toolbar) { - Prism.plugins.NormalizeWhitespace.setDefaults({ - 'remove-trailing': true, - 'remove-indent': true, - 'left-trim': true, - 'right-trim': true, - 'remove-initial-line-feed': true, - }); - toolbar.find(".code").each((i, el) => { - Prism.highlightElement(el, false) - }) - } - renderPopovers(toolbar) { $(toolbar).find('[data-toggle="popover"]').popover(); } diff --git a/web/templates/dashboard/request/show/_overview.html.eex b/web/templates/dashboard/request/show/_overview.html.eex new file mode 100644 index 0000000..65b7dc1 --- /dev/null +++ b/web/templates/dashboard/request/show/_overview.html.eex @@ -0,0 +1,33 @@ +
+
+

Parameters

+

Route

+
+    
+      <%= inspect(@conn.path_params, limit: 200, pretty: true) %>
+    
+  
+

Query

+
+    
+      <%= inspect(@conn.query_params, limit: 200, pretty: true) %>
+    
+  
+

Assigns

+
+    
+      <%= inspect(@conn.assigns, limit: 200, pretty: true) %>
+    
+  
+
+
+
+
+
+

Parameters

+

+ test text +

+
+
+
diff --git a/web/templates/dashboard/request/show/_request.html.eex b/web/templates/dashboard/request/show/_request.html.eex index 6d2a9f6..cfe9019 100644 --- a/web/templates/dashboard/request/show/_request.html.eex +++ b/web/templates/dashboard/request/show/_request.html.eex @@ -40,46 +40,35 @@